morse-2.4/0000755000000000000000000000000011576631014011206 5ustar rootrootmorse-2.4/morse.xml0000644000002700000270000002717511472771412011305 0ustar morse 1 January 2005 morse morse Education morse QSO Morse-code trainer and QSO generator for aspiring radio hams morse -i -I -r -n num -R num -N num -C charset -w num -f num -v num -g num -f num -e -c -b -a -l -m -t -T -s -q -p num -E num -M num -d -A -B -S -x num -X num word DESCRIPTION The morse program is a Morse-code trainer intended to help aspiring radio hams pass the 5-word-per-minute Element 1 test. It can take test text from a text file on standard input, or test words from its command-line arguments, or generate random text (-r) or play back what you type (-i). A helper program, QSO, generates plausible QSOs that can be fed to the standard input of morse. The following options control the behavior of morse: -i Play what you type. -I Like -i but don't turn off keyboard echoing. -r Generate random text. Starts out slanted towards easy letters, then slants towards ones you get wrong. -n NUM Make words (groups) NUM characters long. Valid values are between 1 and 20. -R NUM Set the total time (in minutes) to generate text. -N NUM (default 0 means unlimited) Set the total number of words (groups) to generate. -C 'STRING' (default all available characters) Select characters to send from this STRING only. -w words_per_minute -f frequency_in_hertz -v volume (zero to one, rather nonlinear) -g alternate_frequency (toggles via control-G in input FILE at a word break) -F Farnsworth_character_words_per_minute -e leave off the <SK> sound at the end -c complain about illegal characters instead of just ignoring them -b print each word before doing it -a print each word after doing it -l print each letter just before doing it -m print morse dots and dashes as they sound (this printing-intensive option slows the wpm down!) -t Type along with the morse, but don't see what you're typing (unless you make a mistake). You are allowed to get ahead as much as you want. If you get too far behind it will stop and resync with you. You can force it to resync at the next word end by hitting control-H. Hit ESC to see how you are doing, control-D to end. (The rightmost space in the printout marks where the average is. Farther left spaces separate off blocks of letters that are about twice as probable as the average to occur, three times, etc.) -T Like -t but see your characters (after they are played). -s Stop after each character and make sure you get it right. (implies -t) -q Quietly resyncs with your input (after you make a mistake). -p NUM Make you get it right NUM times, for penance. (implies -s). -E NUM If your count of wrong answers minus right answers for a given character exceeds this, the program will start prompting you. If above the maximum error prompt it will never prompt (implies -t). -M NUM If you get more than this number of characters behind, pause until you do your next letter. 1 behind is normal, 0 behind means never pause. This option mplies -t. -d Dynamically speed up or slow down depending on how you are doing. (if also-s, then -d only speeds up!) -A Add ISO 8859-1 (Latin-1) signs to test set. -B Add uncommon punctuation to test set. -S Add uncommon prosigns to test set. -X Set error volume. Error volume 0 means use console speaker. -x Set frequency of error tone. Here is the basic International Morse codest that the program will train you in: A .- N -. 1 .---- . .-.-.- B -... O --- 2 ..--- , --..-- C -.-. P .--. 3 ...-- ? ..--.. D -.. Q --.- 4 ....- ( -.--. E . R .-. 5 ..... - -....- F ..-. S ... 6 -.... G --. T - 7 --... H .... U ..- 8 ---.. I .. V ...- 9 ----. J .--- W .-- 0 ----- K -.- X -..- / -..-. L .-.. Y -.-- + .-.-. M -- Z --.. = -...- The following characters are included if one uses the -B option: ) -.--.- " .-..-. _ ..--.- ' .----. : ---... ; -.-.-. $ ...-..- ! -.-.-- @ .--.-. The following procedural signals (prosigns) are also included if one uses -B: <AR> "+" over, end of message <AS> "*" please stand by (<AS> 5 Wait 5 Minutes) (".-...") <BT> "=" (double dash) pause, break for text CL going off the air (clear) CQ calling any station K go, invite any station to transmit <KN> "(" go only, invite a specific station to transmit R all received OK <SK> "%" end of contact (sent before call) ("...-.-", known also as <VA>) The following less-used prosigns are included if one uses the -S option: <AA> "^" new line (".-.-", the same as :a, ae) <BK> "#" invite receiving station to transmit ("-...-.-") <KA> "&" attention ("-.-.-") <SN> "~" understood ("...-.") The following characters are included if one uses the -A option: :a .-.- (also for ae, the same as <AA>) `a .--.- (also oa, danish a with ring over it) ch ---- (bar-ch ?, bar-h ?, ISO 8859-1 code 199 and 231 ?) -d ..--. (eth, overstrike d with -, ISO 8859-1 code 208 and 240) `e ..-.. ~n --.-- :o ---. (also for oe) :u ..-- (also for ue) ]p .--.. (thorn, overstrike ] with p, ISO 8859-1 code 222 and 254) paragraph .-.-.. (ISO 8859-1 code 167 ?) For the raw beginner trying to learn morse code, we recommend the following sequence: Start learning the alphabet: morse -r -s -T -d -w 5 -F 15 -p 5 -E -10 Then drill drill drill: morse -r -s -T -d -w 5 -F 15 -p 5 -E 0 Real-time drill, with hints if you really need it: morse -r -T -d -w 5 -F 15 -M 2 -E 4 Simulated test: QSO | morse -e -T -d -w 5 -F 15 The dreaded random-letter test: morse -r -T -d -w 5 -F 15 Finally try for greater and greater speed: morse -r -T -d -w 13 -F 24 AUTHORS Joe Dellinger joe@montebello.soest.hawaii.edu. Updated 2005 by Eric S. Raymond esr@thyrsus.com. Updated 2010 by Thomas Horsten thomas@horsten.com. Other contributions by Jacek M. Holeczek and Marc Unangst. morse-2.4/HISTORY0000644000002700000270000000674111572366016010517 0ustar History of the "Morse Classic" trainer Neale Pickett , June 2011 (release 2.4): Add beep for ALSA Thomas Horsten , November 2010 (release 2.3): Fixed the -A, -B, and -S options (-B was always active, -A and -S had no effect). Only include prosigns if -B is specified, per the documentation. Added '@' character (.--.-.), in use if -B is enabled. Changed representation of prosign from '@' to '~' to accommodate '@'. Don't crash if char is signed and a negative value is sent. Thomas Horsten , October 2010 (release 2.2): Add beep for PulseAudio. Jay Maynard (K5ZC) , January 2005 (release 2.1): Mac OS X port patches. Eric S. Raymond , January 2005 (release 2.0): Accepted maintainer's baton from Joe Dellinger and Paul J. Drongowski. Dusted it off, cleaned it up to modern C standards. Changed ALLINTERNATIONAL to runtime -A option. Changed ALLPROSIGNS to runtime -S option. Changed ALLPUNCTUATION to runtime -B option. Changed ERROR_FREQUENCY to runtime -x option. Changed ERROR_VOLUME to runtime -X option. Dropped BSD signal and tty support, it's all POSIX now. QSO assumes that srand48/lrand48 is available, so morse will too. Wrote the manual page. Updated all code to use ANSI prototypes. Named it "Morse Classic" in recognition of its ancient BSD-Reno roots and to distinguish it from Alan Cox's morse program. Jacek M. Holeczek , March/April 2000: Fixed some source code files so that no warnings from -Wall appear. The character set made compatible with the International Morse Code. Added the -n NUM, -R NUM, -N NUM, -C 'STRING', -q options. Added beep for the AdLib/SoundBlaster FM chip and for the Open Sound System (OSS) /dev/dsp device. Note: The code uses directly ANSI sequences "\E[7m" to turn the inverse video mode on and "\E[0m" to turn all video attributes off. One should rewrite the openterminal function to provide the enter_standout_mode "smso/so" and exit_standout_mode "rmso/se" terminfo/termcap terminal string capabilities. Joe Dellinger , November 1994: Fixed a bug in the USG termio calls. Added an option to make the "error" beep come out via the beep routines instead of by printing a control-G. Joe Dellinger , April 1994: Finally got around to getting my license: WH6UR Marc Unangst (N8VRH), , December 1992: Added System V support. The program was originally written by Joe Dellinger at the Hawaii Institute of Geophysics (but he moved to Oklahoma in July 1994). * First alpha on Tue Aug 11 14:01:02 HST 1992 * Second alpha Thu Nov 26 03:24:19 HST 1992 * submitted to comp.sources.misc Dec 15 1993 * Revised version submitted to comp.sources.misc Nov 22 1994 Joe had this to say about the origin of the program: This code is (ridiculously) heavily modified from morse.c from the Reno UNIX distribution. I (Joe) also used slightly modified versions of a subroutine from Richard Ottolini at Unocal for Sun workstation tone generation. Scott Seligman at Stanford added support for other sorts of devices and made several other changes. John Shalamskas helped test and made comments. (Note that Sun support and the beeper code for most of these odd devices was long obsolete and has been removed.) morse-2.4/test_input0000644000002700000270000000015011455237613011540 0ustar Jocks find quartz glyph, vex BMW. testing, testing, 1 2 3  different tone now.  Back again. VVV VVV morse-2.4/morse.d/0000755000000000000000000000000011576631014012555 5ustar rootrootmorse-2.4/morse.d/alarm.c0000644000002700000270000000241611455237613012235 0ustar /* alarm.c -- wakeup calls */ /* -- Implementation of alarm.h */ #include #include #include #include #include static int alarmPending = 0; /* Nonzero when the alarm is set. */ static void ualarm(); static void AlarmHandler(); void AlarmSet(time) int time; { struct sigaction handler; alarmPending = 1; handler.sa_handler = AlarmHandler; sigemptyset(&handler.sa_mask); handler.sa_flags = 0; sigaction(SIGALRM, &handler, NULL); ualarm(1000 * time, 0); } /* -- If an alarm signal is lurking (due to a prior call to SetAlarm), then -- pause until it arrives. This procedure could have simply been written: -- if (alarmPending) pause(); -- but that allows a potential race condition. */ void AlarmWait() { sighold(SIGALRM); if (alarmPending) sigpause(SIGALRM); sigrelse(SIGALRM); } static void ualarm(us) unsigned us; { struct itimerval rttimer, old_rttimer; rttimer.it_value.tv_sec = us / 1000000; rttimer.it_value.tv_usec = us % 1000000; rttimer.it_interval.tv_sec = 0; rttimer.it_interval.tv_usec = 0; if (setitimer(ITIMER_REAL, &rttimer, &old_rttimer)) { perror("ualarm"); exit(1); } } static void AlarmHandler() { alarmPending = 0; } morse-2.4/morse.d/morse.c0000644000002700000270000014070511572365672012301 0ustar /* * Copyright (c) 1988 Regents of the University of California. * Copyright (c) 1992 Joe Dellinger, University of Hawaii at Manoa * Copyright (c) 2005 Eric S. Raymond. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * A morse code practice utility. (Contains those characters that can appear * on the FCC ham license exam.) * * Running "morse" without arguments or input gives self-doc. * * It doesn't keep PERFECT time, but it seems reasonably close * for reasonable word speeds on my slow SUN IPC! * * This program has a long history, see the HISTORY file for details. */ /* * Useful for seeing what the interleaved reading and writing loops are * really up to. * * #define DEBUG * * If you want to be overwhelmed with information about the probabilities * of each letter being chosen. * * #define DEBUGG */ #include #include #include #include #include #include #include #include #include "beep.h" #define FREQUENCY 800.0 #define FREQUENCY2 602.0 #define VOLUME 0.5 #define ERROR_VOLUME 0.5 #define WORDS_PER_MINUTE 20.0 #define MAX_BEHINDNESS 0 #define ERROR_FREQUENCY 2000.0 static int whichfrequ = 0; static float frequency1 = FREQUENCY; static float frequency2 = FREQUENCY2; static float frequency; static float volume = VOLUME; static float dot_time; static float dash_time; static float intra_char_time; static float inter_char_time; static float inter_word_time; static float catchup_time; static int showletters = 0; static int showmorse = 0; static int wordsbefore = 0; static int wordsafter = 0; static int fancyending = 1; static int noticebad = 0; static int testing = 0; static int showtesting = 0; static int keepquiet = 0; static int dynamicspeed = 0; static int charbychar = 0; static int international = 0; static int allprosigns = 0; static int allpunctuation = 0; static int tryagaincount = 1; static float words_per_minute = WORDS_PER_MINUTE; static float error_frequency = ERROR_FREQUENCY; static float error_volume = ERROR_VOLUME; static float fwords_per_minute; static int randomletters = 0; #define LETMESEE 2 static int typeaway = 0; static int totalhitcount = 0; static int totalmisscount = 0; static int helpmeflag = 0; #define MAXWORDLEN 20 #define TESTBUFSZ ((MAXWORDLEN+1)*10) static int wordlen = MAXWORDLEN; static int wordcount = -1; static time_t starttime; static int timeout = -1; static int testpointer = -1; static int testlength = 0; static int behindness = 0; static int max_behindness = MAX_BEHINDNESS; static char teststring[TESTBUFSZ]; static int yourpointer = -1; static int yourlength = 0; static char yourstring[TESTBUFSZ]; static int linepos = 0; static char *user_charset = NULL; /* * How many times can a given character not be asked before * kicking up the probability of asking that one by one randomfactor unit. */ #define RIPECOUNT 64 #define TWOFIFTYSIX 256 static char *(code[TWOFIFTYSIX]); static int errorlog[TWOFIFTYSIX]; static int randomfactor[TWOFIFTYSIX]; static int randomripe[TWOFIFTYSIX]; static int testterminal (void); static int randomletter (void); /* * Pointers to termcap/terminfo "smso/so" (enter_standout_mode) and "rmso/se" * (exit_standout_mode) terminal string capabilities (initialized respectively * with ANSI sequences "\E[7m" to turn the inverse video mode on and "\E[0m" * to turn all video attributes off). */ static const char *enter_standout_mode = "\033[7m"; static const char *exit_standout_mode = "\033[0m"; /* * Value of (Wrong - Right), which, if exceeded, will cause the program * to start prompting you. Above MAX_ERROR_THRESHOLD it will never prompt. * Don't let the user bank too much credit for past correct answers; * limit it by min(ERROR_FLOOR, error_threshold). */ #define MAX_ERROR_THRESHOLD 1000 #define ERROR_FLOOR -3 static int error_threshold = MAX_ERROR_THRESHOLD; static int error_floor = ERROR_FLOOR; /* * How many characters behind before it decides you're having * trouble keeping up. */ #define BEHIND 1 #define WAYBEHIND 3 #define TOOFARBEHIND 6 /* * If SLOWPOKE or more wpm ticks go by, then it decides you are having lots * of trouble remembering this character, and need to be asked it more * often. */ #define SLOWPOKE 10 /* You aren't slow -- you left and came back! */ #define SLOWPOKEMAX (50 * SLOWPOKE) /* * If FASTPOKE or less wpm ticks go by, then it decides you are good at this * character, and need to be asked it less often. */ #define FASTPOKE 4 /* * These control how quickly the dynamicspeed option acts when you are * fast or slow. Easier to slow down than speed up! */ #define ERRORSLOWER 1.04 #define ALOTSLOWER 1.15 #define ALITTLESLOWER 1.02 #define ALITTLEFASTER 1.02 /* * How many inter_char_time's to give you to answer after the end of * a word before considering that you are not keeping up. * Maximum of 2.3, minimum of 0. * The bigger the value, the easier it is to kick in the "automatic * speedup" when using the "-d" option. The maximum means you have (almost) * right up to the beginning of the next word to answer and still have it * count as keeping up. */ #define SPORTING_RATIO 1.5 /* * The bigger, the more evenly things start out. * (Must be at least 2) */ #define RANDOMBASELEVEL 7 /* * RANDOMINCWORSE scales how badly you are punished for being wrong * or taking too long. RANDOMINCBETTER scales how you are rewarded for * answering quickly or being right. */ #define RANDOMINCWORSE 6 #define RANDOMINCBETTER 7 #define RANDOMMAX (30 * RANDOMBASELEVEL) /* * The average length of a random word (chosen using exponential distribution). * After implementing this I'm not so sure an exponential distribution * actually models the distribution of real word lengths in English very well. * It's not too bad, though, and the words themselves are all garbage anyway, * so what the heck. */ #define RANDWORDLEN 3.5 /* Put in a newline instead of a space when past this column */ #define LINELENGTH 78 /* An EOF without the EOF (%) sound */ #define SILENTEOF -2 /* Toggle tone frequency on control-G within input file */ #define FREQU_TOGGLE ((int)'\007') /* * If you want the morse code to come out synchronized with the printing * of dots and dashes with the -m option, then define this. The problem * is that then the morse code sounds ratty on slower CPU's. * John Shalamskas (KJ9U) suggested turning the precise morse-code printing * synching off because he didn't like the resulting code quality! */ #undef FLUSHCODE static void new_words_per_minute (void); static void dowords (int c); static void morse (int c); static void show (char *s); static void testaddchar (char c); static void youraddchar (char c); static void pollyou (void); static void tone (float hertz, float duration, float amplitude); static void toneflush (void); static void openterminal (void); static int readterminal (char **string); static void closeterminal (void); static void report (void); static void die (), suspend (); static void cleanup (); int main (int argc, char **argv) { extern char *optarg; extern int optind; int ch; char *p; int ii, jj; int firsttime, notdoneyet; int yourchar; float randexp, randnum; struct sigaction handler; if (argc == 1 && isatty (fileno (stdin))) { /* * SELF DOC */ printf ("Usage:\n"); printf ("morse [options] < text_file\n"); printf ("morse [options] words words words\n"); printf ("morse [options] -r\n"); printf ("morse [options] -i\n"); printf ("Options:\n"); printf ("-i Play what you type.\n"); printf ("-I Like -i but don't turn off keyboard echoing.\n"); printf ("-r Generate random text. Starts out slanted towards easy\n"); printf (" letters, then slants towards ones you get wrong.\n"); printf ("-n NUM (default %d means random length)\n", MAXWORDLEN); printf (" Make words (groups) NUM characters long.\n"); printf (" Valid values are between %d and %d.\n", 1, MAXWORDLEN); printf ("-R NUM (default 0 means unlimited)\n"); printf (" Set the total time (in minutes) to generate text.\n"); printf ("-N NUM (default 0 means unlimited)\n"); printf (" Set the total number of words (groups) to generate.\n"); printf ("-C \'STRING\' (default all available characters)\n"); printf (" Select characters to send from this STRING only.\n"); printf ("-w words_per_minute (default %g)\n", WORDS_PER_MINUTE); printf (" actual overall sending speed\n"); printf ("-F Farnsworth_character_words_per_minute\n"); printf (" If specified, characters are sent at this speed, with extra\n"); printf (" spaces inserted to bring the overall speed down to the -w\n"); printf (" value. Ignored if not higher than -w.\n"); printf ("-f frequency_in_hertz (default %g)\n", FREQUENCY); printf ("-v volume (zero to one, rather nonlinear, default %g)\n", VOLUME); printf ("-g alternate_frequency (default %g)\n", FREQUENCY2); printf (" (toggles via control-G in input FILE at a word break)\n"); printf ("-e leave off the sound at the end\n"); printf ("-c complain about illegal characters instead of just ignoring them\n"); printf ("-b print each word before doing it\n"); printf ("-a print each word after doing it\n"); printf ("-l print each letter just before doing it\n"); printf ("-m print morse dots and dashes as they sound\n"); #ifdef FLUSHCODE printf (" (this printing-intensive option slows the wpm down!)\n"); #endif printf ("-t Type along with the morse, but don't see what\n"); printf (" you're typing (unless you make a mistake).\n"); printf (" You are allowed to get ahead as much as you want.\n"); printf (" If you get too far behind it will stop and resync with you.\n"); printf (" You can force it to resync at the next word end by hitting control-H.\n"); printf (" Hit ESC to see how you are doing, control-D to end.\n"); printf (" (The rightmost space in the printout marks where the average is.\n"); printf (" Farther left spaces separate off blocks of letters that are\n"); printf (" about twice as probable as the average to occur, three times, etc.)\n"); printf ("-T Like -t but see your characters (after they are played).\n"); printf ("-s Stop after each character and make sure you get it right. (implies -t)\n"); printf ("-q Quietly resyncs with your input (after you make a mistake).\n"); printf ("-p NUM (default 0)\n"); printf (" Make you get it right NUM times, for penance. (implies -s)\n"); printf (" (Yes, NUM = 0 means you can sin all you want.)\n"); printf ("-E NUM (default %d)\n", MAX_ERROR_THRESHOLD); printf (" If your count of wrong answers minus right answers for a given character\n"); printf (" exceeds this, the program will start prompting you.\n"); printf (" If %d or above, it will never prompt. (implies -t)\n", MAX_ERROR_THRESHOLD); printf ("-M NUM (default %d)\n", MAX_BEHINDNESS); printf (" If you get more than this number of characters behind, pause until you\n"); printf (" do your next letter. (1 behind is normal, 0 behind means never pause.)\n"); printf (" (implies -t)\n"); printf ("-d Dynamically speed up or slow down depending on how you are doing.\n"); printf (" (if also -s, then -d _only speeds up_!)\n"); printf ("-A Add ISO 8850-1 (Latin-1) signs to test set.\n"); printf ("-B Add uncommon punctuation to test set.\n"); printf ("-S Add uncommon prosigns to test set.\n"); printf ("-X Set error volume. Defaults to %g.\n", ERROR_VOLUME); printf (" Error volume 0 means use console speaker.\n"); printf ("-x Set frequency of error tone, default 2000.0Hz\n"); exit (0); } /* DGHJKLMOPQUVWYZhjkouyz are still available */ while ((ch = getopt (argc, argv, "ABC:E:F:IM:N:R:STXabcdef:g:ilmn:p:qrstv:w:x:")) != EOF) switch ((char) ch) { case 'A': international = 1; break; case 'B': allpunctuation = 1; break; case 'C': user_charset = optarg; break; case 'E': testing = 1; sscanf (optarg, "%d", &error_threshold); if (error_threshold < error_floor) error_floor = error_threshold; break; case 'F': sscanf (optarg, "%f", &fwords_per_minute); break; case 'I': typeaway = LETMESEE; break; case 'M': testing = 1; sscanf (optarg, "%d", &max_behindness); if (max_behindness < 1) max_behindness = 0; break; case 'N': sscanf (optarg, "%d", &wordcount); if (wordcount < 1) wordcount = -1; break; case 'R': sscanf (optarg, "%d", &timeout); timeout *= 60; if (timeout < 1) timeout = -1; break; case 'S': allprosigns = 1; break; case 'T': testing = 1; showtesting = 1; break; case 'X': sscanf (optarg, "%f", &error_volume); break; case 'a': wordsafter = 1; break; case 'b': wordsbefore = 1; break; case 'c': noticebad = 1; break; case 'd': dynamicspeed = 1; break; case 'e': fancyending = 0; break; case 'f': sscanf (optarg, "%f", &frequency1); break; case 'g': sscanf (optarg, "%f", &frequency2); break; case 'i': typeaway = 1; break; case 'l': showletters = 1; break; case 'm': showmorse = 1; break; case 'n': sscanf (optarg, "%d", &wordlen); if (wordlen < 1) wordlen = 1; if (wordlen > MAXWORDLEN) wordlen = MAXWORDLEN; break; case 'p': charbychar = 1; testing = 1; sscanf (optarg, "%d", &tryagaincount); break; case 'q': keepquiet = 1; break; case 'r': randomletters = 1; break; case 's': charbychar = 1; testing = 1; break; case 't': testing = 1; break; case 'v': sscanf (optarg, "%f", &volume); if (volume < 0.) volume = 0.; if (volume > 1.) volume = 1.; break; case 'w': sscanf (optarg, "%f", &words_per_minute); break; case 'x': sscanf (optarg, "%f", &error_frequency); break; default: fprintf (stderr, "Type \"morse\" without arguments to get self-doc!\n"); exit (1); break; } argc -= optind; argv += optind; if (fwords_per_minute <= 0.) fwords_per_minute = words_per_minute; new_words_per_minute (); frequency = frequency1; if (BeepInit () != 0) { fprintf (stderr, "Can't access speaker.\n"); exit (1); } for (ii = 0; ii < TWOFIFTYSIX; ii++) code[ii] = NULL; /* Load in the morse code code */ code[(int) 'a'] = ".-"; code[(int) 'b'] = "-..."; code[(int) 'c'] = "-.-."; code[(int) 'd'] = "-.."; code[(int) 'e'] = "."; code[(int) 'f'] = "..-."; code[(int) 'g'] = "--."; code[(int) 'h'] = "...."; code[(int) 'i'] = ".."; code[(int) 'j'] = ".---"; code[(int) 'k'] = "-.-"; code[(int) 'l'] = ".-.."; code[(int) 'm'] = "--"; code[(int) 'n'] = "-."; code[(int) 'o'] = "---"; code[(int) 'p'] = ".--."; code[(int) 'q'] = "--.-"; code[(int) 'r'] = ".-."; code[(int) 's'] = "..."; code[(int) 't'] = "-"; code[(int) 'u'] = "..-"; code[(int) 'v'] = "...-"; code[(int) 'w'] = ".--"; code[(int) 'x'] = "-..-"; code[(int) 'y'] = "-.--"; code[(int) 'z'] = "--.."; code[(int) '1'] = ".----"; code[(int) '2'] = "..---"; code[(int) '3'] = "...--"; code[(int) '4'] = "....-"; code[(int) '5'] = "....."; code[(int) '6'] = "-...."; code[(int) '7'] = "--..."; code[(int) '8'] = "---.."; code[(int) '9'] = "----."; code[(int) '0'] = "-----"; /* Punctuation marks */ code[(int) '.'] = ".-.-.-"; code[(int) ','] = "--..--"; code[(int) '?'] = "..--.."; code[(int) '/'] = "-..-."; code[(int) '-'] = "-....-"; if (allpunctuation) { /* Not so commonly used punctuation marks */ code[(int) ')'] = "-.--.-"; code[(int) '\"'] = ".-..-."; code[(int) '_'] = "..--.-"; code[(int) '\''] = ".----."; code[(int) ':'] = "---..."; code[(int) ';'] = "-.-.-."; code[(int) '$'] = "...-..-"; code[(int) '!'] = "-.-.--"; code[(int) '@'] = ".--.-."; } if (allpunctuation) { /* Commonly used procedure signs ("prosigns") */ code[(int) '+'] = ".-.-."; /* end of message */ code[(int) '*'] = ".-..."; /* wait, stand-by */ code[(int) '='] = "-...-"; /* (double dash) pause, break for text */ code[(int) '('] = "-.--."; /* over-specified station only */ code[(int) '%'] = "...-.-"; /* end of contact, known also as */ } if (allprosigns) { /* Not so commonly used procedure signs ("prosigns") */ code[(int) '^'] = ".-.-"; /* new line, the same as :a, ae */ code[(int) '#'] = "-...-.-";/* invite receiving station to transmit */ code[(int) '&'] = "-.-.-"; /* attention */ code[(int) '~'] = "...-."; /* understood */ } if (international) { /* Not so commonly used international extensions (ISO 8859-1) */ code[(int) ((unsigned char)'\344')] = ".-.-"; /* :a (also for ae), the same as */ if (code[(int) '^'] != NULL) code[(int) '^'] = NULL; code[(int) ((unsigned char)'\340')] = ".--.-"; /* `a, oa (danish a with ring over it) */ code[(int) ((unsigned char)'\347')] = "----"; /* ch (bar-ch) */ code[(int) ((unsigned char)'\360')] = "..--."; /* -d (eth, overstrike d with -) */ code[(int) ((unsigned char)'\350')] = "..-.."; /* `e */ code[(int) ((unsigned char)'\361')] = "--.--"; /* ~n */ code[(int) ((unsigned char)'\366')] = "---."; /* :o (also for oe) */ code[(int) ((unsigned char)'\374')] = "..--"; /* :u (also for ue) */ code[(int) ((unsigned char)'\376')] = ".--.."; /* ]p (thorn, overstrike ] with p) */ code[(int) ((unsigned char)'\247')] = ".-.-.."; /* paragraph */ } if (user_charset) { for (ii = 0; ii < strlen(user_charset); ii++) { *(user_charset+ii) = tolower(*(user_charset+ii)); } for (ii = 0; ii < TWOFIFTYSIX; ii++) { if (code[ii] != NULL) { if (strchr(user_charset, ii) != NULL) { randomfactor[ii] = RANDOMBASELEVEL - 1; } else { code[ii] = NULL; randomfactor[ii] = 0; } } } } for (ii = 0; ii < TWOFIFTYSIX; ii++) { /* Everything starts equally fresh */ randomripe[ii] = 0; /* Start out assuming you know how everything sounds */ errorlog[ii] = 0; if (code[ii] == NULL) { /* Ensures these will never be chosen */ randomfactor[ii] = 0; } else { /* Start out favoring easy ones */ randomfactor[ii] = RANDOMBASELEVEL - strlen (code[ii]); if (randomfactor[ii] < 1) randomfactor[ii] = 1; } } words_per_minute = WORDS_PER_MINUTE; fwords_per_minute = -1.; time(&starttime); handler.sa_handler = die; sigemptyset(&handler.sa_mask); handler.sa_flags = 0; sigaction (SIGINT, &handler, NULL); sigaction (SIGTERM, &handler, NULL); sigaction (SIGQUIT, &handler, NULL); handler.sa_handler = suspend; sigaction (SIGTSTP, &handler, NULL); if (testing || typeaway) { openterminal (); } /* * Do 0.25 seconds of silence initially to give the workstation time to * get settled after the stress of starting this program and opening * up everything. */ tone (frequency, 0.25, 0); toneflush (); if (typeaway) { testing = 0; showtesting = 0; charbychar = 0; wordsbefore = 0; wordsafter = 0; randomletters = 0; notdoneyet = 1; while (notdoneyet) { pollyou (); for (jj = 0; jj < yourlength; jj++) { yourchar = yourstring[(yourpointer - yourlength + 1 + jj + TESTBUFSZ) % TESTBUFSZ]; /* Control-D: finished */ if (yourchar == (int) '\004') { toneflush (); notdoneyet = 0; break; } if (isspace (yourchar)) { if (showletters) { toneflush (); printf ("%c", yourchar); fflush (stdout); } tone (frequency, inter_word_time, 0.); continue; } morse (yourchar); } yourlength -= jj; if (timeout > 0) if (difftime(time(NULL),starttime) > (double)timeout) break; } } else if (randomletters) { srand48(time (NULL)); randexp = 1. / (1. - 1. / (float) (RANDWORDLEN)); while (1) { if ((wordcount == 0) || timeout == 0) break; dowords (randomletter ()); if (wordlen == MAXWORDLEN) { /* Knock a few bits off the top so we're sure it won't overflow */ /* Shift a few bits because the lower bits stink */ /* Add in the time so it doesn't repeat from run to run */ randnum = (float) ( (((lrand48() >> 9) + (long) (time (NULL))) >> 4) & 0x00FFFFFF); randnum = randnum - randexp * (int) (randnum / randexp); if ((randnum >= 1.) && (linepos != 0)) dowords ((int) ' '); } } } else { if (*argv) { firsttime = 1; do { if (!firsttime) { dowords ((int) ' '); } else firsttime = 0; if ((wordcount == 0) || timeout == 0) break; for (p = *argv; *p; ++p) { dowords ((int) *p); if ((wordcount == 0) || timeout == 0) break; } if ((wordcount == 0) || timeout == 0) break; } while (*++argv); } else { while ((ch = getchar ()) != EOF) { dowords (ch); if ((wordcount == 0) || timeout == 0) break; } } } if (fancyending) dowords (EOF); else dowords (SILENTEOF); fflush (stdout); if (testing) { /* * WE'RE completely done, and YOU aren't! Force catch up. (Note if * charbychar = YES we won't get here, since we're always caught up * after each character as it comes out.) */ while (testlength > 0) { tone (frequency, catchup_time, 0.); toneflush (); testterminal (); } } /* Just to be sure! */ toneflush (); if (showmorse || wordsbefore || wordsafter || showletters || showtesting) printf ("\n"); fflush (stdout); if (testing) report (); /* If you make any mistakes exit with a return code! */ cleanup (); return (totalmisscount > 0); } static void new_words_per_minute () { float wtick, ftick, tick; tick = 60. / (words_per_minute * 50); /* * In the limit as wpm goes past fwpm, Farnsworth becomes kosher PARIS */ if (fwords_per_minute <= words_per_minute) ftick = 60. / (words_per_minute * 50); else ftick = 60. / (fwords_per_minute * 50); wtick = (50. * tick - 31. * ftick) / 19.; /* * This time is used when the computer is waiting on you to hit a key; it * is useful to scale the granularity with the real overrall words per * minute. This also serves as a measuring rod to see if you are * responding "fast enough". If you are too slow, then obviously you are * having trouble with that character, and should be given it more OFTEN. * Heh heh heh... */ catchup_time = tick; /* * Things between characters and words go at the "remainder" speed, * whatever space you need to make the sped-up Farnsworth characters come * out with the correct overall words per minute. */ inter_char_time = wtick * 3.; inter_word_time = wtick * 7.; /* Things within the character go at the Farnsworth speed */ intra_char_time = ftick; dot_time = ftick; dash_time = ftick * 3.; } static int tryingagain = 0, slowpoke = 0; static void dowords (int c) { static int wordc = 0; static char word[MAXWORDLEN+1]; char *wordp; int ii; int againcount = 0; int are_we_repeating; /* * Increment the line position counter. * If a line gets too long, just cut it off by inserting a new line. */ if (c != EOF && c != SILENTEOF && c != FREQU_TOGGLE) linepos++; if (isspace (c) && ((linepos + wordlen) >= LINELENGTH)) c = '\n'; if (c == '\n') linepos = 0; if (isspace (c) || c == EOF || c == SILENTEOF || c == FREQU_TOGGLE) { if (wordc > 0) { if (wordcount > 0) wordcount--; if (timeout > 0) if (difftime(time(NULL),starttime) > (double)timeout) timeout = 0; word[wordc] = '\0'; /* * We have just read in a new complete word from the input, (hopefully) * during the time of an inter-word space minus an inter-char space. * Now let's go back and see what happened with the PREVIOUS word, * the one that we had just finished playing. Did the user keep * up with us? */ #ifdef DEBUG fprintf (stderr, " [%d] ", behindness); #endif if (testing && dynamicspeed && !charbychar) { /* * (If charbychar then behindness is ALWAYS 0 at this * point...) */ if (behindness == 0) { /* You're a speed demon! Speed up a bit, then! */ words_per_minute *= ALITTLEFASTER; new_words_per_minute (); } else if (behindness > WAYBEHIND) { /* You're way behind! Slow way down. */ words_per_minute /= ALOTSLOWER; new_words_per_minute (); } else if (behindness > BEHIND) { /* You're behind! Slow down a bit. */ words_per_minute /= ALITTLESLOWER; new_words_per_minute (); } } /* * If the user was WAY too far behind stop and catch up with * the "new" word as the first one. */ if (testing && (behindness > TOOFARBEHIND || helpmeflag)) { if (helpmeflag) printf ("\nOK, let's restart.\n"); else printf ("\nYou are too far behind! Let's restart.\n"); fflush (stdout); toneflush (); /* Flush the keyboard buffer */ pollyou (); /* Forget the past */ helpmeflag = 0; behindness = 0; testlength = 0; yourlength = 0; /* Give the user a little rest. */ sleep (2); printf ("\nWPM now %d\n", (int) (words_per_minute + .5)); fflush (stdout); sleep (2); printf ("\nREADY?\n"); fflush (stdout); sleep (1); printf ("\nSET\n"); fflush (stdout); sleep (1); printf ("\nGO!\n"); fflush (stdout); linepos = 0; } /* * Start treating the new word. */ if (wordsbefore) { /* Try to keep your out-of-sync text from getting swirled in */ if (showtesting) { printf ("\n"); linepos = 0; } printf ("%s", word); if (showmorse || showletters || wordsafter || showtesting) { printf (" "); for (ii = 0; ii < 16 - (wordc + 2); ii++) { printf (" "); } } fflush (stdout); } if (testing && charbychar) { againcount = 0; } for (wordp = word; *wordp != '\0'; wordp++) { tryingagain = 0; tryagain: if (testing && !tryingagain && !showletters && error_threshold < MAX_ERROR_THRESHOLD && errorlog[(int) *wordp] > error_threshold) { toneflush (); /* Give them a quick hint */ printf ("[%c]", *wordp); fflush (stdout); morse (*wordp); toneflush (); if (!showmorse) { /* Erase the hint */ printf ("\b\b\b \b\b\b"); fflush (stdout); } } else { morse (*wordp); } if (testing) { if (charbychar) { toneflush (); /* Force catchup */ slowpoke = 0; while (behindness > 0) { if (testterminal () && tryagaincount > 0) { /* * OOPS! They got it WRONG! MAKE THEM TRY * AGAIN! */ printf ("Try again.\n"); linepos = 0; /* * Yeah I know gotos are inelegant but I * don't feel like figuring out the "elegant" * way to do this right now. */ againcount = tryagaincount - 1; tryingagain = 1; goto tryagain; } else { /* * They got it right, or they didn't answer * yet. */ if (behindness > 0) { /* * They are STILL thinking, the * slowpokes. Wait a bit before trying * again. */ tone (frequency, catchup_time, 0.); /* * Keep track of how long they're taking * to answer! */ if (slowpoke < SLOWPOKEMAX) slowpoke++; toneflush (); } else if (dynamicspeed && !slowpoke && !tryingagain) { /* * They got it right without errors the * first time and we didn't have to wait * for them! A speed demon! Speed up a * bit, then! */ words_per_minute *= ALITTLEFASTER; new_words_per_minute (); } } } /* Insufficient penance? */ if (againcount > 0) { againcount--; goto tryagain; } } else { testterminal (); /* * Stop if we get more than max_behindness ahead. * max_behindness == 0 means don't worry about them, * they can be as far behind as they want and we * won't stop! */ if (max_behindness > 0) { are_we_repeating = 0; while (behindness >= max_behindness) { #ifdef DEBUG fprintf (stderr, " (%d) ", behindness); #endif if (are_we_repeating) { /* * Pause for a bit so we don't loop too * fast */ tone (frequency, catchup_time, 0.); } else { are_we_repeating = 1; } /* Finish playing whatever we're playing */ toneflush (); /* And give them another chance */ testterminal (); } } } } } toneflush (); if (testing) testterminal (); if (wordsafter) { printf (" (%s)", word); } if (wordsbefore || wordsafter || showmorse) { if (!showmorse && !testing && linepos) { if (wordsafter) linepos += 3; else printf (" "); } else { printf ("\n"); linepos = 0; } } else if (showletters || showtesting) { if (c != EOF && c != SILENTEOF && c != FREQU_TOGGLE) { if (showletters) printf ("%c", c); if (showtesting) testaddchar (c); } } /* * WHEW! FINISHED QUEUEING THE WORD FOR PLAYING! * Now finish up all the other sundry details... */ /* Flush the output printing queue... */ fflush (stdout); /* * Pause for a bit; this gives the user a sporting chance at * catching up with us. */ tone (frequency, SPORTING_RATIO * inter_char_time, 0.); toneflush (); /* Start sounding an inter-word space */ tone (frequency, inter_word_time - SPORTING_RATIO * inter_char_time, 0.); /* While that silence is playing check if the user has caught up. */ if (testing) testterminal (); /* We finished this word; reset the word character count */ wordc = 0; } else if (!(wordsbefore || wordsafter || showmorse) && (showletters || showtesting)) { if (c != EOF && c != SILENTEOF && c != FREQU_TOGGLE) { if (showletters) printf ("%c", c); if (showtesting) testaddchar (c); } } if (c == EOF) { morse (EOF); toneflush (); } else if (c == SILENTEOF) { toneflush (); } else if (c == FREQU_TOGGLE) { /* Switch to the other frequency */ /* (Won't work from keyboard, only from a file.) */ whichfrequ = 1 - whichfrequ; switch (whichfrequ) { case 1: frequency = frequency2; break; case 0: default: frequency = frequency1; break; } } } else { word[wordc++] = c; } /* * If a word gets too long, just cut it off by inserting a space. * Just call ourselves with the character we wish we'd gotten... */ if (wordc == wordlen && !(isspace (c) || c == EOF || c == SILENTEOF || c == FREQU_TOGGLE)) dowords ((int) ' '); } /* * Don't try to test the person DURING the call into morse! */ void morse (int c) { if ((isalpha (c) && (code[tolower(c)] == NULL)) || ((code[(int) '%'] == NULL) && ((c == EOF) || (c == '\004')))) c = ' '; if (showletters) { if ((c == EOF) || (c == '\004')) { if (showmorse) { printf (""); } else { printf ("%%"); } } else if (c == '.' && showmorse) printf (""); else if (c == '-' && showmorse) printf (""); else if (c == '+' && showmorse) printf (""); else if (c == '*' && showmorse) printf (""); else if (c == '=' && showmorse) printf (""); else if (c == '(' && showmorse) printf (""); else if (c == '%' && showmorse) printf (""); else if (allprosigns) { if (c == '^' && (code[(int) '^'] != NULL) && showmorse) printf (""); else if (c == '#' && showmorse) printf (""); else if (c == '&' && showmorse) printf (""); else if (c == '~' && showmorse) printf (""); } else printf ("%c", c); fflush (stdout); } if (isalpha (c)) { if (testing) testaddchar (c - (isupper (c) ? 'A' : 'a') + 'a'); show (code[c - (isupper (c) ? 'A' : 'a') + 'a']); } else if ((c == EOF) || (c == '\004')) { show (code[(int) '%']); } else if (code[c] != NULL) { if (testing) testaddchar (c); show (code[c]); } else { /* Oops! This letter is junk! */ if (noticebad) { if (showletters) { fflush (stdout); } /* Simulate a stumble */ tone (frequency, 2. * inter_word_time, 0.); toneflush (); } if (showletters) { /* Wipe out what we just printed */ fflush (stdout); printf ("\b"); printf (" "); printf ("\b"); fflush (stdout); } if (noticebad) { if (showletters) { /* And replace it with an error message */ printf (""); fflush (stdout); } /* Give the error call */ show ("........"); /* Regroup */ tone (frequency, inter_word_time, 0.); } } if (showmorse) printf (" "); fflush (stdout); toneflush (); tone (frequency, inter_char_time - intra_char_time, 0.); } /* * Don't try to test the person WHILE doing dots and dashes! */ static void show (char *s) { char c; while ((c = *s++) != '\0') { tone (frequency, intra_char_time, 0.); #ifdef FLUSHCODE if (showmorse) toneflush (); #endif switch (c) { case '.': tone (frequency, dot_time, volume); break; case '-': tone (frequency, dash_time, volume); break; } if (showmorse) { printf ("%c", c); fflush (stdout); #ifdef FLUSHCODE toneflush (); #endif } } } /* * This only gets passed valid characters: ones * that have a morse code associated with them * or ones for which isspace(c) is true. */ static void testaddchar (char c) { testpointer = (testpointer + 1) % TESTBUFSZ; teststring[testpointer] = c; #ifdef DEBUG fprintf (stderr, " (%c,%d,%d) ", c, testlength, behindness); #endif testlength++; if (testlength > TESTBUFSZ) { fprintf (stderr, "\n\nInput buffer queue overflow! Make TESTBUFSZ bigger!\n"); fprintf (stderr, "(Or don't fall so far behind)\n"); die (); } /* * Since you are never asked to type spaces (you can type them if * you want, but they are ignored) spaces in the input file don't * count against your "behindness". */ if (!isspace (c)) behindness++; } static void youraddchar (char c) { yourpointer = (yourpointer + 1) % TESTBUFSZ; yourstring[yourpointer] = c; #ifdef DEBUG fprintf (stderr, " <%c,%d> ", c, yourlength); #endif yourlength++; if (yourlength > TESTBUFSZ) { fprintf (stderr, "\n\nKeyboard typeahead buffer queue overflow! Make TESTBUFSZ bigger!\n"); fprintf (stderr, "(Or don't type so far ahead... how did you expect to get them right anyway?)\n"); die (); } } static void pollyou (void) { int ii, num; char *string; num = readterminal (&string); for (ii = 0; ii < num; ii++) youraddchar (string[ii]); } static int testterminal (void) { int testinc, yourinc; int correctchar, yourchar, yourcharnocase; int errorcount; int resync; errorcount = 0; /* * There is nothing in the input file queue right now, * so we can't process any of your keystrokes. * Defer processing until we can catch up with YOU! */ if (testlength == 0) return errorcount; /* We're ready for you; but are you ready for us? */ pollyou (); /* * Process your entries and the input queue entries in parallel */ if (yourlength > 0 && testlength > 0) { for (testinc = 0, yourinc = 0; testinc < testlength && yourinc < yourlength; testinc++, yourinc++) { correctchar = teststring[(testpointer - testlength + 1 + testinc + TESTBUFSZ) % TESTBUFSZ]; /* * The latter half of this if shouldn't be necessary, but just in * case... */ if (isspace (correctchar) || code[correctchar] == NULL) { if (showtesting) { printf ("%c", correctchar); fflush (stdout); } /* White space doesn't count for "behindness" */ behindness++; /* The _other_ pointer wasn't used; don't increment it. */ yourinc--; /* Short circuit the loop */ continue; } yourchar = yourstring[(yourpointer - yourlength + 1 + yourinc + TESTBUFSZ) % TESTBUFSZ]; if (isalpha (yourchar)) yourcharnocase = yourchar - (isupper (yourchar) ? 'A' : 'a') + 'a'; else yourcharnocase = yourchar; /* Did you type something rude? If so, just ignore it. */ if (isspace (yourchar) || code[yourcharnocase] == NULL) { /* ESCAPE: dump status info */ /* Control-D: dump status info and then bye bye */ /* Control-H: force restart */ if (yourchar == '\033' || yourchar == (int) '\004') { report (); if (yourchar == (int) '\004') die (); } else if (yourchar == '\b') { helpmeflag = 1; } /* The _other_ pointer wasn't used; don't increment it. */ testinc--; /* Short circuit the loop */ continue; } if (keepquiet > 1) { for (resync = testinc; resync < testlength; resync++) if ( yourcharnocase == teststring[(testpointer - testlength + 1 + resync + TESTBUFSZ) % TESTBUFSZ]) { for (; testinc < resync; testinc++) { correctchar = teststring[(testpointer - testlength + 1 + testinc + TESTBUFSZ) % TESTBUFSZ]; if (isspace (correctchar) || code[correctchar] == NULL) { if (showtesting) printf ("%c", correctchar); } else { printf("%s%c%s", enter_standout_mode, correctchar, exit_standout_mode); } } fflush (stdout); correctchar = teststring[(testpointer - testlength + 1 + testinc + TESTBUFSZ) % TESTBUFSZ]; keepquiet = 1; break; } } if (yourcharnocase != correctchar) { errorcount++; totalmisscount++; /* * Record that you are having trouble with these. */ errorlog[correctchar]++; if (code[yourcharnocase] != NULL && errorlog[yourcharnocase] < MAX_ERROR_THRESHOLD) errorlog[yourcharnocase]++; if (keepquiet > 0) { printf("%s%c%s", enter_standout_mode, correctchar, exit_standout_mode); fflush (stdout); keepquiet++; } else { /* * Scold them for their mistake. */ printf ("\n"); if (error_volume) { /* Beep using the tone generator */ toneflush (); tone (error_frequency, 0.1, error_volume); } else /* Beep using control-G */ printf ("\007"); printf ("%c (%s) for %c (%s)\n", yourchar, code[yourcharnocase], correctchar, code[correctchar]); fflush (stdout); linepos = 0; } if (charbychar) { /* Give them a bit of time to think about their error */ tone (frequency, inter_word_time, 0.); toneflush (); } if (dynamicspeed && !charbychar) { /* * Slow down. Doesn't make sense to slow down for errors, * though, if you've got all the time you want to think * about each one. */ words_per_minute /= ERRORSLOWER; new_words_per_minute (); } if (randomletters && !tryingagain) { /* * Ask ones that confused you more often! */ if (code[yourcharnocase] != NULL) { randomfactor[yourcharnocase] += (3 * RANDOMINCWORSE / 2); if (randomfactor[yourcharnocase] > RANDOMMAX) randomfactor[yourcharnocase] = RANDOMMAX; } randomfactor[correctchar] += RANDOMINCWORSE * 2; if (randomfactor[correctchar] > RANDOMMAX) randomfactor[correctchar] = RANDOMMAX; } } else { /* * Record that you got this right. */ if (!tryingagain) { totalhitcount++; if (errorlog[correctchar] > error_floor) errorlog[correctchar]--; } if (showtesting) { printf ("%c", yourchar); fflush (stdout); } if (randomletters && !tryingagain) { if (slowpoke == SLOWPOKEMAX) { printf ("\nNice to have you back again, I was getting bored!\n"); linepos = 0; } else if (slowpoke >= SLOWPOKE * 3) { /* * Did you take too long thinking about it? If so, * you probably need to be asked this one more * often... */ randomfactor[correctchar] += (3 * RANDOMINCWORSE / 2); if (randomfactor[correctchar] > RANDOMMAX) randomfactor[correctchar] = RANDOMMAX; /* * Hits this slow shouldn't count! You were obviously * just guessing! (But it doesn't count as an error * either.) */ totalhitcount--; } else if (slowpoke > FASTPOKE) { randomfactor[correctchar] += (slowpoke * RANDOMINCWORSE) / (2 * SLOWPOKE); if (randomfactor[correctchar] > RANDOMMAX) randomfactor[correctchar] = RANDOMMAX; } else if (slowpoke <= (FASTPOKE / 2)) { /* * Ask ones that you quickly answer correctly less * often! */ randomfactor[correctchar] -= (3 * RANDOMINCBETTER / 2); /* * Don't let randomfactor hit 0, or you'll NEVER be * asked this one AGAIN! */ if (randomfactor[correctchar] < 1) randomfactor[correctchar] = 1; } else if (slowpoke <= FASTPOKE) { randomfactor[correctchar] -= (RANDOMINCBETTER / 2); if (randomfactor[correctchar] < 1) randomfactor[correctchar] = 1; } } } } testlength -= testinc; behindness -= testinc; yourlength -= yourinc; } /* * If there are some extra white space characters in the input queue * it's OK, we'll get to them next time or we'll clean them out at the * end. */ return errorcount; } /*----------------------------------------*/ static void tone (float hertz, float duration, float amplitude) { Beep ((int) (duration * 1000), (int) (amplitude * 100), (int) hertz); } static void toneflush (void) { BeepWait (); } /*----------------------------------------*/ #include #include #include struct termios oldtermgtty; struct termios termgtty; static char *terminal = "/dev/tty"; static int termfd; static int termopen = 0; static int oldflgs, newflgs; static void openterminal (void) { /* get parameters and open terminal */ termfd = open (terminal, O_RDWR | O_NDELAY, 0); tcgetattr(termfd, &termgtty); oldtermgtty = termgtty; if (typeaway != LETMESEE) termgtty.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL); termgtty.c_lflag &= ~ICANON; termgtty.c_cc[VMIN] = 1; termgtty.c_cc[VTIME] = 0; tcsetattr(termfd, TCSADRAIN, &termgtty); termopen = 1; } static int readterminal (char **string) { /* This must be declared static! */ static char line[TESTBUFSZ]; int n; n = read (termfd, line, sizeof (line) - 1); if (n > 0) { line[n] = '\0'; *string = line; } else *string = NULL; return n; } static void closeterminal (void) { tcsetattr(termfd, TCSADRAIN, &oldtermgtty); close (termfd); } static void die (void) { cleanup (); exit (1); } static void cleanup (void) { if (termopen) closeterminal (); BeepCleanup (); } static void suspend (int sig) { struct sigaction handler; sigemptyset(&handler.sa_mask); handler.sa_flags = 0; handler.sa_handler = suspend; sigaction (SIGTSTP, &handler, NULL); cleanup (); kill (getpid (), SIGSTOP); if (termopen) openterminal (); BeepResume (); } /*----------------------------------------*/ static int randomletter (void) { int ii; int sum, sum2; long ranspot; static int lasttime = -1; static long norepeat; /* * This keeps the not-so-random random number generator from ignoring * certain characters forever! */ norepeat = ((long) time (NULL) / 31) % 17291; /* * All the usable letters get one unit riper. */ for (ii = 0; ii < TWOFIFTYSIX; ii++) { if (randomfactor[ii] > 0) { #ifdef DEBUGG fprintf (stderr, "%c: %d %d\n", (char) ii, randomfactor[ii], randomripe[ii]); #endif randomripe[ii]++; } } sum = 0; for (ii = 0; ii < TWOFIFTYSIX; ii++) sum += (randomfactor[ii] + (int) (randomripe[ii] / RIPECOUNT)); /* * The low bits of random aren't very random, I don't care WHAT * the manual claims. */ do { ranspot = ((lrand48() >> 4) % sum + norepeat) % sum; sum2 = 0; for (ii = 0; ii < TWOFIFTYSIX - 1; ii++) { sum2 += (randomfactor[ii] + (int) (randomripe[ii] / RIPECOUNT)); if (sum2 > ranspot) break; } /* Do it again if you got the same as last time! */ } while (ii == lasttime); /* This one is FRESH again. */ randomripe[ii] = 0; /* Remember for next time. */ lasttime = ii; return ii; } static int rancomp (const void *elem1, const void *elem2) { register int *e1 = (int *)elem1; register int *e2 = (int *)elem2; float a, b; a = (randomfactor[(*e1)] + (randomripe[(*e1)] / (float) RIPECOUNT)); b = (randomfactor[(*e2)] + (randomripe[(*e2)] / (float) RIPECOUNT)); if (a == b) return 0; else if (a > b) return -1; else return 1; } static void report (void) { int ii, jj, count; float sum; int randomstr[TWOFIFTYSIX]; printf ("\nCurrent words per minute: %.1f\n", words_per_minute); printf ("Total hits %d, misses %d", totalhitcount, totalmisscount); if (totalmisscount > 0) printf (", hit per miss ratio %.1f\n", (float) totalhitcount / (float) totalmisscount); else printf ("\n"); if (randomletters) { printf ("Most to least frequent choices:\n"); count = 0; sum = 0.; for (ii = 0; ii < TWOFIFTYSIX; ii++) { if (randomfactor[ii] > 0) { sum += (randomfactor[ii] + (randomripe[ii] / (float) RIPECOUNT)); randomstr[count] = ii; count++; } } qsort ((char *) randomstr, count, sizeof (randomstr[0]), rancomp); for (ii = 0; ii < count; ii++) { /* * Insert a space for each jump across an integer. * The normalization (count/sum) ensures that if all * letters were equally probable, they would all have value 1. * Since they are not generally equally probable, then 1 is just the average. * Thus the rightmost space in the printout marks where the average is. * Further left spaces separate off blocks of letters that are approximately * twice as probable as the average, three times, etc. */ if (ii > 0) { for (jj = 0; jj < (int) ( (randomfactor[randomstr[ii - 1]] + (randomripe[randomstr[ii - 1]] / (float) RIPECOUNT)) * count / sum) - (int) ( (randomfactor[randomstr[ii]] + (randomripe[randomstr[ii]] / (float) RIPECOUNT)) * count / sum); jj++) printf (" "); } printf ("%c", (char) randomstr[ii]); } printf ("\n"); } /* * So you don't get penalized for being "slow" after this. */ if (charbychar) slowpoke = SLOWPOKEMAX + 1; fflush (stdout); } morse-2.4/morse.d/beepX11.c0000644000002700000270000000246211455237613012347 0ustar /* beepX11.c -- seligman 5/92 */ /* -- Implementation of beep.h for X11. -- -- Compile with the library "-lX11". */ #include #include #include "alarm.h" #include "beep.h" static Display *dpy = 0; static XKeyboardControl initialState; #define BellFlags (KBBellPercent | KBBellPitch | KBBellDuration) int BeepInit() { XKeyboardState state; if (! (dpy = XOpenDisplay(0))) { perror("Couldn't open display"); return 1; } /* Save initial state so it can be restored later. */ XGetKeyboardControl(dpy, &state); initialState.bell_duration = state.bell_duration; initialState.bell_percent = state.bell_percent; initialState.bell_pitch = state.bell_pitch; return 0; } int Beep(time, volume, pitch) int time, volume, pitch; { XKeyboardControl values; AlarmWait(); if (volume != 0 && pitch != 0) { values.bell_duration = time; values.bell_percent = 100; values.bell_pitch = pitch; XChangeKeyboardControl(dpy, BellFlags, &values); XBell(dpy, volume - 100); XFlush(dpy); } AlarmSet(time); return 0; } int BeepWait() { AlarmWait(); return 0; } int BeepCleanup() { if (dpy != 0) { XChangeKeyboardControl(dpy, BellFlags, &initialState); XFlush(dpy); } return 0; } int BeepResume() { return 0; } morse-2.4/morse.d/alarm.h0000644000002700000270000000071011455237613012235 0ustar /* alarm.h -- wakeup call interface */ /* -- Routines for using the system interval timer to time beeps. Useful -- for implementing the functions in beep.h on systems that don't provide -- a more straightforward BeepWait() equivalent. -- -- These routines use the ALRM signal. */ /* -- Set the alarm for a time specified in ms. */ void AlarmSet(time_t); /* -- Wait for the alarm, or return immediately if the alarm isn't set. */ void AlarmWait(void); morse-2.4/morse.d/beepLinux.c0000644000002700000270000000307711455237613013100 0ustar /* * From: jmorriso@bogomips.ee.ubc.ca (John Paul Morrison) * Subject: beepLinux.c * To: joe@montebello.soest.hawaii.edu * Date: Fri, 18 Nov 1994 15:32:33 -0800 (PST) * X-Linux: watch for it: Linux 94 aka "Helsinki" * * beepLinux.c for morse (lightly tested, seems to work fine) */ /* * beep for the Linux console (PC Speaker) * * (beepSun.c might work if you have a sound card installed and /dev/audio) * * by John Paul Morrison * */ /* beepLinux.c -- 11/94 */ #include #include #include #include #include #include #include "alarm.h" #include "beep.h" static int fd; int BeepInit() { if ((fd = open("/dev/console",O_WRONLY)) == -1) { fprintf(stderr,"You have no permissions to use /dev/console (chmod a+w).\n"); return 1; } return 0; } int Beep(time, volume, pitch) int time, volume, pitch; { int count; AlarmWait(); if (volume == 0) count = 0; else count = (1193180 / pitch) & 0xffff; ioctl(fd, KDMKTONE, (time << 16) | count); AlarmSet(time); return 0; } int BeepWait() { AlarmWait(); return 0; } int BeepCleanup() { close(fd); return 0; } int BeepResume() { return 0; } /* * --------------------------------------------------------------------------- * BogoMIPS Research Labs -- bogosity research & simulation -- VE7JPM -- * jmorriso@bogomips.ee.ubc.ca ve7jpm@ve7jpm.ampr.org jmorriso@ve7ubc.ampr.org * --------------------------------------------------------------------------- */ morse-2.4/morse.d/beepALSA.c0000600000002700000270000001030211572365454012503 0ustar /* beepALSA.c -- Neale Pickett 8/2007 */ /* A lot of code taken from the beepOSS.c, which said: */ /* * A lot of code taken from the beepSun.c */ /* Implementation of beep for ALSA. */ #include #include static char *device = "default"; #include "beep.h" #define RATE (44100) /* 44.1K samples = 1 second (CD quality) */ #define RAMP (RATE * 5 / 1000) /* 5 millisecond ramp */ #define MAXTIME (2 * RATE) /* 2 seconds max tone time */ static int err; static snd_pcm_t *handle; static snd_pcm_sframes_t frames; static int channels = 1; /* 1=mono, 2=stereo */ static float silence[2*MAXTIME]; static float soundbuf[2*(MAXTIME - RAMP)]; static float ramp_down[2*RAMP]; int BeepInit (void) { int i; /* * Initialize the sound of silence */ for (i = 0; i < 2*MAXTIME; i++) { silence[i] = 0; } /* * Set up ALSA */ if ((err = snd_pcm_open(&handle, device, SND_PCM_STREAM_PLAYBACK, 0)) < 0) { printf("Playback open error: %s\n", snd_strerror(err)); return 1; /* Not OK */ } if ((err = snd_pcm_set_params(handle, SND_PCM_FORMAT_FLOAT, SND_PCM_ACCESS_RW_INTERLEAVED, channels, RATE, 1, 500000)) < 0) { /* 0.5sec */ printf("Playback open error: %s\n", snd_strerror(err)); return 1; /* Not OK */ } BeepWait(); return 0; /* OK */ } int Beep (int time, int volume, int pitch) { static int last_pitch = -1, last_n = -1, last_volume = -1; int i, n, first_len, down_len, cycle; double dt; /* * Finagle the number of samples */ n = (time / 1000.) * RATE; /* Number samples in tone time */ n = n < MAXTIME ? n : MAXTIME; /* clip to buffer size */ n = n < 2 * RAMP ? 2 * RAMP : n; /* leave room for ramps */ /* * Catch stupidity */ if (pitch <= 0) { volume = 0; } if (volume <= 0) { snd_pcm_writei(handle, silence, channels*n); } else { /* * clip to Nyquist * (Of course this means that if you ask for too high a frequency you * just get silence, since you sample all the zero-crossings of the * sine wave.) */ pitch = pitch < RATE / 2 ? pitch : RATE / 2; cycle = ((RATE + 1.e-6) / pitch); /* samples per cycle */ if (cycle > MAXTIME / 2) { cycle = MAXTIME / 2; } /* round down length of (rampup + mesa top) to integral cycle */ first_len = ((n - RAMP) / cycle) * cycle; if (first_len < cycle) { first_len = cycle; } if (first_len > MAXTIME - RAMP) { first_len = MAXTIME - RAMP; } /* round down length of (rampdown) to integral cycle */ down_len = ((RAMP) / cycle) * cycle; if (down_len < cycle) { down_len = cycle; } if (down_len > RAMP) { down_len = RAMP; } /* * Can we just reuse what we had before? */ if (pitch != last_pitch || n > last_n || volume != last_volume) { last_pitch = pitch; last_n = n; last_volume = volume; dt = 2. * M_PI / cycle; /* sine scale factor */ /* Ramp up; begin with silence */ for (i = 0; i < RAMP; i++) { soundbuf[i*channels] = ((float)i / RAMP) * (volume/100.0) * sin(i * dt); if (channels == 2) soundbuf[i*channels+1] = soundbuf[i*channels]; } /* Mesa top */ for (i = RAMP; i < first_len; i++) { soundbuf[i*channels] = (volume/100.0) * sin(i * dt); if (channels == 2) { soundbuf[i*channels+1] = soundbuf[i*channels]; } } /* Ramp down; end with silence */ for (i = 0; i < down_len; i++) { ramp_down[i*channels] = (1. - ((float)i / RAMP)) * (volume/100.0) * sin(i * dt); if (channels == 2) { ramp_down[i*channels+1] = ramp_down[i*channels]; } } } snd_pcm_writei(handle, soundbuf, channels*first_len); snd_pcm_writei(handle, ramp_down, channels*down_len); } return 0; } int BeepWait (void) { return 0; } int BeepCleanup (void) { return 0; } int BeepResume (void) { return 0; } morse-2.4/morse.d/Makefile0000600000002700000270000000253411572373026012425 0ustar DEVICE=PA BEEPERS = beepLinux.c beepOSS.c beepX11.c beepALSA.c SOURCES = alarm.c morse.c alarm.h beep.h $(BEEPERS) # The flags necessary to link with the X11 libraries. X11LIBS = -L/usr/X11R6/lib -lX11 # The flags necessary to link with PulseAudio and support pthread PA_CFLAGS = -pthread $(shell pkg-config --cflags libpulse-simple) PA_LIBS = $(shell pkg-config --libs libpulse-simple) -pthread # The flags necessary to link with ALSA ALSA_CFLAGS = $(shell pkg-config --cflags alsa) ALSA_LIBS = $(shell pkg-config --libs alsa) # Any additional flags your favorite C compiler requires to work. CFLAGS = -O3 -I/usr/X11R6/include $($(device)_EXTRA_CFLAGS) morse: morse${DEVICE} rm -f $@ ln morse${DEVICE} $@ morseX11: morse.o beepX11.o alarm.o $(CC) $(X11LIBS) -o $@ morse.o beepX11.o alarm.o morseLinux: morse.o beepLinux.o alarm.o $(CC) -o $@ morse.o beepLinux.o alarm.o -lm morseOSS: morse.o beepOSS.o $(CC) $(CFLAGS) -o $@ morse.o beepOSS.o -lm morsePA: morse.o beepPA.o $(CC) $(CFLAGS) $(PA_CFLAGS) -o $@ morse.o beepPA.o -lm $(PA_LIBS) morseALSA: morse.o beepALSA.o $(CC) $(CFLAGS) $(ALSA_CFLAGS) -o $@ morse.o beepALSA.o -lm $(ALSA_LIBS) morse.o: beep.h Makefile beepX11.o: beep.h alarm.h beepLinux.o: beep.h alarm.h beepOSS.o: beep.h beepALSA.o: beep.h alarm.o: alarm.h clean: rm -f *.o morse QSO morseX11 morseLinux morseOSS morsePA morseALSA morse-2.4/morse.d/beepOSS.c0000644000002700000270000001156411455237613012445 0ustar /* beepOSS.c -- Jacek M. Holeczek 3/2000 */ /* A lot of code taken from the beepSun.c */ /* Implementation of beep for the Open Sound System /dev/dsp device. */ #include #include #include #include #include #include #include "beep.h" #define DEVICE_NAME "/dev/dsp" #define RATE (8000) /* 8 K samples = 1 second */ #define RAMP (RATE * 5 / 1000) /* 5 millisecond ramp */ #define MAXTIME (2 * RATE) /* 2 seconds max tone time */ static int audio = 0; static int channels = 0; /* 1=mono, 2=stereo */ static unsigned char silence[2*MAXTIME]; static unsigned char soundbuf[2*(MAXTIME - RAMP)]; static unsigned char ramp_down[2*RAMP]; int BeepInit (void) { int i; /* * Initialize the sound of silence */ for (i = 0; i < 2*MAXTIME; i++) silence[i] = 128; audio = open(DEVICE_NAME, O_WRONLY, 0); if (audio < 0) { return 1; /* not o.k. */ } else { i = 0x00ff0008; /* 255 fragments, 256 bytes each */ if (ioctl(audio, SNDCTL_DSP_SETFRAGMENT, &i)) { fprintf(stderr, "SNDCTL_DSP_SETFRAGMENT error : 0x%08x\n", i); return 2; } channels = 1; /* 1 channel = mono */ if (ioctl(audio, SNDCTL_DSP_CHANNELS, &channels)==-1) { fprintf(stderr, "SNDCTL_DSP_CHANNELS error : %i\n", channels); return 3; } if (channels != 1) { channels = 2; /* 2 channels = stereo */ if (ioctl(audio, SNDCTL_DSP_CHANNELS, &channels)==-1) { fprintf(stderr, "SNDCTL_DSP_CHANNELS error : %i\n", channels); return 4; } } if (!(channels == 1 || channels == 2)) { fprintf(stderr, "Neither mono nor stereo mode could be set.\n"); return 5; } i = AFMT_U8; /* standard unsigned 8 bit audio encoding */ if (ioctl(audio, SNDCTL_DSP_SETFMT, &i)==-1) { fprintf(stderr, "SNDCTL_DSP_SETFMT error : %i\n", i); return 6; } i = RATE; /* sampling rate RATE */ if (ioctl(audio, SNDCTL_DSP_SPEED, &i)==-1) { fprintf(stderr, "SNDCTL_DSP_SPEED error : %i\n", i); return 7; } write (audio, silence, channels*2); BeepWait(); return 0; /* o.k. */ } } int Beep (int time, int volume, int pitch) { static int last_pitch = -1, last_n = -1, last_volume = -1; int i, n, first_len, down_len, cycle; double dt; /* * Finagle the number of samples */ n = (time / 1000.) * RATE; /* Number samples in tone time */ n = n < MAXTIME ? n : MAXTIME; /* clip to buffer size */ n = n < 2 * RAMP ? 2 * RAMP : n; /* leave room for ramps */ /* * Catch stupidity */ if (pitch <= 0) volume = 0; if (volume <= 0) { write (audio, silence, channels*n); } else { /* * clip to Nyquist * (Of course this means that if you ask for too high a frequency you * just get silence, since you sample all the zero-crossings of the * sine wave.) */ pitch = pitch < RATE / 2 ? pitch : RATE / 2; cycle = ((RATE + 1.e-6) / pitch); /* samples per cycle */ if (cycle > MAXTIME / 2) cycle = MAXTIME / 2; /* round down length of (rampup + mesa top) to integral cycle */ first_len = ((n - RAMP) / cycle) * cycle; if (first_len < cycle) first_len = cycle; if (first_len > MAXTIME - RAMP) first_len = MAXTIME - RAMP; /* round down length of (rampdown) to integral cycle */ down_len = ((RAMP) / cycle) * cycle; if (down_len < cycle) down_len = cycle; if (down_len > RAMP) down_len = RAMP; /* * Can we just reuse what we had before? */ if (pitch != last_pitch || n > last_n || volume != last_volume) { last_pitch = pitch; last_n = n; last_volume = volume; dt = 2. * M_PI / cycle; /* sine scale factor */ /* Ramp up; begin with silence */ for (i = 0; i < RAMP; i++) { soundbuf[i*channels] = rint( 128. + ((float) i / RAMP) * (volume * 1.26) * sin (i * dt) ); if (channels == 2) soundbuf[i*channels+1] = soundbuf[i*channels]; } /* Mesa top */ for (i = RAMP; i < first_len; i++) { soundbuf[i*channels] = rint( 128. + 1. * (volume * 1.26) * sin (i * dt) ); if (channels == 2) soundbuf[i*channels+1] = soundbuf[i*channels]; } /* Ramp down; end with silence */ for (i = 0; i < down_len; i++) { ramp_down[i*channels] = rint( 128. + (1. - (float) (i + 1) / down_len) * (volume * 1.26) * sin (i * dt) ); if (channels == 2) ramp_down[i*channels+1] = ramp_down[i*channels]; } } write (audio, soundbuf, channels*first_len); write (audio, ramp_down, channels*down_len); } return 0; } int BeepWait (void) { ioctl (audio, SNDCTL_DSP_SYNC, 0); return 0; } int BeepCleanup (void) { return 0; } int BeepResume (void) { return 0; } morse-2.4/morse.d/beepPA.c0000600000002700000270000001076611455241471012271 0ustar /* * beep for pulseaudio * * by Thomas Horsten * */ /* beepPA.c -- 10/2010 */ #include #include #include #include #include #include #include #include #include #include #include #include "beep.h" #if 0 #define dprintf(args...) printf(args) #else #define dprintf(args...) #endif static pthread_t beep_thread; static pthread_mutex_t beep_mutex = PTHREAD_MUTEX_INITIALIZER; static pthread_cond_t beep_cv = PTHREAD_COND_INITIALIZER; static const pa_sample_spec sample_format = { .format = PA_SAMPLE_S16LE, .rate = 44100, .channels = 2 }; static pa_simple *snddev; static struct { int time; int volume; int pitch; } beep_info = {0,0,0}; static void play_tone() { int c; int len = (int)(sample_format.rate*beep_info.time/1000.0*2); double t, tt; double v; int16_t *sample; int r; sample = malloc(len*sizeof(sample[0])); if (!sample) return; if (beep_info.volume == 0) { memset(sample, 0, len*sizeof(sample[0])); } else { tt = beep_info.time/1000.0; for (c=0; cBeep(%d,%d,%d)\n",time,volume,pitch); pthread_mutex_lock(&beep_mutex); if (beep_info.time) { pthread_cond_wait(&beep_cv, &beep_mutex); } beep_info.time = time; beep_info.volume = volume; beep_info.pitch = pitch; pthread_mutex_unlock(&beep_mutex); pthread_cond_signal(&beep_cv); dprintf("<--Beep()\n"); } int BeepWait() { dprintf("-->BeepWait() %d\n", beep_info.time); pthread_mutex_lock(&beep_mutex); if (beep_info.time) { dprintf("<<<<<<<<<<<<<\n"); pthread_cond_wait(&beep_cv, &beep_mutex); dprintf(">>>>>>>>>>>>>\n"); } pthread_mutex_unlock(&beep_mutex); dprintf("<--BeepWait()\n"); } int BeepCleanup() { BeepWait(); Beep(-1, 0, 0); pthread_join(beep_thread, NULL); pa_simple_drain(snddev, NULL); pa_simple_free(snddev); return 0; } int BeepResume() { return 0; } morse-2.4/morse.d/beep.h0000644000002700000270000000264211455237613012062 0ustar /* beep.h -- seligman 5/92 */ /* -- Machine-dependent code for sounding a beep. */ #ifndef _BEEP_H #define _BEEP_H /* -- Called exactly once, before any other function in this interface. -- Returns nonzero on error. */ int BeepInit(void); /* -- Sound a beep for a time specified in ms. -- The volume is in the range [0..100], and the pitch is in Hz. -- -- May return immediately, after the sounding of the beep is completed, -- or any time in between. May be called while a previous beep is still -- sounding, in which case the previous beep finishes before the new one -- begins. Overall timing will be much better if this routine can return -- during the sounding of the beep, especially if it's a "zero-volume beep", -- meaning it's really just the timed pause of silence between tones. -- ("morse.c" tries to do all its thinking during the pauses between beeps, -- mostly in the longer ones between words.) -- -- May use the ALRM signal for timing. -- -- Returns nonzero on error. */ int Beep(int time, int volume, int pitch); /* -- Wait until any currently sounding beeps have completed. -- Returns nonzero on error. */ int BeepWait(void); /* -- Clean up any altered state before exiting or suspending the program. -- Returns nonzero on error. */ int BeepCleanup(void); /* -- Restore the world when program is resumed after having been suspended. -- Returns nonzero on error. */ int BeepResume(void); #endif /* _BEEP_H */ morse-2.4/COPYING0000644000002700000270000000261511457644421010463 0ustar BSD LICENSE Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither name of the this project nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. morse-2.4/qso.d/0000755000000000000000000000000011576631014012232 5ustar rootrootmorse-2.4/qso.d/init_str.c0000644000002700000270000000667611455237613012465 0ustar char *Transceiver[] = { #include "rig.h" 0 }; char *Antenna[] = { #include "antenna.h" 0 }; char *UpFeet[] = { "10", "15", "20", "25", "30", "35", "40", "45", "50", "55", "60", "65", "70", "75", "80", "85", "90", "95", "100", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "10 1/2", "11 1/2", "25", "29 1/2", "30", "35", "40", "42", "45", "45 1/2", "45.5", "50", "55", "60", "62", "65", "70", "75", "80", "85", "87 1/3", "90", "95", "100", "103", "137", "189 1/2", "210", "246", "250", 0 }; char *Weather1[] = { "sunny", "rain", "freezing rain", "sleet", "snow", "cloudy", "partly cloudy", "partly sunny", "clear", 0 }; char *Weather2[] = { #include "weather.h" 0 }; char *Power[] = { "2", "5", "10", "20", "25", "40", "50", "80", "100", "125", "140", "150", "170", "200", "250", "270", "300", 0 }; char *Job[] = { #include "jobs.h" 0 }; char *Name[] = { #include "names.h" 0 }; char *CallSign[] = { #include "callsign.h" 0 }; char *License[] = { "Novice", "Technician", "Tech", "Tech plus", "Tech plus", "Tech plus", "Tech plus", "Tech no code", "General", "Advanced", "Extra", "Extra", "Extra", 0 }; char *City[] = { #include "city.h" 0 }; char *NewCity[] = { #include "newcity.h" 0 }; char *CityHeights[] = { #include "cityh.h" 0 }; char *New[] = { "New", "Old", "North", "South", "East", "West", "New", "Old", "North", "Northeast", "Northwest", "South", "Southwest", "Southeast", "East", "West", "Upper", "Lower", 0 }; char *Heights[] = { #include "heights.h" 0 }; char *State[] = { "Alabama", "Alaska", "Arizona", "Arkansas", "California", "Colorado", "Connecticut", "District of Columbia", "Delaware", "Florida", "Georgia", "Guam", "Hawaii", "Idaho", "Illinois", "Indiana", "Iowa", "Kansas", "Kentucky", "Louisiana", "Maine", "Maryland", "Massachusetts", "Michigan", "Midway", "Minnesota", "Mississippi", "Missouri", "Montana", "Nebraska", "Nevada", "New Hampshire", "New Jersey", "New Mexico", "New York", "North Carolina", "North Dakota", "Ohio", "Oklahoma", "Oregon", "Pennsylvania", "Puerto Rico", "Rhode Island", "Saipan", "American Samoa", "South Carolina", "South Dakota", "Tennessee", "Texas", "Utah", "Vermont", "Virginia", "Virgin Islands", "Wake Island", "Washington", "West Virginia", "Wisconsin", "Wyoming", 0 }; char *Frqmisc[] = { "QSN %d?", "QSU %d?", "QSW %d?", "QSN %d", "QSU %d", "QSW %d", 0 }; char *Callmisc[] = { "QRK %s", "QRL %s", "QRZ %s", "QSP %s", "QRK %s?", "QRL %s?", "QRZ %s?", "QSP %s?", 0 }; char *NumMisc[] = { "QRI %d", "QRK %d", "QRM %d", "QRN %d", "QRS %d", "QRY %d", "QSG %d", "QTA %d", "QTC %d", "QRI %d?", "QRK %d?", "QRM %d?", "QRN %d?", "QRS %d?", "QRY %d?", "QSG %d?", "QTA %d?", "QTC %d?", 0 }; char *Miscellaneous[] = { #include "misc.h" 0 }; char *RST[] = { "555", "577", "578", "579", "588", "589", "599", "478", "354", "248", "126", 0 }; morse-2.4/qso.d/QSO.c0000644000002700000270000004224611455242431011257 0ustar /* * Copyright (c) 1991 Paul J. Drongowski. * Copyright (c) 1992 Joe Dellinger. * Copyright (c) 2005 Eric S. Raymond. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * Return-Path: * Received: from cadillac.siemens.com by montebello.soest.hawaii.edu (4.1/montebello-MX-1.9) * id AA01487; Mon, 10 Aug 92 03:21:41 HST * Received: from kevin.siemens.com by cadillac.siemens.com (4.1/SMI-4.0) * id AA25847; Mon, 10 Aug 92 09:21:37 EDT * Date: Mon, 10 Aug 92 09:21:37 EDT * From: pjd@cadillac.siemens.com (paul j. drongowski) * Message-Id: <9208101321.AA25847@cadillac.siemens.com> * To: joe@montebello.soest.hawaii.edu * Status: RO */ /* * This copy is slightly hacked by Joe Dellinger, August 1992 * And some more... November 1992 * * Partially re-written by "murray@vs6.scri.fsu.edu" * to use better grammar and to avoid some nonsensical * responses (like claiming to be a person who's been licensed * longer than they've been alive!), Jan 1994 * * Those improvements merged with others by Joe Dellinger, Oct 1994 */ /* * Generate QSO */ /* * When run, this program generates a single QSO. The form of the * QSO is similar to QSO's one would expect to hear at a code test. * It begins with a series of V's (commented out in this version), * callsigns of the receiver and * sender, followed by a few sentences about weather, name, * occupation, etc. The QSO ends with the callsigns of the receiver * and sender. * * All output is produced using "printf." This should make the * program easy to port. Output can be piped into another program * such as sparc-morse on the Sun or it can be redirected into * a file (without viewing the contents of course!) * * The program design is similar to a "random poetry generator" * or "mad-libs." Each QSO form is generated by its own C function, * such as "PutForm1." Each function calls other C functions to * produce the sentences in the QSO. The sentence forms are * selected somewhat randomly as well as any blanks to be filled. * Words and phrases are selected from several lists such as * "Transceiver," "Antenna," "Job," etc. Sometimes this scheme is * clever as in the formation of city names. Sometimes it is * stupidly simple-minded and grammatical agreement is lost. * By the way, the callsigns are real and were picked from * rec.radio.amateur.misc on USENET. * * The program was constructed in C for Sun workstations. It uses * the library function "drand48" in function "Roll" to produce * pseudo-random numbers. The library function "srand48" and "time" * in "main" are used to set the pseudo-random number seed. * * Known problems and caveats? Hey, it`s software! All Morse * training programs handle the procedural signs (e.g., AR, SK) * differently. The function "PutQSO" currently prints "+ %" * for the AR and SK at the end of the QSO. These may be ignored, * mapped into something else, or just plain cause your training * program to roll over and play dead. I don`t know. This is a * cheap hack. * * And speaking of cheap... The program will not generate all * characters and pro-signs that are found on an "official" code * test. This program is for practice only and should be supplemented * with lots of random code. * * Always have fun! */ #include #include #include char *A_Or_An (char *); char *Choose (char *Words[], int Number); int License_Seed (void); int their_age; /* PERSON'S AGE, SO THEY AREN'T LICENSED MORE * THAN THEIR AGE */ extern char *Transceiver[]; extern char *Antenna[]; extern char *UpFeet[]; extern char *Weather1[]; extern char *Weather2[]; extern char *Power[]; extern char *Job[]; extern char *Name[]; extern char *CallSign[]; extern char *License[]; extern char *City[]; extern char *NewCity[]; extern char *CityHeights[]; extern char *New[]; extern char *Heights[]; extern char *State[]; extern char *Frqmisc[]; extern char *Callmisc[]; extern char *NumMisc[]; extern char *Miscellaneous[]; extern char *RST[]; int NXCVR; int NANTENNA; int NUPFEET; int NWX1; int NWX2; int NPOWER; int NJOB; int NNAME; int NCALLSIGN; char *Sender, *Receiver; int NLICENSE; int NCITY; int NNEWCITY; int NCITYHTS; int NNEW; int NHEIGHTS; int NSTATE; int NFRQMISC; int NFRQCALLMISC; char *FrqCallmisc[] = { "QRW %s %d", "QRZ %s %d", "QSN %s %d", "QSX %s %d", "QRW %s %d?", "QRZ %s %d?", "QSN %s %d?", "QSX %s %d?", 0 }; int NCALLMISC; int NNUMMISC; int NMISC; int NRST; /* ************************************* * Routines to put sentences/clauses * ************************************* */ void PutMisc (void) { printf ("%s\n", Choose (Miscellaneous, NMISC)); } void PutThanks (void) { switch (Roll (6)) { case 2: printf ("Thanks for your call.\n"); break; case 3: printf ("Tnx for ur call.\n"); break; case 4: printf ("Tnx for the call.\n"); break; case 5: printf ("Thanks for the call.\n"); break; default: printf ("Thanks %s for the call.\n", Choose (Name, NNAME)); break; } } void PutName (void) { switch (Roll (6)) { case 2: printf ("Name is %s.\n", Choose (Name, NNAME)); break; case 4: printf ("This is %s.\n", Choose (Name, NNAME)); break; case 5: printf ("%s here.\n", Choose (Name, NNAME)); break; default: printf ("My name is %s.\n", Choose (Name, NNAME)); break; } } void PutJob (void) { switch (Roll (20)) { case 2: case 3: printf ("My occupation is %s.\n", Choose (Job, NJOB)); break; case 4: case 5: printf ("I work as %s.\n", A_Or_An (Choose (Job, NJOB))); break; case 6: printf ("I was %s, now unemployed.\n", A_Or_An (Choose (Job, NJOB))); break; case 11: case 12: printf ("Occupation is %s.\n", Choose (Job, NJOB)); break; default: printf ("I am %s.\n", A_Or_An (Choose (Job, NJOB))); break; } } void PutAge (void) { their_age = Roll (60) + 16; switch (Roll (5)) { case 3: printf ("My age is %d.\n", their_age); break; case 4: printf ("I am %d years old.\n", their_age); break; default: printf ("Age is %d.\n", their_age); break; } } void PutLicense (void) { int get_years_licence; get_years_licence = Roll (License_Seed ()); if (get_years_licence < 2) get_years_licence = 2; switch (Roll (12)) { case 1: printf ("I have %s class licence.\n", A_Or_An (Choose (License, NLICENSE))); break; case 2: printf ("I am %s license ham.\n", A_Or_An (Choose (License, NLICENSE))); break; case 3: printf ("I am %s licence ham.\n", A_Or_An (Choose (License, NLICENSE))); break; case 4: printf ("I have been licenced %d years as %s class.\n", get_years_licence, Choose (License, NLICENSE)); break; case 5: printf ("I have %s class license.\n", A_Or_An (Choose (License, NLICENSE))); break; case 6: printf ("I am %s class ham.\n", A_Or_An (Choose (License, NLICENSE))); break; case 7: printf ("I have been licensed %d years as %s class.\n", get_years_licence, Choose (License, NLICENSE)); break; default: printf ("I have been %s class ham for %d years.\n", A_Or_An (Choose (License, NLICENSE)), get_years_licence); break; } } void PutTemperature (void) { printf ("Temperature is %d.\n", Roll (80) + 10); } void PutWeather1 (void) { switch (Roll (17)) { case 2: printf ("WX is %s.\n", Choose (Weather1, NWX1)); PutTemperature (); break; case 3: printf ("Weather here is %s.\n", Choose (Weather1, NWX1)); break; case 4: printf ("Weather is %s.\n", Choose (Weather1, NWX1)); break; case 5: printf ("WX is %s.\n", Choose (Weather1, NWX1)); break; case 6: PutTemperature (); printf ("Weather here is %s.\n", Choose (Weather1, NWX1)); break; case 7: PutTemperature (); printf ("Weather is %s.\n", Choose (Weather1, NWX1)); break; case 8: PutTemperature (); printf ("WX is %s.\n", Choose (Weather1, NWX1)); break; case 9: printf ("Weather here is %s and temperature is %d.\n", Choose (Weather1, NWX1), Roll (80) + 10); break; case 10: printf ("Weather is %s, temperature %d.\n", Choose (Weather1, NWX1), Roll (80) + 10); break; case 11: printf ("WX is %d degrees and %s.\n", Roll (80) + 10, Choose (Weather1, NWX1)); break; case 12: printf ("The WX is %s and the temp is %d degrees.\n", Choose (Weather1, NWX1), Roll (80) + 10); break; case 14: printf ("Weather is %s.\n", Choose (Weather1, NWX1)); PutTemperature (); break; case 15: printf ("Weather here is %s.\n", Choose (Weather1, NWX1)); PutTemperature (); break; default: printf ("WX is %s and %d degrees.\n", Choose (Weather1, NWX1), Roll (80) + 10); } } void PutWeather2 (void) { switch (Roll (10)) { case 0: printf ("It is %s.\n", Choose (Weather2, NWX2)); break; case 1: printf ("It is %s and %d degrees.\n", Choose (Weather2, NWX2), Roll (80) + 10); break; case 2: printf ("The WX is %s and the temp is %d degrees.\n", Choose (Weather2, NWX2), Roll (80) + 10); break; case 3: printf ("WX is %s and the temp is %d degrees.\n", Choose (Weather2, NWX2), Roll (80) + 10); break; case 4: printf ("It is %s today.\n", Choose (Weather2, NWX2)); break; case 5: printf ("It is %s and %d degrees.\n", Choose (Weather2, NWX2), Roll (100) + 3); break; case 6: printf ("The WX is %s and the temp is %d degrees.\n", Choose (Weather2, NWX2), Roll (90) + 10); break; case 7: printf ("WX is %s and the temp is %d degrees.\n", Choose (Weather2, NWX2), Roll (80) + 10); break; default: printf ("It is %s here.\n", Choose (Weather2, NWX2)); break; } } void PutWeather (void) { switch (Roll (4)) { case 3: PutWeather1 (); break; default: PutWeather2 (); break; } } void PutCityState (void) { switch (Roll (6)) { case 4: printf ("%s %s, ", Choose (CityHeights, NCITYHTS), Choose (Heights, NHEIGHTS)); break; case 5: printf ("%s %s, ", Choose (New, NNEW), Choose (NewCity, NNEWCITY)); break; default: printf ("%s, ", Choose (City, NCITY)); break; } printf ("%s.\n", Choose (State, NSTATE)); } void PutLocation (void) { switch (Roll (5)) { case 3: printf ("My QTH is "); break; case 4: printf ("My location is "); break; default: printf ("QTH is "); break; } PutCityState (); } void PutRig (void) { switch (Roll (19)) { case 0: case 1: printf ("My rig runs %s watts into %s up %s feet.\n", Choose (Power, NPOWER), A_Or_An (Choose (Antenna, NANTENNA)), Choose (UpFeet, NUPFEET)); break; case 2: case 3: printf ("Rig is a %s watt %s and antenna is %s.\n", Choose (Power, NPOWER), Choose (Transceiver, NXCVR), A_Or_An (Choose (Antenna, NANTENNA))); break; case 4: case 5: printf ("My transceiver is %s.\n", A_Or_An (Choose (Transceiver, NXCVR))); printf ("It runs %s watts into %s.\n", Choose (Power, NPOWER), A_Or_An (Choose (Antenna, NANTENNA))); break; case 6: case 7: printf ("The rig is %s running %s watts.\n", A_Or_An (Choose (Transceiver, NXCVR)), Choose (Power, NPOWER)); printf ("Antenna is %s up %s m.\n", A_Or_An (Choose (Antenna, NANTENNA)), Choose (UpFeet, NUPFEET)); break; case 8: case 9: case 10: case 11: printf ("My rig runs %s watts into %s up %s meters.\n", Choose (Power, NPOWER), A_Or_An (Choose (Antenna, NANTENNA)), Choose (UpFeet, NUPFEET)); break; case 12: printf ("My rig runs %s watts into %s up %s feet, but\nthe antenna has partly fallen.\n", Choose (Power, NPOWER), A_Or_An (Choose (Antenna, NANTENNA)), Choose (UpFeet, NUPFEET)); break; case 13: printf ("Rig is %s running %s watts into %s up %s ft.\n", A_Or_An (Choose (Transceiver, NXCVR)), Choose (Power, NPOWER), A_Or_An (Choose (Antenna, NANTENNA)), Choose (UpFeet, NUPFEET)); break; case 14: printf ("My rig runs %s watts into %s up %s feet.\n", Choose (Power, NPOWER), A_Or_An (Choose (Antenna, NANTENNA)), Choose (UpFeet, NUPFEET)); break; case 15: printf ("Rig is %s watt %s and antenna is %s.\n", A_Or_An (Choose (Power, NPOWER)), Choose (Transceiver, NXCVR), Choose (Antenna, NANTENNA)); break; case 16: printf ("My transceiver is %s.\n", A_Or_An (Choose (Transceiver, NXCVR))); printf ("It runs %s watts into %s.\n", Choose (Power, NPOWER), A_Or_An (Choose (Antenna, NANTENNA))); break; case 17: printf ("The rig is %s running %s watts.\n", A_Or_An (Choose (Transceiver, NXCVR)), Choose (Power, NPOWER)); printf ("Antenna is %s up %s feet.\n", A_Or_An (Choose (Antenna, NANTENNA)), Choose (UpFeet, NUPFEET)); break; default: printf ("Rig is %s ", A_Or_An (Choose (Transceiver, NXCVR))); printf ("running %s watts into %s up %s feet.\n", Choose (Power, NPOWER), A_Or_An (Choose (Antenna, NANTENNA)), Choose (UpFeet, NUPFEET)); break; } } void PutRST (void) { register char *TheRST; TheRST = Choose (RST, NRST); switch (Roll (8)) { case 0: printf ("UR RST %s=%s.\n", TheRST, TheRST); break; case 1: printf ("RST is %s=%s.\n", TheRST, TheRST); break; case 2: printf ("RST %s=%s.\n", TheRST, TheRST); break; case 3: printf ("Your RST %s=%s.\n", TheRST, TheRST); break; case 4: printf ("Your RST is %s=%s.\n", TheRST, TheRST); break; case 5: printf ("Your signal is RST %s/%s.\n", TheRST, TheRST); break; case 6: printf ("UR signal is RST %s,%s.\n", TheRST, TheRST); break; default: printf ("Your RST is %s/%s.\n", TheRST, TheRST); break; } } void PutQ_And_Freq (void) { switch (Roll (8)) { case 2: printf (Frqmisc[Roll (NFRQMISC)], make_freq ()); printf ("\n"); break; case 3: printf (Callmisc[Roll (NFRQMISC)], Choose (CallSign, NCALLSIGN)); printf ("\n"); break; case 4: printf (FrqCallmisc[Roll (NFRQCALLMISC)], Choose (CallSign, NCALLSIGN), make_freq ()); printf ("\n"); break; case 5: printf (NumMisc[Roll (NNUMMISC)], Roll (3) + Roll (2) + 1); printf ("\n"); break; default: break; } } void PutFirstCallsign (void) { Sender = Choose (CallSign, NCALLSIGN); Receiver = Choose (CallSign, NCALLSIGN); printf ("%s de %s\n", Receiver, Sender); } void PutLastCallsign (void) { printf ("%s de %s\n", Receiver, Sender); } main (int argc, char **argv) { NXCVR = CountStrings (Transceiver); NANTENNA = CountStrings (Antenna); NUPFEET = CountStrings (UpFeet); NPOWER = CountStrings (Power); NRST = CountStrings (RST); NWX1 = CountStrings (Weather1); NWX2 = CountStrings (Weather2); NJOB = CountStrings (Job); NNAME = CountStrings (Name); NSTATE = CountStrings (State); NCITY = CountStrings (City); NCITYHTS = CountStrings (CityHeights); NNEW = CountStrings (New); NHEIGHTS = CountStrings (Heights); NNEWCITY = CountStrings (NewCity); NLICENSE = CountStrings (License); NMISC = CountStrings (Miscellaneous); NCALLSIGN = CountStrings (CallSign); NFRQMISC = CountStrings (Frqmisc); NFRQCALLMISC = CountStrings (FrqCallmisc); NCALLMISC = CountStrings (Callmisc); NNUMMISC = CountStrings (NumMisc); srand48 ((long) time (0)); PutQSO (); return 0; } morse-2.4/qso.d/callsign.h0000644000002700000270000000175411455237613012423 0ustar "AA0ET", "AA4LR", "AA5BT", "AA6NP", "AA6YD", "AA9BK", "AB5AP", "AB6FI", "AC4HF", "G0GWA", "GM4ZNX", "I5FLN", "IK5AAX", "JA1BLV", "JY1", "K2WK", "K5RC", "K6OCK", "K6XO", "K9ALD", "KA0WCH", "KA1AXY", "KA1CV", "KA1UTU", "KA1ZGC", "KA2RAF", "KA6S", "KB0CY", "KB2NRH", "KB6CSP", "KB6JXT", "KC6SKV", "KC6SSS", "KC6TDR", "KC6VWV", "KD3FU", "KD4AUS", "KD4CPL", "KE2TP", "KE4ZV", "KF6BZF", "KF8NH", "KJ6NN", "KJ9U", "KJ9U/KH6", "KK6JQ", "KM3T", "KT7H", "N1AL", "N1JCX", "N4PBK", "N4VRN", "N5IAL", "N5OP", "N6BIS", "N6MWC", "N6TTO", "N8EMR", "N9FZX", "N9JRV", "N9LFF", "N9MYI", "NE3X", "NH6EG", "NH6EG/5", "NH6ZW", "NJ7E", "NR3Z", "NT1G", "OD5NG", "OH3BK", "OH8NUP", "TG9VT", "UT5RP", "VE6MGS", "VE7EMD", "VK2BQS", "VK2EG", "W0PBV", "W0RIJ", "W0RSB", "W2FG", "W2JGR", "W3GRG", "W3OTC", "WA1UXA", "WA2AGE", "WA3EEC", "WA3TBL", "WA3UQV", "WA5RPF", "WA6DGX", "WA7VYJ", "WA8ZGO", "WB2CJL", "WB4JCM", "WB5FDP", "WB5FKH", "WB5NRN", "WB7CJO", "WB7EEL", "WB7TZA", "WB8EOH", "WB9IVR", "WD0EIB", "WH6UR", "WH6UR/5", "WX9T", morse-2.4/qso.d/names.h0000644000002700000270000000277211455237613011733 0ustar "Al", "Alan", "Alen", "Alex", "Alexander", "Alexandra", "Alexeev", "Alice", "Allen", "Alma", "Amber", "Angel", "Anne", "Art", "Barbara", "Barbie", "Bart", "Bea", "Betty", "Bill", "Bob", "Bruce", "Bryant", "Bud", "Carl", "Carol", "Cathy", "Cheryl", "Chris", "Christy", "Chuck", "Dale", "Dan", "Dave", "David", "Dennis", "Diane", "Dick", "Don", "Ed", "Edmund", "Edward", "Elaine", "Eleuterio", "Ellen", "Francie", "Frank", "Fred", "Gary", "George", "Gilda", "Gus", "Hadassah", "Harry", "Hedwig", "Heika", "Helen", "Helmut", "Henry", "Heriberto", "Ingrid", "Isaac", "Israel", "Jack", "Jacob", "Jake", "Jakob", "James", "Janae", "Jane", "Janet", "Jeff", "Jenni", "Jessica", "Jill", "Jim", "JimBob", "Joan", "Joe", "John", "Jon", "Kaahumanu", "Karen", "Karl", "Kathy", "Keith", "Ken", "Kent", "Kevin", "Kristen", "Kurt", "Larry", "Lauren", "Liholiho", "Linda", "Lou", "Lourdes", "Lynda", "Lynn", "Marc", "Margaret", "Maria", "Mariam", "Mark", "Marty", "Marv", "Mary", "Mike", "Monica", "Moses", "Mosha", "Nancy", "Nathan", "Neil", "Noelani", "Oliver", "Olivia", "Pal", "Pat", "Patrick", "Paul", "Paula", "Peter", "Peto", "Phil", "Pieter", "Quimby", "Rachel", "Ralph", "Ray", "Rebekkah", "Reiko", "Rex", "Reza", "Rich", "Rick", "Ron", "Roy", "Sally", "Sam", "Sara", "Sarah", "Scott", "Scottie", "Spencer", "Steve", "Stew", "Stu", "Sue", "Tello", "Terry", "Thomas", "Tim", "Timothy", "Todd", "Tom", "Tony", "Umberto", "Vicente", "Victor", "Wallace", "Wally", "Walt", "Walter", "Wendy", "William", "Xavier", "Yaohui", "Yolanda", "Zelda", morse-2.4/qso.d/heights.h0000644000002700000270000000054311455237613012255 0ustar "Beach", "Canyon", "Castle", "City", "Corner", "Cove", "Creek", "Estates", "Forest", "Gardens", "Glen", "Grove", "Harbor", "Heights", "Hill", "Hills", "Hole", "Island", "Knob", "Lake", "Meadow", "Meadows", "Mill", "Mountain", "Neck", "Palisades", "Park", "Pass", "Plantation", "Ridge", "River", "Springs", "Station", "Swale", "Terrace", "Valley", "Wood", morse-2.4/qso.d/jobs.h0000644000002700000270000000177311455237613011565 0ustar "administrator", "airline pilot", "artist", "attorney", "bricklayer", "bus driver", "carpenter", "chemist", "clerk", "clown", "college student", "consultant", "cook", "corporate liquidator", "curator", "dentist", "designer", "director", "doctor", "driver", "electrician", "engineer", "farmer", "fireman", "gardener", "geophysicist", "guard", "high school student", "hs student", "human resource consultant", "investment banker", "janitor", "jr college student", "juggler and unicyclist", "junior college student", "lawyer", "letter carrier", "librarian", "mafia killer", "mathematician", "mechanic", "midwife", "milkman", "nurse", "orthodontist", "pacifist", "painter", "petroleum engineer", "physician", "physicist", "police officer", "politician", "prison guard", "professor", "programmer", "researcher", "sailor", "sanitation worker", "sculptor", "secretary", "security guard", "semiotician", "soldier", "sql programmer", "stock broker", "student", "systems analyst", "teacher", "teller", "vulcanologist", "writer", morse-2.4/qso.d/grammar.c0000644000002700000270000000110011455242466012233 0ustar #include int is_vowel (first_char) char first_char; { if ( first_char == 'A' || first_char == 'E' || first_char == 'I' || first_char == 'O' || first_char == 'U' || first_char == 'a' || first_char == 'e' || first_char == 'i' || first_char == 'o' || first_char == 'u' ) return (1); return (0); } char buffer[200]; char * A_Or_An (string) char *string; { if (is_vowel (string[0]) == 1) sprintf (buffer, "an %s", string); else sprintf (buffer, "a %s", string); return ((char *) buffer); } morse-2.4/qso.d/put_form.c0000644000002700000270000000333411455237613012451 0ustar #include void PutForm0 (void) { PutRST (); PutName (); PutLocation (); PutMisc (); PutRig (); PutWeather (); PutJob (); PutAge (); PutMisc (); PutQ_And_Freq (); PutLicense (); } void PutForm1 (void) { PutLocation (); PutRST (); PutRig (); PutWeather (); PutMisc (); PutName (); PutLicense (); PutMisc (); PutQ_And_Freq (); PutAge (); PutJob (); } void PutForm2 (void) { PutThanks (); PutRST (); PutName (); PutWeather (); PutLocation (); PutJob (); PutLicense (); PutRig (); PutAge (); PutQ_And_Freq (); } void PutForm3 (void) { PutLocation (); PutRST (); PutRig (); PutMisc (); PutName (); PutMisc (); PutAge (); PutJob (); PutLicense (); PutMisc (); PutWeather (); PutMisc (); PutQ_And_Freq (); } void PutForm4 (void) { PutThanks (); PutRST (); PutJob (); PutMisc (); PutMisc (); PutName (); PutAge (); PutLicense (); PutRig (); PutLocation (); PutWeather (); PutMisc (); } void PutForm5 (void) { PutLocation (); PutRST (); PutRig (); PutName (); PutJob (); PutAge (); PutMisc (); PutLicense (); PutWeather (); PutMisc (); PutQ_And_Freq (); } PutQSO (void) { /* printf("VVV VVV\n") ; */ PutFirstCallsign (); switch (Roll (6)) { case 0: PutForm0 (); break; case 1: PutForm1 (); break; case 2: PutForm2 (); break; case 3: PutForm3 (); break; case 4: PutForm4 (); break; default: PutForm5 (); break; } printf ("+ %%\n"); PutLastCallsign (); printf ("\n"); } morse-2.4/qso.d/misc.h0000644000002700000270000001702411455237613011557 0ustar "+%=x/,? 73 just testing you.", ",?/=+9% 73 just testing you.", ",?/=q+% 73 just testing u.", "8y67fvgb oops cat on keyboard.", "9p0ojgbhnw23 oops cat on keyboard.", "%w=+/,? 73 just testing you.", "A clumsy gecko just fell on my hand.", "Are you a communist?", "Are you a democrat?", "Are you a libertarian?", "Are you a republican?", "Are you divorced?", "Are you good at auto repair?", "Are you good at calculus? I have a question for you.", "Are you good at car repair? I have a question for you.", "Are you good at group theory? I have a question for you.", "Are you good at summing infinite series?", "Are you married?", "Are you on daylight savings time?", "Are you single?", "Are you using a linear amplifier?", "Are you using an iambic key?", "Are you widowed?", "Aye, laddie, have you ever been to sea?", "Can you pick kryptonite locks? Those are tricky.", "Can you pick kryptonite locks?", "Can you pick master locks? Those are supposed to be easy.", "Can you think of something else interesting to say?", "Copy?", "Cpy?", "Did you attend ORU?", "Did you hear news?", "Did you hear the news?", "Do u understand English?", "Do you have a baby?", "Do you have a cat?", "Do you have a dog?", "Do you have a ferret?", "Do you have a gecko?", "Do you have a horse?", "Do you know morse code?", "Do you know the word copacetic?", "Do you know the word garrulous?", "Do you know the word prosy?", "Do you know what a pangram is?", "Do you like bach?", "Do you like bernstein?", "Do you like c and w music?", "Do you like classical music?", "Do you like country music?", "Do you like hawaiian music?", "Do you like jawaiian music?", "Do you like modern rock?", "Do you like mozart?", "Do you like pop music?", "Do you like reggae music?", "Do you like rock music?", "Do you like swing music?", "Do you listen to Deutsche Welle?", "Do you listen to Radio Australia?", "Do you listen to Radio Moscow?", "Do you listen to Radio New Zealand Intl?", "Do you listen to Radio Peace Peoples Republic of Korea?", "Do you listen to VOA?", "Do you listen to click and clack on PBS?", "Do you listen to the BBC?", "Do you prefer metric units?", "Do you recycle often?", "Do you understand English?", "Do you watch Quantum Leap?", "Do you watch STTNG?", "Do you watch Simpsons?", "Gaverete Ruskie?", "Habla espanol?", "Has the war started yet?", "Have a nice T day.", "Have a nice thanksgiving.", "Have you been to Hawaii recently?", "Have you been to Kauai since Iniki?", "Have you ever been to New Madrid, Missouri?", "Have you ever been to the Chatham islands?", "Have you ever contacted Kalawao county, Molokai?", "Have you ever contacted Loving county, Texas?", "Have you ever played lemmings?", "Have you ever played tetris?", "Have you ever seen a computer virus?", "How copy so far?", "How copy?", "How did you learn morse code?", "How is my signal?", "How is the weather?", "How long have you been a radio amateur?", "How old is your rig?", "Hows my signal?", "Hows the weather?", "I am mobile and am going to the office.", "I am mobile and am going to work.", "I am mobile and driving to work.", "I am mobile, driving cross country.", "I am mobile, driving home from work.", "I am mobile, riding a Peruvian Paso Fino horse.", "I am mobile, riding a Peruvian Paso horse.", "I am mobile, stuck in traffic.", "I am using a linear amplifier.", "I am using an iambic key.", "I just saw a bolide.", "I live at 10 Downing.", "I live at 1010 Springwood.", "I live at 1620 Keeaumoku.", "I live at 2500 Pennsylvania.", "I live at 61C Escondido.", "I sometimes monitor ULF for earthquake precursors.", "I sometimes monitor ulf for earthquake precursors.", "I sometimes work packet on vhf.", "Is it green there or brown?", "Is the bad news true?", "Is your state the one that doesnt have any city governments?", "Is your state the one that has a unicameral legislature?", "Is your state the one that has boroughs instead of counties?", "Is your state the one that has parishes instead of counties?", "Is your state the one that has townships instead of counties?", "Ive fallen and I cant get up.", "Jocks find quartz glyph, vex BMW.", "Jocks find quartz glyph, vex BMW.", "Jocks find quartz glyph, vex BMW.", "Lots of QRM.", "Mele kelikimaka and hauoli makahiki hou 1995.", "Must QRT for Babylon V.", "Must QRT for Star Trek.", "Must QRT for bathroom break.", "Must QRT for breakfast.", "Must QRT for cold breakfast.", "Must QRT for cold dinner.", "Must QRT for cold supper.", "Must QRT for diarreah break.", "Must QRT for dinner.", "Must QRT for hot breakfast.", "Must QRT for hot dinner.", "Must QRT for hot lunch.", "Must QRT for hot supper.", "Must QRT for lunch.", "Must QRT for sleep.", "Must QRT for some sleep.", "Must QRT for supper.", "Must QRT invading tanks making too much noise outside to hear you.", "Must QRT occupation forces knocking at door.", "Must QRT to hear news about approaching hurricane.", "Must QRT wind has blown door open again.", "Must QRT, lightning storm has started.", "Must QRT, lightning threatens.", "Must QRT, nuclear attack?", "Must QRT, tornado sirens sounding.", "Must QRT, tsunami sirens sounding.", "Must QRT, weather radio warbling.", "Our neighbors have a horse named morse code.", "Our neighbors have a horse named morse.", "Please QRS.", "Propagation is good.", "Propagation is poor.", "Propagation is very good.", "Propagation is very poor.", "QLF?", "QRG", "QRH", "QRI 1", "QRI 2", "QRI 3", "QRI", "QRJ", "QRK 1", "QRK 2", "QRK 3", "QRK 4", "QRK 5", "QRK", "QRL", "QRM", "QRM?", "QRN 1", "QRN 2", "QRN 3", "QRN 4", "QRN 5", "QRN", "QRO", "QRP", "QRP?", "QRQ 10", "QRQ 15", "QRQ 20", "QRQ 5", "QRQ", "QRS 10", "QRS 15", "QRS 20", "QRS 5", "QRS", "QRS?", "QRU", "QRV", "QRW", "QRX 0300", "QRX 0500", "QRX 2000", "QRX 2300", "QRX", "QRX?", "QRY 1", "QRY 2", "QRY 3", "QRY", "QRZ", "QSA 1", "QSA 2", "QSA 3", "QSA 4", "QSA 5", "QSA", "QSB", "QSD", "QSG 1", "QSG 2", "QSG", "QSK", "QSK?", "QSL", "QSM", "QSN", "QSO", "QSP", "QST", "QSU", "QSW", "QSX", "QSY", "QSY?", "QSZ", "QTB", "QTC", "QTH?", "QTR", "QTR?", "Should we QSY?", "So how is the weather?", "Sorry, stack of books just fell over.", "Sprechen Sie Deutsch?", "Thanks for the call.", "There is a rainbow outside the window.", "There is an eclipse of the moon right now.", "Tnx for the call.", "Tnx for the report.", "Tnx for ur call.", "We are on vacation and I am mobile.", "We just felt a small quake here.", "What are your hobbies?", "What is the air pressure there?", "What is the air quality there?", "What is the air temperature there?", "What is the humidity there?", "What is your QTH?", "What is your elevation?", "What is your hobby?", "What is your job?", "What is your sign? I am a cancer.", "What is your sign? I am a centaur.", "What is your sign? I am a fish.", "What time zone are you in?", "Whats your job?", "When did you start to learn morse code?", "Where do you live now?", "Where do you live?", "Where is Hollister, California anyway?", "Where is Parkfield, California anyway?", "Whoa, we are having an earthquake here. A real roller.", "Would you have given Morse a Nobel prize?", "You are my first contact today.", "You are my last contact today.", "You are my second contact today.", "You are using a nonlinear amplifier?", "You are using an iambic key?", "Your contest sequence no is 1035.", "Your contest sequence no is 12.", "Your contest sequence no is 17.", "Your contest sequence no is 479.", "Your contest sequence no is 73.", "Your contest sequence no is 7v.", "Your contest sequence no is 826.", "Your contest sequence no is 99.", "Your job is?", "Your signal is chirpy.", "am using a linear amplifier.", "ewsqgbhjolpi oops cat on keyboard.", "ru using linear amplifier?", morse-2.4/qso.d/antenna.h0000644000002700000270000000100111455237613012234 0ustar "10 meter dipole", "10 meter whip", "3 element beam", "5 band vertical", "5 element loop", "7 band beam", "beam", "delta loop", "dipole", "doublet zepp", "dummy load", "ground=plane", "half wave dipole", "inverted V", "light bulb", "log periodic", "long=wire", "monobander", "parasitic beam", "quad loop", "quad vertical", "quagi", "quarter wave vertical", "random wire up 2 kite", "random wire up to kite", "random wire", "rhombic", "symmetrical delta loop", "trap doublet", "tribander", "whip", "yagi", "zepp", morse-2.4/qso.d/cityh.h0000644000002700000270000000073411455237613011744 0ustar "Apple", "Ashford", "Baker", "Baldwin", "Banner", "Barnard", "Benton", "Cabbot", "Carson", "Chester", "College", "Conway", "Cornwall", "Crystal", "Duxbury", "Fletcher", "Franklin", "Granite", "Grant", "Guyan", "Hamilton", "Harper", "Hickory", "Hoosick", "Jefferson", "Lincoln", "Maple", "Mercer", "Morgan", "Morris", "Murray", "Oak", "Orwell", "Oswego", "Perry", "Potter", "Quail", "Salem", "Stafford", "Stone", "Tinker", "Walnut", "Warren", "Washington", "Weston", "Wilton", morse-2.4/qso.d/newcity.h0000644000002700000270000000047411455237613012307 0ustar "Albany", "Avalon", "Barnard", "Bedford", "Bethel", "Boston", "Brunswick", "Canaan", "Chester", "Conway", "Dime Box", "Franklin", "Granville", "Hamilton", "London", "Morris", "Oxford", "Salisbury", "Scarborough", "Stafford", "Stanton", "Trenton", "Troy", "Walpole", "Warren", "Weston", "Wilton", "Windsor", "Zulch", morse-2.4/qso.d/weather.h0000644000002700000270000000125711455237613012264 0ustar "a blue norther", "a noreaster", "a siberia express", "chinook winds", "cloudy", "cold and windy", "cold/dry", "cool/windy", "damp", "drizzling", "fog/drizzle", "foggy", "gale force winds", "gentle rain", "gusting trade winds", "hailing", "horizontal rain", "hot and humid", "hot and windy", "hot", "hot/dry", "hot/humid", "hot/muggy", "hot/smoggy", "humid", "kona winds", "pleasantly cool", "pleasantly warm", "raining cats and dogs", "raining", "santa anna winds", "sleeting", "smoggy", "snowing", "spitting rain", "sunny", "tornadic winds", "trade winds", "uncomfortably hot", "very cold", "very hot", "very windy", "warm", "wet", "wet/foggy", "wet/windy", "windy and warm", "windy", morse-2.4/qso.d/Makefile0000644000002700000270000000045211455237613012110 0ustar CFLAGS = -O3 OBJECTS = QSO.o put_form.o make_fre.o grammar.o util.o init_str.o INCLUDES = antenna.h callsign.h city.h cityh.h heights.h jobs.h misc.h \ names.h newcity.h rig.h weather.h all: QSO QSO: $(OBJECTS) $(CC) -o $@ $(OBJECTS) init_str.o: $(INCLUDES) clean: rm -f *.o QSO morse-2.4/qso.d/city.h0000644000002700000270000000411511455237613011571 0ustar "Agassiz", "Aiea", "Alexander", "Asbury", "Baker", "Bayaney", "Beckley", "Bedford", "Bixby", "Branyan", "Brazoria", "Broken Arrow", "Brunswick", "Bryan", "Burnsville", "Buzzard", "Cambridge", "Carrizo", "Catoosa", "Chamizal", "Charleston", "Chepiwanoxet", "Chesuncook", "Chinquapin", "Circleville", "Claquato", "Clarksburg", "Clarksville", "Clear Lake", "Cleveland", "College", "Crystal", "Duncanville", "Elizabeth", "Enid", "Ewa", "Faalaaga", "Fairbanks", "Fairfax", "Fairfield", "Flamboyant Gardens", "Flint", "Gahanna", "Gappas", "Glenpool", "Grant", "Greensburg", "Guyandotte", "Guyanoga", "Harper Valley", "Harper", "Harquahala", "Hells Crossing", "Hill Valley", "Hillsdale", "Honolulu", "Hyannis", "Iraan", "Iyanbito", "Jamestown", "Jefferson", "Jenks", "Juncos", "Kaaawa", "Kohlsaat", "Kona", "Laager", "Lakewood", "Lancaster", "Lawrenceville", "Leyan", "Lincoln", "Litchfield", "London", "Long Branch", "Luxello", "Lyndale", "Lyndhurst", "Lynnville", "Maaloon", "Maitwan", "Manasquan", "Mansfield", "Maple", "Meadows", "Melbourne", "Mentor", "Mercer", "Mesquite", "Midland", "Milldale", "Milltown", "Moorestown", "Moscow", "Mountain View", "Moxee", "Murray", "Muskogee", "Musquiz", "Naxera", "New London", "Newfield", "Newport", "Nipgen", "Nisqually", "Nome", "Noname", "Noxubee", "Nutzotin", "Oak", "Occoquan", "Olmstead", "Owasso", "Oxford", "Oxnard", "Paradise", "Paris", "Pattaquattic", "Pawtuxet", "Perry", "Piscataquis", "Potter", "Pottsville", "Praag", "Quanah", "Quebec", "Redwood", "Rueechayaam", "Russellville", "Salem", "San Pasqual", "Sandy", "Sapulpa", "Saratoga", "Sequatchie", "Smithville", "Snoqualmie", "Springdale", "Springfield", "Squaxin", "Starkville", "Sunnyvale", "Sunset Valley", "Suquamish", "Tahlequah", "Tahquamenon", "Texoma", "Texum", "Tinker", "Trenton", "Tulsa", "Twisp", "Umpqua", "Union", "Uruguay", "Utica", "Vancouver", "Verona", "Viroqua", "Vista", "Waldberggaard", "Walnut", "Warners Landing", "Warren", "Warsaw", "Washington", "Wesleyanna", "Weston", "Wheatfield", "Williamson", "Worchester", "Wyandanch", "Xanthus", "Xenia", "Yangtze", "Yellowstone", "Yreka", "Zolton", "Zuni", morse-2.4/qso.d/util.c0000644000002700000270000000161311455237613011571 0ustar /* ******************** * Utility routines * ******************** */ extern int their_age; int CountStrings (char *StringVector[]) /* * Count the number of string values in the supplied vector * of pointers. Start with the first pointer and stop when * NIL (0) is encountered. */ { register char **SV; register int Count; Count = 0; for (SV = StringVector; *SV; SV++) { Count++; } return (Count); } int Roll (int Number) { int new_tmp; double tmp_val; double drand48 (); tmp_val = ((int) (drand48 () * (Number /*-1*/ ))); new_tmp = (int) tmp_val % 32767; if (new_tmp < 2) tmp_val = 2; return ((int) new_tmp); } int License_Seed (void) { if (their_age > 20) return (20); if (their_age < 10) return (10); return (their_age - 8); } char * Choose (char *Words[], int Number) { return (Words[Roll (Number)]); } morse-2.4/qso.d/make_fre.c0000644000002700000270000000066111455237613012367 0ustar #define M80 2 #define M40 3 #define M15 4 #define M10 5 #define NUM_BAND 4 int make_freq (void) { switch (Roll (NUM_BAND + 2)) { case M80: return (3675 + Roll (50)); break; case M40: return (7100 + Roll (50)); break; case M15: return (21100 + Roll (100)); break; case M10: return (28100 + Roll (200)); break; default: return (7100 + Roll (50)); break; } } morse-2.4/qso.d/rig.h0000644000002700000270000000220111455237613011374 0ustar "Collins 75S=3", "Collins KWM=2", "Drake T=4XB", "Drake TR3", "Drake TR4", "Eico 753", "Hallicrafters SR150", "Hallicrafters SR160", "Hallicrafters SR2000", "Hallicrafters SR400", "Hallicrafters SR500", "Heathkit DX=660B", "Heathkit HG=10B", "Heathkit HR=10", "Heathkit HW100", "Heathkit HW12", "Heathkit HW12A", "Heathkit HW22", "Heathkit HW22A", "Heathkit HW32", "Heathkit HW32A", "Heathkit HW8", "Heathkit SB100", "Homebrew", "Icom IC=1275", "Icom IC=275", "Icom IC=475", "Icom IC=575", "Icom IC=725", "Icom IC=726", "Icom IC=730", "Icom IC=735", "Icom IC=751", "Icom IC=751A", "Icom IC=765", "Icom IC=781", "Kenwood TR=450", "Kenwood TR=751", "Kenwood TR=850", "Kenwood TR=851", "Kenwood TS=140", "Kenwood TS=440", "Kenwood TS=680", "Kenwood TS=711", "Kenwood TS=77", "Kenwood TS=850", "National NCL 200", "National NCX3", "National NCX5", "RS HTX=100", "Radio Shack HTX=100", "Swan 120", "Swan 140", "Swan 180", "Swan 240", "Swan 350", "Ten Tec 562", "Ten Tec 585", "Ten Tec Argonaut", "Ten Tec Delta", "Ten Tec Omni", "Yaesu FT=1000", "Yaesu FT=101", "Yaesu FT=736", "Yaesu FT=747", "Yaesu FT=757", "Yaesu FT=767", "Yaesu FT=840", "Yaesu FT=990", morse-2.4/morse.10000644000002700000270000002321711572375074010643 0ustar '\" t .\" Title: morse .\" Author: [see the "AUTHORS" section] .\" Generator: DocBook XSL Stylesheets v1.75.2 .\" Date: 06/04/2011 .\" Manual: Education .\" Source: morse .\" Language: English .\" .TH "MORSE" "1" "06/04/2011" "morse" "Education" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" http://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" morse, QSO \- Morse\-code trainer and QSO generator for aspiring radio hams .SH "SYNOPSIS" .HP \w'\fBmorse\fR\ 'u \fBmorse\fR [\-i] [\-I] [\-r] [\-n\ \fInum\fR] [\-R\ \fInum\fR] [\-N\ \fInum\fR] [\-C\ \fIcharset\fR] [\-w\ \fInum\fR] [\-f\ \fInum\fR] [\-v\ \fInum\fR] [\-g\ \fInum\fR] [\-f\ \fInum\fR] [\-e] [\-c] [\-b] [\-a] [\-l] [\-m] [\-t] [\-T] [\-s] [\-q] [\-p\ \fInum\fR] [\-E\ \fInum\fR] [\-M\ \fInum\fR] [\-d] [\-A] [\-B] [\-S] [\-x\ \fInum\fR] [\-X\ \fInum\fR] [\fIword\fR...] .SH "DESCRIPTION" .PP The \fBmorse\fR program is a Morse\-code trainer intended to help aspiring radio hams pass the 5\-word\-per\-minute Element 1 test\&. It can take test text from a text file on standard input, or test words from its command\-line arguments, or generate random text (\-r) or play back what you type (\-i)\&. .PP A helper program, \fBQSO\fR, generates plausible QSOs that can be fed to the standard input of \fBmorse\fR\&. .PP The following options control the behavior of \fBmorse\fR: .PP \-i .RS 4 Play what you type\&. .RE .PP \-I .RS 4 Like \-i but don\*(Aqt turn off keyboard echoing\&. .RE .PP \-r .RS 4 Generate random text\&. Starts out slanted towards easy letters, then slants towards ones you get wrong\&. .RE .PP \-n NUM .RS 4 Make words (groups) NUM characters long\&. Valid values are between 1 and 20\&. .RE .PP \-R NUM .RS 4 Set the total time (in minutes) to generate text\&. .RE .PP \-N NUM (default 0 means unlimited) .RS 4 Set the total number of words (groups) to generate\&. .RE .PP \-C \*(AqSTRING\*(Aq (default all available characters) .RS 4 Select characters to send from this STRING only\&. .RE .PP \-w .RS 4 words_per_minute .RE .PP \-f .RS 4 frequency_in_hertz .RE .PP \-v .RS 4 volume (zero to one, rather nonlinear) .RE .PP \-g .RS 4 alternate_frequency (toggles via control\-G in input FILE at a word break) .RE .PP \-F .RS 4 Farnsworth_character_words_per_minute .RE .PP \-e .RS 4 leave off the sound at the end .RE .PP \-c .RS 4 complain about illegal characters instead of just ignoring them .RE .PP \-b .RS 4 print each word before doing it .RE .PP \-a .RS 4 print each word after doing it .RE .PP \-l .RS 4 print each letter just before doing it .RE .PP \-m .RS 4 print morse dots and dashes as they sound (this printing\-intensive option slows the wpm down!) .RE .PP \-t .RS 4 Type along with the morse, but don\*(Aqt see what you\*(Aqre typing (unless you make a mistake)\&. You are allowed to get ahead as much as you want\&. If you get too far behind it will stop and resync with you\&. You can force it to resync at the next word end by hitting control\-H\&. Hit ESC to see how you are doing, control\-D to end\&. (The rightmost space in the printout marks where the average is\&. Farther left spaces separate off blocks of letters that are about twice as probable as the average to occur, three times, etc\&.) .RE .PP \-T .RS 4 Like \-t but see your characters (after they are played)\&. .RE .PP \-s .RS 4 Stop after each character and make sure you get it right\&. (implies \-t) .RE .PP \-q .RS 4 Quietly resyncs with your input (after you make a mistake)\&. .RE .PP \-p NUM .RS 4 Make you get it right NUM times, for penance\&. (implies \-s)\&. .RE .PP \-E NUM .RS 4 If your count of wrong answers minus right answers for a given character exceeds this, the program will start prompting you\&. If above the maximum error prompt it will never prompt (implies \-t)\&. .RE .PP \-M NUM .RS 4 If you get more than this number of characters behind, pause until you do your next letter\&. 1 behind is normal, 0 behind means never pause\&. This option mplies \-t\&. .RE .PP \-d .RS 4 Dynamically speed up or slow down depending on how you are doing\&. (if also\-s, then \-d \fIonly speeds up\fR!) .RE .PP \-A .RS 4 Add ISO 8859\-1 (Latin\-1) signs to test set\&. .RE .PP \-B .RS 4 Add uncommon punctuation to test set\&. .RE .PP \-S .RS 4 Add uncommon prosigns to test set\&. .RE .PP \-X .RS 4 Set error volume\&. Error volume 0 means use console speaker\&. .RE .PP \-x .RS 4 Set frequency of error tone\&. .RE .PP Here is the basic International Morse codest that the program will train you in: .sp .if n \{\ .RS 4 .\} .nf A \&.\- N \-\&. 1 \&.\-\-\-\- \&. \&.\-\&.\-\&.\- B \-\&.\&.\&. O \-\-\- 2 \&.\&.\-\-\- , \-\-\&.\&.\-\- C \-\&.\-\&. P \&.\-\-\&. 3 \&.\&.\&.\-\- ? \&.\&.\-\-\&.\&. D \-\&.\&. Q \-\-\&.\- 4 \&.\&.\&.\&.\- ( \-\&.\-\-\&. E \&. R \&.\-\&. 5 \&.\&.\&.\&.\&. \- \-\&.\&.\&.\&.\- F \&.\&.\-\&. S \&.\&.\&. 6 \-\&.\&.\&.\&. G \-\-\&. T \- 7 \-\-\&.\&.\&. H \&.\&.\&.\&. U \&.\&.\- 8 \-\-\-\&.\&. I \&.\&. V \&.\&.\&.\- 9 \-\-\-\-\&. J \&.\-\-\- W \&.\-\- 0 \-\-\-\-\- K \-\&.\- X \-\&.\&.\- / \-\&.\&.\-\&. L \&.\-\&.\&. Y \-\&.\-\- + \&.\-\&.\-\&. M \-\- Z \-\-\&.\&. = \-\&.\&.\&.\- .fi .if n \{\ .RE .\} .PP The following characters are included if one uses the \-B option: .sp .if n \{\ .RS 4 .\} .nf ) \-\&.\-\-\&.\- " \&.\-\&.\&.\-\&. _ \&.\&.\-\-\&.\- \*(Aq \&.\-\-\-\-\&. : \-\-\-\&.\&.\&. ; \-\&.\-\&.\-\&. $ \&.\&.\&.\-\&.\&.\- ! \-\&.\-\&.\-\- @ \&.\-\-\&.\-\&. .fi .if n \{\ .RE .\} .PP The following procedural signals (prosigns) are also included if one uses \-B: .sp .if n \{\ .RS 4 .\} .nf "+" over, end of message "*" please stand by ( 5 Wait 5 Minutes) ("\&.\-\&.\&.\&.") "=" (double dash) pause, break for text CL going off the air (clear) CQ calling any station K go, invite any station to transmit "(" go only, invite a specific station to transmit R all received OK "%" end of contact (sent before call) ("\&.\&.\&.\-\&.\-", known also as ) .fi .if n \{\ .RE .\} .PP The following less\-used prosigns are included if one uses the \-S option: .sp .if n \{\ .RS 4 .\} .nf "^" new line ("\&.\-\&.\-", the same as :a, ae) "#" invite receiving station to transmit ("\-\&.\&.\&.\-\&.\-") "&" attention ("\-\&.\-\&.\-") "~" understood ("\&.\&.\&.\-\&.") .fi .if n \{\ .RE .\} .PP The following characters are included if one uses the \-A option: .sp .if n \{\ .RS 4 .\} .nf :a \&.\-\&.\- (also for ae, the same as ) `a \&.\-\-\&.\- (also oa, danish a with ring over it) ch \-\-\-\- (bar\-ch ?, bar\-h ?, ISO 8859\-1 code 199 and 231 ?) \-d \&.\&.\-\-\&. (eth, overstrike d with \-, ISO 8859\-1 code 208 and 240) `e \&.\&.\-\&.\&. ~n \-\-\&.\-\- :o \-\-\-\&. (also for oe) :u \&.\&.\-\- (also for ue) ]p \&.\-\-\&.\&. (thorn, overstrike ] with p, ISO 8859\-1 code 222 and 254) paragraph \&.\-\&.\-\&.\&. (ISO 8859\-1 code 167 ?) .fi .if n \{\ .RE .\} .PP For the raw beginner trying to learn morse code, we recommend the following sequence: .sp .RS 4 .ie n \{\ \h'-04' 1.\h'+01'\c .\} .el \{\ .sp -1 .IP " 1." 4.2 .\} Start learning the alphabet: .sp .if n \{\ .RS 4 .\} .nf morse \-r \-s \-T \-d \-w 5 \-F 15 \-p 5 \-E \-10 .fi .if n \{\ .RE .\} .RE .sp .RS 4 .ie n \{\ \h'-04' 2.\h'+01'\c .\} .el \{\ .sp -1 .IP " 2." 4.2 .\} Then drill drill drill: .sp .if n \{\ .RS 4 .\} .nf morse \-r \-s \-T \-d \-w 5 \-F 15 \-p 5 \-E 0 .fi .if n \{\ .RE .\} .RE .sp .RS 4 .ie n \{\ \h'-04' 3.\h'+01'\c .\} .el \{\ .sp -1 .IP " 3." 4.2 .\} Real\-time drill, with hints if you really need it: .sp .if n \{\ .RS 4 .\} .nf morse \-r \-T \-d \-w 5 \-F 15 \-M 2 \-E 4 .fi .if n \{\ .RE .\} .RE .sp .RS 4 .ie n \{\ \h'-04' 4.\h'+01'\c .\} .el \{\ .sp -1 .IP " 4." 4.2 .\} Simulated test: .sp .if n \{\ .RS 4 .\} .nf QSO | morse \-e \-T \-d \-w 5 \-F 15 .fi .if n \{\ .RE .\} .RE .sp .RS 4 .ie n \{\ \h'-04' 5.\h'+01'\c .\} .el \{\ .sp -1 .IP " 5." 4.2 .\} The dreaded random\-letter test: .sp .if n \{\ .RS 4 .\} .nf morse \-r \-T \-d \-w 5 \-F 15 .fi .if n \{\ .RE .\} .RE .sp .RS 4 .ie n \{\ \h'-04' 6.\h'+01'\c .\} .el \{\ .sp -1 .IP " 6." 4.2 .\} Finally try for greater and greater speed: .sp .if n \{\ .RS 4 .\} .nf morse \-r \-T \-d \-w 13 \-F 24 .fi .if n \{\ .RE .\} .RE .SH "AUTHORS" .PP Joe Dellinger joe@montebello\&.soest\&.hawaii\&.edu\&. .PP Updated 2005 by Eric S\&. Raymond esr@thyrsus\&.com\&. .PP Updated 2010 by Thomas Horsten thomas@horsten\&.com\&. .PP Other contributions by Jacek M\&. Holeczek and Marc Unangst\&. morse-2.4/QSO.10000644000002700000270000000002111572375074010144 0ustar .so man1/morse.1 morse-2.4/Makefile0000644000002700000270000000516711572374113011071 0ustar # Select your audio output device. Current choices are: # # X11: The X11 window system. # Linux: IBM PC Console running Linux. # OSS: Open Sound System /dev/dsp device. # PA: PulseAudio using the pulse-simple client API. # ALSA: Advanced Linux Sound Architecture # # Running on Linux: # Many Linux laptops seem to have console speakers that are unreliable # for various hardware and software reasons. You may be better off # using morseALSA or morseOSS than morseLinux. # # Running on Mac OS X: # (1) Use X11. The user must, as with any X11 client, set the DISPLAY # variable, and have the X server running. Finally, the X11 output # preferences dialog should have "Use system alert effect" unchecked; # otherwise, the system alert (settable, but unlikely to be useful to # copy code in any event) will be used instead of the X beep. # # Adding a new device is as simple as creating a new implementation of the # beep.h interface. See beep*.c for examples. Please send any additions # to the authors! # #DEVICE = X11 #DEVICE = Linux #DEVICE = OSS #DEVICE = ALSA DEVICE = PA VERSION=2.4 MANPAGES = morse.1 QSO.1 DOCS = README HISTORY COPYING morse.xml $(MANPAGES) ALL= $(DOCS) Makefile $(SOURCES) test_input \ morse.d/*.[ch] morse.d/Makefile \ qso.d/*.[ch] qso.d/Makefile default: make testmorse all: morse QSO morse.1 QSO.1 morse: cd morse.d && make DEVICE=${DEVICE} ln morse.d/morse ./morse QSO: cd qso.d && make ln qso.d/QSO ./QSO # # "Jocks find quartz glyph, vex BMW." is my attempt to win Stephen J. Gould's # prize (a copy of all his books) for the first person who can come up with a # "perfect pangram": a meaningful sentence consisting entirely of common # English words, with no abbreviations or proper names, that contains each # letter exactly once. He rejected it because it contains "BMW", alas, but # he did say it's the closest he's seen so far. - Joe Dellinger # testmorse: morse QSO (cat test_input; qso.d/QSO) | ./morse -w 24 -l -e testqso: morse QSO qso.d/QSO | ./morse -w 20 -l -e all: morse QSO clean: rm -f morse QSO *.1 *.html SHIPPER.* cd morse.d; make clean cd qso.d; make clean pristine: clean rm -f $(MANPAGES) morse.html morse.1 QSO.1: morse.xml xmlto man morse.xml morse.html: morse.xml xmlto xhtml-nochunks morse.xml morse-$(VERSION).tar.gz: $(ALL) @ls $(ALL) | sed s:^:morse-$(VERSION)/: >MANIFEST @(cd ..; ln -s morse-classic morse-$(VERSION)) (cd ..; tar -czf morse-classic/morse-$(VERSION).tar.gz `cat morse-classic/MANIFEST`) @(cd ..; rm morse-$(VERSION)) dist: morse-$(VERSION).tar.gz release: morse-$(VERSION).tar.gz morse.html shipper -u -m -t; make clean morse-2.4/README0000600000002700000270000000272211572365454010303 0ustar This is Morse Classic, a generic morse-code practice utility for Unix systems. You'll invoke it as "morse"; the full name is to distinguish it from Alan Cox's "morse" program. Currently supported devices: X11: The X11 window system. (Warning: not all X11 implementations handle duration and frequency of beeps properly!) Linux: The IBM PC console speaker. OSS: Open Sound System /dev/dsp device. Also works with the newer ALSA Linux sound system using the legacy OSS device. PA: PulseAudio using the pulse-simple client API. ALSA: ALSA Linux sound system /dev/snd/* device. Adding a new device is as simple as creating a new implementation of the beep.h interface. See beep*.[ch] for examples and documentation. Please send any additions to the maintainers. A modified version of the program "QSO" by Paul J. Drongowski is also included. For the character set this trainer generates, see the manual page. Special Characters and Groups (never included, placed here for completeness) : Multiplication sign -..- (the same as x, ISO 8859-1 code 215 ?) "Mistake, delete the last word" ........ (actually six or more dots are used for this purpose, eight dots are recommended). Cut Numbers : 1 .- 6 -... 1 .- 6 -.... 2 ..- 7 --. 2 ..- 7 -... 3 .-- 8 -.. 3 ...- 8 -.. 4 ...- 9 -. 4 ....- 9 -. 5 ... 0 - 5 . 0 -