2 * Copyright (c) 1988, 1993
3 * The Regents of the University of California. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * Taught to send *real* morse by Lyndon Nerenberg (VE7TCP/VE6BBM)
36 * <lyndon@orthanc.com>
40 static const char copyright[] =
41 "@(#) Copyright (c) 1988, 1993\n\
42 The Regents of the University of California. All rights reserved.\n";
47 static char sccsid[] = "@(#)morse.c 8.1 (Berkeley) 5/31/93";
49 static const char rcsid[] =
67 #include <machine/speaker.h>
75 static const struct morsetab mtab[] = {
126 {'=', "-...-"}, /* BT */
129 {'(', "-.--."}, /* KN */
132 {'+', ".-.-."}, /* AR */
134 /* prosigns without already assigned values */
136 {'#', ".-..."}, /* AS */
137 {'@', "...-.-"}, /* SK */
138 {'*', "...-."}, /* VE */
139 {'%', "-...-.-"}, /* BK */
145 static const struct morsetab iso8859tab[] = {
160 static const struct morsetab koi8rtab[] = {
162 * the cyrillic alphabet; you'll need a KOI8R font in order
163 * to see the actual characters
166 {'Â', "-..."}, /* be */
167 {'×', ".--"}, /* ve */
168 {'Ç', "--."}, /* ge */
169 {'Ä', "-.."}, /* de */
171 {'£', "."}, /* yo, the same as ye */
172 {'Ö', "...-"}, /* she */
173 {'Ú', "--.."}, /* ze */
175 {'Ê', ".---"}, /* i kratkoye */
176 {'Ë', "-.-"}, /* ka */
177 {'Ì', ".-.."}, /* el */
178 {'Í', "--"}, /* em */
179 {'Î', "-."}, /* en */
180 {'Ï', "---"}, /* o */
181 {'Ð', ".--."}, /* pe */
182 {'Ò', ".-."}, /* er */
183 {'Ó', "..."}, /* es */
185 {'Õ', "..-"}, /* u */
186 {'Æ', "..-."}, /* ef */
187 {'È', "...."}, /* kha */
188 {'Ã', "-.-."}, /* ce */
189 {'Þ', "---."}, /* che */
190 {'Û', "----"}, /* sha */
191 {'Ý', "--.-"}, /* shcha */
192 {'Ù', "-.--"}, /* yi */
193 {'Ø', "-..-"}, /* myakhkij znak */
194 {'Ü', "..-.."}, /* ae */
195 {'À', "..--"}, /* yu */
196 {'Ñ', ".-.-"}, /* ya */
201 void show(const char *), play(const char *), morse(char);
202 void ttyout(const char *);
203 void sighandler(int);
205 #define GETOPTOPTS "d:ef:sw:"
207 "usage: morse [-s] [-e] [-d device] [-w speed] [-f frequency] [string ...]\n"
209 static int pflag, sflag, eflag;
210 static int wpm = 20; /* words per minute */
211 #define FREQUENCY 600
212 static int freq = FREQUENCY;
213 static char *device; /* for tty-controlled generator */
217 #define WORD_SPACE (7 - CHAR_SPACE - 1)
218 static float dot_clock;
220 struct termios otty, ntty;
226 #define GETOPTOPTS "d:ef:psw:"
229 "usage: morse [-s] [-p] [-e] [-d device] [-w speed] [-f frequency] [string ...]\n"
232 static const struct morsetab *hightab;
235 main(int argc, char **argv)
240 while ((ch = getopt(argc, argv, GETOPTOPTS)) != -1)
247 setvbuf(stdout, 0, _IONBF, 0);
265 fputs(USAGE, stderr);
268 if ((pflag || device) && sflag) {
269 fputs("morse: only one of -p, -d and -s allowed\n", stderr);
272 if ((pflag || device) && ((wpm < 1) || (wpm > 60))) {
273 fputs("morse: insane speed\n", stderr);
276 if ((pflag || device) && (freq == 0))
281 if ((spkr = open(SPEAKER, O_WRONLY, 0)) == -1) {
288 if ((line = open(device, O_WRONLY | O_NONBLOCK)) == -1) {
289 perror("open tty line");
292 if (tcgetattr(line, &otty) == -1) {
293 perror("tcgetattr() failed");
297 ntty.c_cflag |= CLOCAL;
298 tcsetattr(line, TCSANOW, &ntty);
299 lflags = fcntl(line, F_GETFL);
300 lflags &= ~O_NONBLOCK;
301 fcntl(line, F_SETFL, &lflags);
302 ioctl(line, TIOCMGET, &lflags);
303 lflags &= ~TIOCM_RTS;
305 ioctl(line, TIOCMSET, &lflags);
306 (void)signal(SIGHUP, sighandler);
307 (void)signal(SIGINT, sighandler);
308 (void)signal(SIGQUIT, sighandler);
309 (void)signal(SIGTERM, sighandler);
311 if (pflag || device) {
312 dot_clock = wpm / 2.4; /* dots/sec */
313 dot_clock = 1 / dot_clock; /* duration of a dot */
314 dot_clock = dot_clock / 2; /* dot_clock runs at twice */
316 dot_clock = dot_clock * 100; /* scale for ioctl */
322 if (setlocale(LC_CTYPE, "") != NULL &&
323 *(codeset = nl_langinfo(CODESET)) != '\0') {
324 if (strcmp(codeset, "KOI8-R") == 0)
326 else if (strcmp(codeset, "ISO8859-1") == 0 ||
327 strcmp(codeset, "ISO8859-15") == 0)
328 hightab = iso8859tab;
333 for (p = *argv; *p; ++p) {
343 while ((ch = getchar()) != EOF) {
350 tcsetattr(line, TCSANOW, &otty);
357 const struct morsetab *m;
359 if (isalpha((unsigned char)c))
360 c = tolower((unsigned char)c);
361 if ((c == '\r') || (c == '\n'))
375 for (m = ((unsigned char)c < 0x80? mtab: hightab);
376 m != NULL && m->inchar != '\0';
378 if (m->inchar == c) {
396 printf(" %s", *s == '.' ? "dit" : "dah");
406 for (c = s; *c != '\0'; c++) {
409 sound.frequency = freq;
410 sound.duration = dot_clock;
413 sound.frequency = freq;
414 sound.duration = dot_clock * DASH_LEN;
418 sound.duration = dot_clock * WORD_SPACE;
423 if (sound.duration) {
424 if (ioctl(spkr, SPKRTONE, &sound) == -1) {
425 perror("ioctl play");
430 sound.duration = dot_clock;
431 if (ioctl(spkr, SPKRTONE, &sound) == -1) {
432 perror("ioctl rest");
437 sound.duration = dot_clock * CHAR_SPACE;
438 ioctl(spkr, SPKRTONE, &sound);
443 ttyout(const char *s)
446 int duration, on, lflags;
448 for (c = s; *c != '\0'; c++) {
452 duration = dot_clock;
456 duration = dot_clock * DASH_LEN;
460 duration = dot_clock * WORD_SPACE;
467 ioctl(line, TIOCMGET, &lflags);
469 ioctl(line, TIOCMSET, &lflags);
474 ioctl(line, TIOCMGET, &lflags);
475 lflags &= ~TIOCM_RTS;
476 ioctl(line, TIOCMSET, &lflags);
477 duration = dot_clock * 10000;
480 duration = dot_clock * CHAR_SPACE * 10000;
485 sighandler(int signo)
488 ioctl(line, TIOCMSET, &olflags);
489 tcsetattr(line, TCSANOW, &otty);
491 signal(signo, SIG_DFL);
492 (void)kill(getpid(), signo);