/* The guts of a morse code tutorial/training/transmission system. Set length variables to control speed and spacing. Written for Lattice C. Note short is 16 bits, int == long is 32 bits. */ #include /* Constants for Giaccess */ #define TRUE 1 #define FALSE 0 #define NO_ADDR 0x0L #define GI_WRITE 0x80 #define GI_READ 0 #define CHANA_LO 0 #define CHANA_HI 1 #define CHAN_ENABLE 7 #define CHANA_VOLUME 8 #define PORT_MASK 0xC0 /* Don't disturb i/o port bits */ #define GI_STATE 0x3E /* Tone ch A on; others off */ #define OFF 0 /* Event flags, etc */ short ev_mwhich = 0, ev_mflags = MU_KEYBD | MU_BUTTON | MU_TIMER, ev_mbclicks = 2, ev_mbmask = 2, ev_mbstate = 2, ev_mm1flags = 0, ev_mm1x = 0, ev_mm1y = 0, ev_mm1width = 0, ev_mm1height = 0, ev_mm2flags = 0, ev_mm2x = 0, ev_mm2y = 0, ev_mm2width = 0, ev_mm2height = 0, ev_mmox, ev_mmoy, ev_mmobutton, ev_mmokstate, ev_mkreturn, ev_mbreturn; char ev_mmgpbuff[16]; /* Sound parameters */ unsigned char a_volume = 15, a_hi_note = 1, a_lo_note = 0; /* Initial values are for 5 WPM */ short l_dot = 240, /* 1200/WPM */ l_dash = 720, /* 3*l_dot */ l_el = 240, /* Interelement spacing == l_dot */ l_char = 480, /* Char spacing, normally 2*l_el */ l_word = 960; /* Word spacing, 4*l_dot */ /* Note that the routine actually sends l_el after each element, l_char after each character, and l_word for a space, so the character space is l_el+l_char == 3*l_el, and word space is l_el+l_char+l_word == 7*l_el, agreeing with the standards */ /* Coding table: '.' = send dit; '_' = send dah; ' ' = word space; anything else (ie, '\0') terminates sequence. */ #define NO_CODE "\0" char *codes[128] = { NO_CODE, /* 00 */ NO_CODE, /* 01 */ NO_CODE, /* 02 */ NO_CODE, /* 03 */ NO_CODE, /* 04 */ NO_CODE, /* 05 */ NO_CODE, /* 06 */ NO_CODE, /* 07 */ NO_CODE, /* 08 */ " ", /* 09 TAB */ " ", /* 0A \N */ NO_CODE, /* 0B */ NO_CODE, /* 0C */ NO_CODE, /* 0D */ NO_CODE, /* 0E */ NO_CODE, /* 0F */ NO_CODE, /* 10 */ NO_CODE, /* 11 */ NO_CODE, /* 12 */ NO_CODE, /* 13 */ NO_CODE, /* 14 */ NO_CODE, /* 15 */ NO_CODE, /* 16 */ NO_CODE, /* 17 */ NO_CODE, /* 18 */ NO_CODE, /* 19 */ NO_CODE, /* 1A */ NO_CODE, /* 1B */ NO_CODE, /* 1C */ NO_CODE, /* 1D */ NO_CODE, /* 1E */ NO_CODE, /* 1F */ " ", /* 20 SPACE */ "..._.", /* 21 ! Understood */ "._.._.", /* 22 " */ "._._..", /* 23 # Paragraph */ "..._.._", /* 24 $ Dollar sign */ "_._._", /* 25 % Start/Attention */ "._...", /* 26 & Wait */ ".____.", /* 27 ' */ "_.__.", /* 28 ( */ "_.__._", /* 29 ) */ "..._._", /* 2A * End of Work */ "._._.", /* 2B + End of Message */ "__..__", /* 2C , */ "_..._", /* 2D - */ "._._._", /* 2E . */ "_.._.", /* 2F / */ "_____", /* 30 0 */ ".____", /* 31 1 */ "..___", /* 32 2 */ "...__", /* 33 3 */ "...._", /* 34 4 */ ".....", /* 35 5 */ "_....", /* 36 6 */ "__...", /* 37 7 */ "___..", /* 38 8 */ "____.", /* 39 9 */ "___...", /* 3A : */ "_._._.", /* 3B ; */ NO_CODE, /* 3C < */ "_..._", /* 3D = Double dash */ "._._", /* 3E > Newline */ "..__..", /* 3F ? */ NO_CODE, /* 40 @ */ "._", /* 41 A */ "_...", /* 42 B */ "_._.", /* 43 C */ "_..", /* 44 D */ ".", /* 45 E */ ".._.", /* 46 F */ "__.", /* 47 G */ "....", /* 48 H */ "..", /* 49 I */ ".___", /* 4A J */ "_._", /* 4B K */ "._..", /* 4C L */ "__", /* 4D M */ "_.", /* 4E N */ "___", /* 4F O */ ".__.", /* 50 P */ "__._", /* 51 Q */ "._.", /* 52 R */ "...", /* 53 S */ "_", /* 54 T */ ".._", /* 55 U */ "..._", /* 56 V */ ".__", /* 57 W */ "_.._", /* 58 X */ "_.__", /* 59 Y */ "__..", /* 5A Z */ NO_CODE, /* 5B [ (start prosign, see below) */ "........", /* 5C \\ Error */ NO_CODE, /* 5D ] (end prosign, see below) */ NO_CODE, /* 5E ^ */ "..__._", /* 5F _ */ NO_CODE, /* 60 ` */ "._", /* 61 a */ "_...", /* 62 b */ "_._.", /* 63 c */ "_..", /* 64 d */ ".", /* 65 e */ ".._.", /* 66 f */ "__.", /* 67 g */ "....", /* 68 h */ "..", /* 69 i */ ".___", /* 6A j */ "_._", /* 6B k */ "._..", /* 6C l */ "__", /* 6D m */ "_.", /* 6E n */ "___", /* 6F o */ ".__.", /* 70 p */ "__._", /* 71 q */ "._.", /* 72 r */ "...", /* 73 s */ "_", /* 74 t */ ".._", /* 75 u */ "..._", /* 76 v */ ".__", /* 77 w */ "_.._", /* 78 x */ "_.__", /* 79 y */ "__..", /* 7A z */ NO_CODE, /* 7B { */ NO_CODE, /* 7C | */ NO_CODE, /* 7D } */ NO_CODE, /* 7E ~ */ NO_CODE /* 7F */ }; /* send_morse: sends each character in the supplied string subject to the above translation table. Exception: '[' sets l_char :== 0 and ']' returns l_char to its original value. Thus prosigns can be composed (eg, [SK], [KN]) rather than using the equivalent punctuation given above. It is the sender's responsibility to see that the results are meaningful; send_morse will happily cram together anything, including [absolute garbage]. Note that end of string simulates ']' so prosigns cannot be broken into separate calls to send_morse. Also note that for multiple calls, str should start or end with a space character (' ', '\t', '\n') because the first character of a new str will be sent immediately, and only inter-character space is given following the last character of str */ short send_morse( str ) char *str; { short ll_char, i, len, j, els, m_send(), m_pause(); char ch, elem, *seq; unsigned char port_state=GI_STATE, new_state; /* Set sound chip */ port_state = (unsigned char) Giaccess( port_state, CHAN_ENABLE|GI_READ ); new_state = (port_state & PORT_MASK) | GI_STATE; Giaccess( new_state, CHAN_ENABLE|GI_WRITE ); Giaccess( OFF, CHANA_VOLUME|GI_WRITE ); Giaccess( a_hi_note, CHANA_HI|GI_WRITE ); Giaccess( a_lo_note, CHANA_LO|GI_WRITE ); ev_mkreturn = 0; ll_char = l_char; /* Actual inter-character space */ len = strlen( str ); for( i=0; i