/* * Morse Code Decoder and door opener * * Josh Myer * * 20091118 rev 1 -- cleaned up, made work a little better * 20090103 rev 0 -- ugly and unfortunate, but mostly functional (my first arduino code) * * Hook a debounced switch up to digital pin 2, like you would for the Button demo. * * This code reads morse code from digital02, turning it into ASCII characters. * If you key in "SOS" (... --- ...), it will turn on the LED on digital13. * * The intended application is to let me key in a password at my apartment's * front gate and have it automatically let me into the building, instead of * fumbling around for keys. * * There's still lots of stuff to do and clean up, but I wanted to share the idea * and the current implementation to help spur people on. */ #include #include int ledPin = 13; // choose the pin for the LED int inputPin = 2; // choose the input pin (for a pushbutton) int val = 0; // variable for reading the pin status #define DELAY_TIME 1 // ms #define NCHARS 26+10+3 char morse_chars[NCHARS] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.', ',', '?', }; char* morse_strings[NCHARS] = { ".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....", "..", ".---", "-.-", ".-..", "--", "-.", "---", ".--.", "--.-", ".-.", "...", "-", "..-", "...-", ".--", "-..-", "-.--", "--..", "-----", ".----", "..---", "...--", "....-", ".....", "-....", "--...", "---..", "----.", ".-.-.-", "--..--", "..--..", }; #define PAUSE 0 #define DIT 1 #define DAH 2 #define DDLEN 5 char passwd[] = "SOS"; #define CHARS_RX_LEN 10 char chars_rx[CHARS_RX_LEN]; int char_cursor= 0; int ditsdahs[DDLEN]; int dd_cursor = 0; void setup() { pinMode(ledPin, OUTPUT); // declare LED as output pinMode(inputPin, INPUT); // declare pushbutton as input for (int i = 0; i < DDLEN; i++) { ditsdahs[i] = 0; } dd_cursor = 0; for (int i = 0; i < 10; i++) { chars_rx[i] = 0; } char_cursor = 0; Serial.begin(9600); } void dd_print() { Serial.print(" > DD BUF: "); for(int i = 0; i < DDLEN; i++) { Serial.print(ditsdahs[i]); Serial.print(", "); } Serial.println(); } boolean dd_eq(char*buf) { if(ditsdahs[0] == PAUSE) return false; int i; for(i = 0; ditsdahs[i] != PAUSE && i < DDLEN; i++) { if (ditsdahs[i] == DIT && buf[i] == '-') { return false; } if (ditsdahs[i] == DAH && buf[i] == '.') { return false; } } /* Serial.print("Got to the end of "); Serial.print(buf); Serial.print("; checking strlen="); Serial.print(strlen(buf)); Serial.print(" == i="); Serial.println(i); */ if (i != strlen(buf)) return false; return true; } void dd_decode() { for(int i = 0; i < NCHARS; i++) { /* Serial.print("dd_decode: check i="); Serial.print(i); Serial.print(" , string=\""); Serial.print(morse_strings[i]); Serial.print("\", c="); Serial.print(morse_chars[i]); Serial.println(); */ if (dd_eq(morse_strings[i])) { char c = morse_chars[i]; char_emit(c); break; } } for (int i = 0; i < DDLEN; i++) { ditsdahs[i] = 0; } dd_cursor = 0; } void check_passwd() { Serial.print("Check password: "); Serial.print(chars_rx); Serial.println(); if (0 != strstr(chars_rx, passwd)) { digitalWrite(ledPin, HIGH); } /* for (int i = 0; i < 10; i++) { chars_rx[i] = 0; } char_cursor = 0; */ } void char_emit(char c) { Serial.print("Got a char: c="); Serial.println(c); chars_rx[char_cursor] = c; char_cursor = (char_cursor + 1) % CHARS_RX_LEN; if (char_cursor >= strlen(passwd)) { check_passwd(); } if (char_cursor == 0) { for (int i = 0; i < CHARS_RX_LEN; i++) { chars_rx[i] = 0; } } } void dd_emit(int v) { ditsdahs[dd_cursor] = v; dd_cursor++; dd_print(); if (v == PAUSE) dd_decode(); } void dit() { dd_emit(DIT); Serial.println("DIT"); } void dah() { dd_emit(DAH); Serial.println("DAH"); } void pause() { dd_emit(PAUSE); Serial.println("PAUSE"); } #define DEBOUNCE_LEN 100 #define DIT_LENGTH 2 #define DAH_LENGTH 5 #define PAUSE_LENGTH 20 #define THRESHOLD 30 int n_since_zero = 0; int n_in_zero = 0; int n_low = 0; int n_high = 0; int last_state = 0; #define SAMPLE_SIZE 20 // 20ms void loop(){ val = digitalRead(inputPin); // read input value if (val == LOW) { n_low++; } else { n_high++; } if (n_low + n_high > SAMPLE_SIZE) { int cur_state = n_low >= n_high ? LOW : HIGH; n_low = n_high = 0; //digitalWrite(ledPin, cur_state); if (cur_state == last_state) { if (cur_state == LOW) n_in_zero++; if (cur_state == HIGH) n_since_zero++; if (n_since_zero == PAUSE_LENGTH) { // attempt a decode, reset state Serial.println("NEED TO DECODE"); pause(); } } else { if (cur_state == LOW) { // falling edge: button depressed n_since_zero = 0; n_in_zero = 1; } else { // rising edge: button released Serial.print("let up, depress len="); Serial.print(n_in_zero); if (n_in_zero < DIT_LENGTH) { Serial.println(" => Noisy depress, ignoring: "); } else if (n_in_zero < DAH_LENGTH) { Serial.println(" => DIT"); dit(); } else if (n_in_zero < PAUSE_LENGTH) { Serial.println(" => DAH"); dah(); } else { Serial.println(" => Noisy depress, ignoring: "); } n_since_zero = 1; n_in_zero = 0; } last_state = cur_state; } } delay(DELAY_TIME); }