Morse Code

Hello guys. I wrote a Morse Code class which takes a solenoid which powers our camera light, and a text to convert to Morse. It runs on a parallel thread and allows the camera to flash some fun and interesting messages.

Hope you like it,
Sasha

public class MorseCode implements Runnable{

	//To Call: (new Thread(new MorseCode("Hello World", caneraLight)).start();

	public static String sentance;
	public static String code];
	public static Solenoid cameraLight;
	public static boolean isDone;

	public MorseCode(String inputSentance, Solenoid light){
		code = new String[inputSentance.length()];
		sentance = inputSentance;
		cameraLight = light;
		convertToMorse();
		isDone = false;
	}
	public void run(){
		cameraLight.set(false);
		try {
			Thread.sleep(4200);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		for(int i = 0; i < code.length; i++){
			for(int j = 0; j < code*.length(); j++){
				if(code*.charAt(j) == '*'){
					cameraLight.set(true);
					try {
						Thread.sleep(600);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}else if(code*.charAt(j) == '-'){
					cameraLight.set(true);
					try {
						Thread.sleep(1800);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}else if(code*.charAt(j) == ' '){
					cameraLight.set(false);
					try {
						Thread.sleep(600);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}
			cameraLight.set(false);
			try {
				Thread.sleep(1800);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		isDone = true;
	}
	private void convertToMorse(){
		for(int i = 0; i < sentance.length(); i++){
			if(sentance.charAt(i)=='A' || sentance.charAt(i)=='a')
				code* = "* -";
			else if(sentance.charAt(i)=='B' || sentance.charAt(i)=='b')
				code* = "- * * *";
			else if(sentance.charAt(i)=='C' || sentance.charAt(i)=='c')
				code* = "- * - *";
			else if(sentance.charAt(i)=='D' || sentance.charAt(i)=='d')
				code* = "- * *";
			else if(sentance.charAt(i)=='E' || sentance.charAt(i)=='e')
				code* = "*";
			else if(sentance.charAt(i)=='F' || sentance.charAt(i)=='f')
				code* = "* * - *";
			else if(sentance.charAt(i)=='G' || sentance.charAt(i)=='g')
				code* = "- - *";
			else if(sentance.charAt(i)=='H' || sentance.charAt(i)=='h')
				code* = "* * * *";
			else if(sentance.charAt(i)=='I' || sentance.charAt(i)=='i')
				code* = "* *";
			else if(sentance.charAt(i)=='J' || sentance.charAt(i)=='j')
				code* = "* - - -";
			else if(sentance.charAt(i)=='K' || sentance.charAt(i)=='k')
				code* = "- * -";
			else if(sentance.charAt(i)=='L' || sentance.charAt(i)=='l')
				code* = "* - * *";
			else if(sentance.charAt(i)=='M' || sentance.charAt(i)=='m')
				code* = "- -";
			else if(sentance.charAt(i)=='N' || sentance.charAt(i)=='n')
				code* = "- *";
			else if(sentance.charAt(i)=='O' || sentance.charAt(i)=='o')
				code* = "- - -";
			else if(sentance.charAt(i)=='P' || sentance.charAt(i)=='p')
				code* = "* - - *";
			else if(sentance.charAt(i)=='Q' || sentance.charAt(i)=='q')
				code* = "- - * -";
			else if(sentance.charAt(i)=='R' || sentance.charAt(i)=='r')
				code* = "* - *";
			else if(sentance.charAt(i)=='S' || sentance.charAt(i)=='s')
				code* = "* * *";
			else if(sentance.charAt(i)=='T' || sentance.charAt(i)=='t')
				code* = "-";
			else if(sentance.charAt(i)=='U' || sentance.charAt(i)=='u')
				code* = "* * -";
			else if(sentance.charAt(i)=='V' || sentance.charAt(i)=='v')
				code* = "* * * -";
			else if(sentance.charAt(i)=='W' || sentance.charAt(i)=='w')
				code* = "* - -";
			else if(sentance.charAt(i)=='X' || sentance.charAt(i)=='x')
				code* = "- * * -";
			else if(sentance.charAt(i)=='Y' || sentance.charAt(i)=='y')
				code* = "- * - -";
			else if(sentance.charAt(i)=='Z' || sentance.charAt(i)=='z')
				code* = "- - * *";
			else if(sentance.charAt(i)=='0')
				code* = "- - - - -";
			else if(sentance.charAt(i)=='1')
				code* = "* - - - -";
			else if(sentance.charAt(i)=='2')
				code* = "* * - - -";
			else if(sentance.charAt(i)=='3')
				code* = "* * * - -";
			else if(sentance.charAt(i)=='4')
				code* = "* * * * -";
			else if(sentance.charAt(i)=='5')
				code* = "* * * * *";
			else if(sentance.charAt(i)=='6')
				code* = "- * * * *";
			else if(sentance.charAt(i)=='7')
				code* = "- - * * *";
			else if(sentance.charAt(i)=='8')
				code* = "- - - * *";
			else if(sentance.charAt(i)=='9')
				code* = "- - - - *";
			else
				code* = " ";
		}
	}
}

Veeeery eeeeenteresting.

No, really, That’s cool. Was it hard to do?

No not really. This was my first time using Java threading but it turns out its fairly easy to use.

The time consuming part was typing the Morse code database.

Talk about the ultimate status display. So long as your drivers know Code, they can get quite a lot of data off the robot.

(Yes, I know there are other ways, too)

Is using threads in Java as “risky” as it is in C++? By that I’m referencing this incident. I sort-of caught some heat from one of our mentors for attempting to show our new programmers how to use threads because there’s a lot of potential unintended coordination issues (even if the threads are basically acting as their own separate programme, like this one appears to be). Thanks, and this project seems really cool :slight_smile:

Threading is only “risky” if you don’t properly synchronize the data you’re sharing across the threads, and only if synchronization matters for the specific task. I wouldn’t say either language is necessarily more difficult to synchronize. In both, you need to think through your critical sections, make sure you’re locking mutexes, semaphores, etc. in the appropriate places.

Don’t show your code to your English teacher. You could be “sentanced” to remedial spelling assignments. :wink:

Is there a reason you used else if instead of a switch statement?

Great Job on the thread code.

Don’t be afraid of threads. They are a very basic mechanism in any real-time or embedded code development. I know Dave Wilner personally and was involved in the periphery of the Pathfinder problem.

The confusion came as a result of something called the priority inversion problem that is common in real-time systems. In VxWorks, there are 3 different kinds of semaphores that are used for different purposes. The one that’s used in the “CRITICAL_REGION/END_REGION” code is the mutual exclusion semaphore that caused the problems for Pathfinder. The problem with Pathfinder was that that semaphore was not created with the SEM_INVERSION_SAFE flag set. However, the constructor used in WPILib automatically set that flag, so you should be good.

Just make sure you protect any global variable accesses in the CRITICAL_REGION/END_REGION wrappers and everything should work fine.

Good Luck,

Mike