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
33 * @(#) Copyright (c) 1988, 1993 The Regents of the University of California. All rights reserved.
34 * @(#)morse.c 8.1 (Berkeley) 5/31/93
35 * $FreeBSD: src/games/morse/morse.c,v 1.12.2.2 2002/03/12 17:45:15 phantom Exp $
36 * $DragonFly: src/games/morse/morse.c,v 1.3 2005/04/25 16:10:24 liamfoy Exp $
40 * Taught to send *real* morse by Lyndon Nerenberg (VE7TCP/VE6BBM)
41 * <lyndon@orthanc.com>
58 #include <machine/speaker.h>
66 static const struct morsetab mtab
[] = {
117 {'=', "-...-"}, /* BT */
120 {'(', "-.--."}, /* KN */
123 {'+', ".-.-."}, /* AR */
125 /* prosigns without already assigned values */
127 {'#', ".-..."}, /* AS */
128 {'@', "...-.-"}, /* SK */
129 {'*', "...-."}, /* VE */
130 {'%', "-...-.-"}, /* BK */
136 static const struct morsetab iso8859tab
[] = {
151 static const struct morsetab koi8rtab
[] = {
153 * the cyrillic alphabet; you'll need a KOI8R font in order
154 * to see the actual characters
157 {'Â', "-..."}, /* be */
158 {'×', ".--"}, /* ve */
159 {'Ç', "--."}, /* ge */
160 {'Ä', "-.."}, /* de */
162 {'£', "."}, /* yo, the same as ye */
163 {'Ö', "...-"}, /* she */
164 {'Ú', "--.."}, /* ze */
166 {'Ê', ".---"}, /* i kratkoye */
167 {'Ë', "-.-"}, /* ka */
168 {'Ì', ".-.."}, /* el */
169 {'Í', "--"}, /* em */
170 {'Î', "-."}, /* en */
171 {'Ï', "---"}, /* o */
172 {'Ð', ".--."}, /* pe */
173 {'Ò', ".-."}, /* er */
174 {'Ó', "..."}, /* es */
176 {'Õ', "..-"}, /* u */
177 {'Æ', "..-."}, /* ef */
178 {'È', "...."}, /* kha */
179 {'Ã', "-.-."}, /* ce */
180 {'Þ', "---."}, /* che */
181 {'Û', "----"}, /* sha */
182 {'Ý', "--.-"}, /* shcha */
183 {'Ù', "-.--"}, /* yi */
184 {'Ø', "-..-"}, /* myakhkij znak */
185 {'Ü', "..-.."}, /* ae */
186 {'À', "..--"}, /* yu */
187 {'Ñ', ".-.-"}, /* ya */
192 void show(const char *), play(const char *), morse(char);
193 void ttyout(const char *);
194 void sighandler(int);
196 #define GETOPTOPTS "d:ef:sw:"
198 "usage: morse [-s] [-e] [-d device] [-w speed] [-f frequency] [string ...]\n"
200 static int pflag
, sflag
, eflag
;
201 static int wpm
= 20; /* words per minute */
202 #define FREQUENCY 600
203 static int freq
= FREQUENCY
;
204 static char *device
; /* for tty-controlled generator */
208 #define WORD_SPACE (7 - CHAR_SPACE - 1)
209 static float dot_clock
;
211 struct termios otty
, ntty
;
217 #define GETOPTOPTS "d:ef:psw:"
220 "usage: morse [-s] [-p] [-e] [-d device] [-w speed] [-f frequency] [string ...]\n"
223 static const struct morsetab
*hightab
;
226 main(int argc
, char **argv
)
231 while ((ch
= getopt(argc
, argv
, GETOPTOPTS
)) != -1)
238 setvbuf(stdout
, 0, _IONBF
, 0);
256 fputs(USAGE
, stderr
);
259 if ((pflag
|| device
) && sflag
) {
260 fputs("morse: only one of -p, -d and -s allowed\n", stderr
);
263 if ((pflag
|| device
) && ((wpm
< 1) || (wpm
> 60))) {
264 fputs("morse: insane speed\n", stderr
);
267 if ((pflag
|| device
) && (freq
== 0))
272 if ((spkr
= open(SPEAKER
, O_WRONLY
, 0)) == -1) {
279 if ((line
= open(device
, O_WRONLY
| O_NONBLOCK
)) == -1) {
280 perror("open tty line");
283 if (tcgetattr(line
, &otty
) == -1) {
284 perror("tcgetattr() failed");
288 ntty
.c_cflag
|= CLOCAL
;
289 tcsetattr(line
, TCSANOW
, &ntty
);
290 lflags
= fcntl(line
, F_GETFL
);
291 lflags
&= ~O_NONBLOCK
;
292 fcntl(line
, F_SETFL
, &lflags
);
293 ioctl(line
, TIOCMGET
, &lflags
);
294 lflags
&= ~TIOCM_RTS
;
296 ioctl(line
, TIOCMSET
, &lflags
);
297 (void)signal(SIGHUP
, sighandler
);
298 (void)signal(SIGINT
, sighandler
);
299 (void)signal(SIGQUIT
, sighandler
);
300 (void)signal(SIGTERM
, sighandler
);
302 if (pflag
|| device
) {
303 dot_clock
= wpm
/ 2.4; /* dots/sec */
304 dot_clock
= 1 / dot_clock
; /* duration of a dot */
305 dot_clock
= dot_clock
/ 2; /* dot_clock runs at twice */
307 dot_clock
= dot_clock
* 100; /* scale for ioctl */
313 if (setlocale(LC_CTYPE
, "") != NULL
&&
314 *(codeset
= nl_langinfo(CODESET
)) != '\0') {
315 if (strcmp(codeset
, "KOI8-R") == 0)
317 else if (strcmp(codeset
, "ISO8859-1") == 0 ||
318 strcmp(codeset
, "ISO8859-15") == 0)
319 hightab
= iso8859tab
;
324 for (p
= *argv
; *p
; ++p
) {
334 while ((ch
= getchar()) != EOF
) {
341 tcsetattr(line
, TCSANOW
, &otty
);
348 const struct morsetab
*m
;
350 if (isalpha((unsigned char)c
))
351 c
= tolower((unsigned char)c
);
352 if ((c
== '\r') || (c
== '\n'))
366 for (m
= ((unsigned char)c
< 0x80? mtab
: hightab
);
367 m
!= NULL
&& m
->inchar
!= '\0';
369 if (m
->inchar
== c
) {
387 printf(" %s", *s
== '.' ? "dit" : "dah");
397 for (c
= s
; *c
!= '\0'; c
++) {
400 sound
.frequency
= freq
;
401 sound
.duration
= dot_clock
;
404 sound
.frequency
= freq
;
405 sound
.duration
= dot_clock
* DASH_LEN
;
409 sound
.duration
= dot_clock
* WORD_SPACE
;
414 if (sound
.duration
) {
415 if (ioctl(spkr
, SPKRTONE
, &sound
) == -1) {
416 perror("ioctl play");
421 sound
.duration
= dot_clock
;
422 if (ioctl(spkr
, SPKRTONE
, &sound
) == -1) {
423 perror("ioctl rest");
428 sound
.duration
= dot_clock
* CHAR_SPACE
;
429 ioctl(spkr
, SPKRTONE
, &sound
);
434 ttyout(const char *s
)
437 int duration
, on
, lflags
;
439 for (c
= s
; *c
!= '\0'; c
++) {
443 duration
= dot_clock
;
447 duration
= dot_clock
* DASH_LEN
;
451 duration
= dot_clock
* WORD_SPACE
;
458 ioctl(line
, TIOCMGET
, &lflags
);
460 ioctl(line
, TIOCMSET
, &lflags
);
465 ioctl(line
, TIOCMGET
, &lflags
);
466 lflags
&= ~TIOCM_RTS
;
467 ioctl(line
, TIOCMSET
, &lflags
);
468 duration
= dot_clock
* 10000;
471 duration
= dot_clock
* CHAR_SPACE
* 10000;
476 sighandler(int signo
)
479 ioctl(line
, TIOCMSET
, &olflags
);
480 tcsetattr(line
, TCSANOW
, &otty
);
482 signal(signo
, SIG_DFL
);
483 (void)kill(getpid(), signo
);