Introduction

I hope you all know what Morse code is; for those who are not aware of it, Morse code is a standardized sequence of dots and dashes to represent any character and number. Well, in this article, I'm demonstrating a program that can control an LED connected to the parallel port of my computer and make it flash Morse code. For dots, the LED remains "on" for lesser time than dashes, thus giving an impression of Morse code. Not to forget the most interesting part: the program can use the webcam and a little bit of image processing to make the computer understand the Morse code flashing LED and convert it back to English.

Perhaps you are asking, "What's the use?" Well, no practical use.. but sometimes, coding is just fun. Ever since I made the webcam enabled Tic-Tac-Toe, I was thinking of some unique ways to communicate with my computer using something real and physical.. and ended up writing this program!

One really cool thing with this program would be using two computers, one having a parallel port (LED attached) and the other with a USB webcam. Watch this YouTube video and check out this program in action ..

Generating the Morse code (by flashing an LED)

As, you can see in the picture above, the program can control an LED connected to the parallel port of my computer and make it flash Morse code. All I have to do is enter a phrase in English and press the button. It also has an option for putting out the audio depicting Morse code.

First of all, a written text is converted to Morse code by a string extension, and finally, the generated Morse code is used to control the LED and audio part. Check the code snippet below:

Now, once the Morse code is generated, the program calls a function asynchronously in a different thread to make the LED flash the Morse without hanging the application. I'm using inpout32.dll to control the parallel port. You can find the complete details about importing and using this DLL in the article I recommended above. Below is a code snippet that uses the generated Morse code to flash the LED:

Webcam and image processing...

To add more fun, I added another feature of decoding this Morse code. The program watches the on/off sequence of the LED and converts it into English!

Earlier, I was thinking of processing the whole webcam frame and finding the on/ off state of the LED, but this technique made the application work too slow that it couldn't even differentiate between a dot and a dash. So, I made an assumption that the camera source will be stationery, and the user will have to define the light source by a mouse click within the webcam window (see the image below: the point of interception of the two yellow lines is the marker which defines the light source).

Once the light source is defined, the program can go through the pixels near the defined light source and calculate the average brightness of each pixel.

Wow, that's easy! This code was simple to write, and easy to understand. However, unfortunately, it is very slow. If you use this code, it might take several milliseconds to process, because the GetPixel()/SetPixel() methods are too slow for iterating through bitmaps. So, in this project, we'll make use of the BitmapData class in GDI+ to access the information we want. BitmapData only allows us to access the data it stores through a pointer. This means that we'll have to use the unsafe keyword to scope the block of code which accesses the data. Based on an article by Eric Gunnerson, here's a class which will perform a very quick unsafe image processing:

With the brightness value, the program can find whether the light source is "on" or "off", and with a stop watch, the timings of on/ off sequences could be calculated...

The program provides all the stats below the webcam view, and with these stats, it also predicts the Morse code! Make sure to watch the video above.

Some notes on using the software

Well, the most tricky part is adjusting the settings within the program to make it work perfectly.. Let's start with the settings one by one..

Here, "dot" defines the time span for which the LED will remain on for every dot within the Morse code, and "DMF", by default, is 3, which means the time span for every dash in the Morse code will be "dot" * 3.

Let's suppose we need to define " ._ " by flashing LEDs. How will we do that..?

LED on for "LESS time" --> LED off for "SOME time" --> LED on for "MORE time"

This LED off for "SOME time" is what "Imm" is in the above settings.

Now, let's come to the settings for the decoding part. I'll soon add some AI so that the program will adapt itself after collecting some on/off data. For now, let me tell you the significance of each setting:

For brightness less than the "Brightness Threshold", the light source will be considered "off". For best results, keep this setting only a little less than the brightness of the light source in "on" state. Similarly, you can play with other settings to get the best results. The program will provide all the statistics below the webcam window.

Conclusion

We have reached the end of this article, and I hope you enjoyed reading it. Now, here's some homework for you: try implementing features like AI for the program, and make this program self-adaptive according to its environment. Use your ideas, and if you end up doing something cool, I'd love to hear about it. Have fun!

I'm voting continuesly, because method GetMorseCode is very, repeating very silly processed. For example, you have not to test cases in all ifs, you should do char.ToString().ToUpper() and you have less code than before. And you should use 'switch', because is more usable.

A lot of people don't know this, but morse code was used to do the first version of signature capture (way back in the 1800's). It was decided that if someone were to bear witness to someone punching in their name in morse code, that this would constitute a legal signature.

People started implementing this when big decisions needed to be made and they couldn't wait for a letter to be sent.

I think this article is very good indeed. I believe I read that Morse Code was no longer officially used in communications anymore. Clearly, there's still an interest in it but is that because we're nostalgic or does it still play a part in the digital world? I'd be interested to hear where it might still be useful/used.

Great demonstration of disparate technologies in c#. I started looking for a morse audio to text because I live near a military base and pick up morse code on my telephone. I plan to modify your code and attempt to decode what is being said. Its probably training or "code" of some type but still, a fun project.

In addition to this comment, I'd like to suggest using the StringBuilder class instead of string concatenation. I may be wrong (I admittedly don't know much about the inner workings of .NET), but I believe I read somewhere that it's much more efficient to use
StringBuilder sb = new StringBuilder();
sb.Append("-.-. ");

The end result is the same, but there are performance implications of using string concatenation due to strings being immutable. StringBuilder uses magic to get around that. Use your favorite search engine and search for "StringBuilder vs. concatenation". I got a few good results:

Why not create an enum and just use that. Morse code only has three values (dot, dash, and space), so I would think it'd be best to use that and throw the converted values into a list. So, something like:

Indeed. It's all open to style and interpretation. Since Morse Code isn't changing any time soon and the enum ensures a strict set of values, I'd lend myself more towards it. Though, to each his own. Ultimately, its up to shivam_kalra to decide what he wants.

Ignoring the enum topic, using the values after they've been translated to dots/dashes immediately rather than storing them up would remove any need to worry about the performance of StringBuilders/Lists/etc. Then, you're only worrying about the performance of the two foreach loops .

Btw, I would also recommend using char.ToLower rather than testing both pairs of cases (ex. 'A' and 'a'). I'm sure the performance hit of ToLower is much less than the overhead of the additional 26 tests. Plus, it'd just make the code prettier.