/* Copyright 2010, 2011 Ethan Blanton */ /* This example blinks P1.0 in morse code, sending the message in the * variable 'str' in main(). */ #include #include #define MORSE_NONE 0x01 #define DELAY_DIT 0x5555 #define DELAY_DAH 0xFFFF /* Each byte is prefixed with a variable number of zero bits and a * single 1, followed by the morse code representation of the * character where 0 = dit and 1 = dah. For example, the character * e is 0b0000 0010; that is, six prefix 0s, a 1 to indicate the * beginning of the character, and a single 0 represinting the dit. * The table is in ASCII order, so indexing a character into the * table directly yields its morse representation. The character * set is incomplete. (Notably, some symbols and all prosigns are * missing.) Missing characters cause a dah-length inter-character * delay with no intervening symbols. */ const unsigned char morse_ascii[] = { MORSE_NONE, MORSE_NONE, MORSE_NONE, MORSE_NONE, MORSE_NONE, MORSE_NONE, MORSE_NONE, MORSE_NONE, MORSE_NONE, MORSE_NONE, MORSE_NONE, MORSE_NONE, MORSE_NONE, MORSE_NONE, MORSE_NONE, MORSE_NONE, MORSE_NONE, MORSE_NONE, MORSE_NONE, MORSE_NONE, MORSE_NONE, MORSE_NONE, MORSE_NONE, MORSE_NONE, MORSE_NONE, MORSE_NONE, MORSE_NONE, MORSE_NONE, MORSE_NONE, MORSE_NONE, MORSE_NONE, MORSE_NONE, MORSE_NONE, MORSE_NONE, MORSE_NONE, MORSE_NONE, MORSE_NONE, MORSE_NONE, MORSE_NONE, MORSE_NONE, MORSE_NONE, MORSE_NONE, MORSE_NONE, MORSE_NONE, 0x73, MORSE_NONE, 0x55, 0x32, /* , _ . / */ 0x3F, 0x2F, 0x27, 0x23, /* 0 1 2 3 */ 0x21, 0x20, 0x30, 0x38, /* 4 5 6 7 */ 0x3C, 0x37, MORSE_NONE, MORSE_NONE, /* 8 9 _ _ */ MORSE_NONE, 0x31, MORSE_NONE, 0x4C, /* _ = _ ? */ MORSE_NONE, 0x05, 0x18, 0x1A, /* _ A B C */ 0x0C, 0x02, 0x12, 0x0E, /* D E F G */ 0x10, 0x04, 0x17, 0x0D, /* H I J K */ 0x14, 0x07, 0x06, 0x0F, /* L M N O */ 0x16, 0x1D, 0x0A, 0x08, /* P Q R S */ 0x03, 0x09, 0x11, 0x0B, /* T U V W */ 0x19, 0x1B, 0x1C, MORSE_NONE, /* X Y Z _ */ MORSE_NONE, MORSE_NONE, MORSE_NONE, MORSE_NONE, MORSE_NONE, 0x05, 0x18, 0x1A, /* _ A B C */ 0x0C, 0x02, 0x12, 0x0E, /* D E F G */ 0x10, 0x04, 0x17, 0x0D, /* H I J K */ 0x14, 0x07, 0x06, 0x0F, /* L M N O */ 0x16, 0x1D, 0x0A, 0x08, /* P Q R S */ 0x03, 0x09, 0x11, 0x0B, /* T U V W */ 0x19, 0x1B, 0x1C, MORSE_NONE, /* X Y Z _ */ MORSE_NONE, MORSE_NONE, MORSE_NONE, MORSE_NONE, }; /* This delays for roughly four cycles per iteration, plus a * couple of cycles of overhead. (See the compiler-generated code * to determine exactly how many cycles per iteration!) */ void delay(unsigned int d) { for (; d > 0; d--) { nop(); nop(); } } int main(void) { /* It is important that this string be some immutable data type, to * prevent the compiler from copying it to RAM. const char str[] is * *not* treated as immutable, and leads to the compiler a) using a * pile of RAM for the string, and b) inserting a 266-byte (!) * memcpy implementation in the binary in ROM. */ const char *str = "hello de KB8OJH"; unsigned int i; WDTCTL = WDTPW | WDTHOLD; P1DIR = 0x1; /* Loop forever */ while (1) { /* Send the string in str as morse code */ for (i = 0; str[i]; i++) { int inchar = 0; /* Indicates whether we are in the prefix * padding or the character itself. */ unsigned int j; for (j = 0; j < 8; j++) { /* The following lookup yields true for dah and false * for dit at each position */ int bit = morse_ascii[(int)str[i]] & (0x80 >> j); if (inchar) { /* Set the output pin, delay for dit or dah * period according to bit, then unset the * output pin. */ P1OUT = 1; delay(bit ? DELAY_DAH : DELAY_DIT); P1OUT = 0; if (j < 7) { /* If we're not yet to the end of the character, * delay one dit period for intra-char delay */ delay(DELAY_DIT); } } else if (bit) { /* This is the end of the padding, set inchar * and iterate. */ inchar = 1; } } delay(DELAY_DAH); /* Inter-character delay. */ } /* Delay two more dahs at the end of the string, before we * repeat. */ delay(DELAY_DAH); delay(DELAY_DAH); } }