morse.c revision 54622
12490Sjkh/*
22490Sjkh * Copyright (c) 1988, 1993
32490Sjkh *	The Regents of the University of California.  All rights reserved.
42490Sjkh *
52490Sjkh * Redistribution and use in source and binary forms, with or without
62490Sjkh * modification, are permitted provided that the following conditions
72490Sjkh * are met:
82490Sjkh * 1. Redistributions of source code must retain the above copyright
92490Sjkh *    notice, this list of conditions and the following disclaimer.
102490Sjkh * 2. Redistributions in binary form must reproduce the above copyright
112490Sjkh *    notice, this list of conditions and the following disclaimer in the
122490Sjkh *    documentation and/or other materials provided with the distribution.
132490Sjkh * 3. All advertising materials mentioning features or use of this software
142490Sjkh *    must display the following acknowledgement:
152490Sjkh *	This product includes software developed by the University of
162490Sjkh *	California, Berkeley and its contributors.
172490Sjkh * 4. Neither the name of the University nor the names of its contributors
182490Sjkh *    may be used to endorse or promote products derived from this software
192490Sjkh *    without specific prior written permission.
202490Sjkh *
212490Sjkh * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
222490Sjkh * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
232490Sjkh * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
242490Sjkh * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
252490Sjkh * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
262490Sjkh * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
272490Sjkh * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
282490Sjkh * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
292490Sjkh * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
302490Sjkh * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
312490Sjkh * SUCH DAMAGE.
322490Sjkh */
332490Sjkh
3410352Sjoerg/*
3510352Sjoerg * Taught to send *real* morse by Lyndon Nerenberg (VE7TCP/VE6BBM)
3610352Sjoerg * <lyndon@orthanc.com>
3710352Sjoerg */
3810352Sjoerg
392490Sjkh#ifndef lint
4053920Sbillfstatic const char copyright[] =
412490Sjkh"@(#) Copyright (c) 1988, 1993\n\
422490Sjkh	The Regents of the University of California.  All rights reserved.\n";
432490Sjkh#endif /* not lint */
442490Sjkh
452490Sjkh#ifndef lint
4653920Sbillf#if 0
472490Sjkhstatic char sccsid[] = "@(#)morse.c	8.1 (Berkeley) 5/31/93";
4853920Sbillf#endif
4953920Sbillfstatic const char rcsid[] =
5053920Sbillf "$FreeBSD: head/games/morse/morse.c 54622 1999-12-15 04:28:10Z billf $";
512490Sjkh#endif /* not lint */
522490Sjkh
532490Sjkh#include <stdio.h>
542490Sjkh#include <ctype.h>
5510352Sjoerg#include <locale.h>
5610352Sjoerg#include <stdlib.h>
5735857Sjb#include <string.h>
5854622Sbillf#include <unistd.h>
592490Sjkh
6010352Sjoerg#ifdef SPEAKER
6110352Sjoerg#include <machine/speaker.h>
6210352Sjoerg#include <fcntl.h>
6310352Sjoerg#endif
6410352Sjoerg
6510352Sjoergstruct morsetab {
6610352Sjoerg	char            inchar;
6710352Sjoerg	char           *morse;
682490Sjkh};
692490Sjkh
7054622Sbillfstatic const struct morsetab mtab[] = {
712490Sjkh
7210352Sjoerg	/* letters */
7310352Sjoerg
7454622Sbillf	{'a', ".-"},
7554622Sbillf	{'b', "-..."},
7654622Sbillf	{'c', "-.-."},
7754622Sbillf	{'d', "-.."},
7854622Sbillf	{'e', "."},
7954622Sbillf	{'f', "..-."},
8054622Sbillf	{'g', "--."},
8154622Sbillf	{'h', "...."},
8254622Sbillf	{'i', ".."},
8354622Sbillf	{'j', ".---"},
8454622Sbillf	{'k', "-.-"},
8554622Sbillf	{'l', ".-.."},
8654622Sbillf	{'m', "--"},
8754622Sbillf	{'n', "-."},
8854622Sbillf	{'o', "---"},
8954622Sbillf	{'p', ".--."},
9054622Sbillf	{'q', "--.-"},
9154622Sbillf	{'r', ".-."},
9254622Sbillf	{'s', "..."},
9354622Sbillf	{'t', "-"},
9454622Sbillf	{'u', "..-"},
9554622Sbillf	{'v', "...-"},
9654622Sbillf	{'w', ".--"},
9754622Sbillf	{'x', "-..-"},
9854622Sbillf	{'y', "-.--"},
9954622Sbillf	{'z', "--.."},
10010352Sjoerg
10110352Sjoerg	/* digits */
10210352Sjoerg
10354622Sbillf	{'0', "-----"},
10454622Sbillf	{'1', ".----"},
10554622Sbillf	{'2', "..---"},
10654622Sbillf	{'3', "...--"},
10754622Sbillf	{'4', "....-"},
10854622Sbillf	{'5', "....."},
10954622Sbillf	{'6', "-...."},
11054622Sbillf	{'7', "--..."},
11154622Sbillf	{'8', "---.."},
11254622Sbillf	{'9', "----."},
11310352Sjoerg
11410352Sjoerg	/* punctuation */
11510352Sjoerg
11654622Sbillf	{',', "--..--"},
11754622Sbillf	{'.', ".-.-.-"},
11854622Sbillf	{'?', "..--.."},
11954622Sbillf	{'/', "-..-."},
12054622Sbillf	{'-', "-....-"},
12154622Sbillf	{'=', "-...-"},		/* BT */
12254622Sbillf	{':', "---..."},
12354622Sbillf	{';', "-.-.-."},
12454622Sbillf	{'(', "-.--."},		/* KN */
12554622Sbillf	{')', "-.--.-"},
12654622Sbillf	{'$', "...-..-"},
12754622Sbillf	{'+', ".-.-."},		/* AR */
12810352Sjoerg
12910352Sjoerg	/* prosigns without already assigned values */
13010352Sjoerg
13154622Sbillf	{'#', ".-..."},		/* AS */
13254622Sbillf	{'@', "...-.-"},	/* SK */
13354622Sbillf	{'*', "...-."},		/* VE */
13454622Sbillf	{'%', "-...-.-"},	/* BK */
13510352Sjoerg
13654622Sbillf	{'\0', ""}
13710352Sjoerg};
13810352Sjoerg
13910352Sjoerg
14054622Sbillfstatic const struct morsetab iso8859tab[] = {
14154622Sbillf	{'�', ".--.-"},
14254622Sbillf	{'�', ".--.-"},
14354622Sbillf	{'�', ".--.-"},
14454622Sbillf	{'�', ".-.-"},
14554622Sbillf	{'�', "-.-.."},
14654622Sbillf	{'�', "..-.."},
14754622Sbillf	{'�', "..-.."},
14854622Sbillf	{'�', "-..-."},
14954622Sbillf	{'�', "---."},
15054622Sbillf	{'�', "..--"},
15110352Sjoerg
15254622Sbillf	{'\0', ""}
15310352Sjoerg};
15410352Sjoerg
15554622Sbillfstatic const struct morsetab koi8rtab[] = {
15610352Sjoerg	/*
15710352Sjoerg	 * the cyrillic alphabet; you'll need a KOI8R font in order
15810352Sjoerg	 * to see the actual characters
15910352Sjoerg	 */
16054622Sbillf	{'�', ".-"},		/* a */
16154622Sbillf	{'�', "-..."},	/* be */
16254622Sbillf	{'�', ".--"},	/* ve */
16354622Sbillf	{'�', "--."},	/* ge */
16454622Sbillf	{'�', "-.."},	/* de */
16554622Sbillf	{'�', "."},		/* ye */
16654622Sbillf	{'�', "."},         	/* yo, the same as ye */
16754622Sbillf	{'�', "...-"},	/* she */
16854622Sbillf	{'�', "--.."},	/* ze */
16954622Sbillf	{'�', ".."},		/* i */
17054622Sbillf	{'�', ".---"},	/* i kratkoye */
17154622Sbillf	{'�', "-.-"},	/* ka */
17254622Sbillf	{'�', ".-.."},	/* el */
17354622Sbillf	{'�', "--"},		/* em */
17454622Sbillf	{'�', "-."},		/* en */
17554622Sbillf	{'�', "---"},	/* o */
17654622Sbillf	{'�', ".--."},	/* pe */
17754622Sbillf	{'�', ".-."},	/* er */
17854622Sbillf	{'�', "..."},	/* es */
17954622Sbillf	{'�', "-"},		/* te */
18054622Sbillf	{'�', "..-"},	/* u */
18154622Sbillf	{'�', "..-."},	/* ef */
18254622Sbillf	{'�', "...."},	/* kha */
18354622Sbillf	{'�', "-.-."},	/* ce */
18454622Sbillf	{'�', "---."},	/* che */
18554622Sbillf	{'�', "----"},	/* sha */
18654622Sbillf	{'�', "--.-"},	/* shcha */
18754622Sbillf	{'�', "-.--"},	/* yi */
18854622Sbillf	{'�', "-..-"},	/* myakhkij znak */
18954622Sbillf	{'�', "..-.."},	/* ae */
19054622Sbillf	{'�', "..--"},	/* yu */
19154622Sbillf	{'�', ".-.-"},	/* ya */
19210352Sjoerg
19354622Sbillf	{'\0', ""}
19410352Sjoerg};
19510352Sjoerg
19610352Sjoergvoid            show(const char *), play(const char *), morse(char);
19710352Sjoerg
19810352Sjoergstatic int      pflag, sflag;
19910352Sjoergstatic int      wpm = 20;	/* words per minute */
20010352Sjoerg#define FREQUENCY 600
20110352Sjoergstatic int      freq = FREQUENCY;
20210352Sjoerg
20310352Sjoerg#ifdef SPEAKER
20410352Sjoerg#define DASH_LEN 3
20510352Sjoerg#define CHAR_SPACE 3
20610352Sjoerg#define WORD_SPACE (7 - CHAR_SPACE - 1)
20710352Sjoergstatic float    dot_clock;
20810352Sjoergint             spkr;
20910352Sjoergtone_t          sound;
21010352Sjoerg#endif
21110352Sjoerg
21254622Sbillfstatic const struct morsetab *hightab = iso8859tab;
21310352Sjoerg
21410352Sjoergint
21510352Sjoergmain(int argc, char **argv)
2162490Sjkh{
21753210Sbillf	int    ch;
21853210Sbillf	char  *p;
2192490Sjkh
22033937Sjkh	while ((ch = getopt(argc, argv, "spw:f:")) != -1)
22110352Sjoerg		switch ((char) ch) {
22210352Sjoerg		case 'f':
22310352Sjoerg			freq = atoi(optarg);
22410352Sjoerg			break;
22510352Sjoerg		case 'p':
22610352Sjoerg			pflag = 1;
22710352Sjoerg			break;
2282490Sjkh		case 's':
2292490Sjkh			sflag = 1;
2302490Sjkh			break;
23110352Sjoerg		case 'w':
23210352Sjoerg			wpm = atoi(optarg);
23310352Sjoerg			break;
2342490Sjkh		case '?':
2352490Sjkh		default:
23610352Sjoerg			fputs("usage: morse [-s] [-p] [-w speed] [-f frequency] [string ...]\n", stderr);
2372490Sjkh			exit(1);
2382490Sjkh		}
23910352Sjoerg	if (pflag && sflag) {
24010352Sjoerg		fputs("morse: only one of -p and -s allowed\n", stderr);
24110352Sjoerg		exit(1);
24210352Sjoerg	}
24310352Sjoerg	if (pflag && ((wpm < 1) || (wpm > 60))) {
24410352Sjoerg		fputs("morse: insane speed\n", stderr);
24510352Sjoerg		exit(1);
24610352Sjoerg	}
24710352Sjoerg	if (pflag && (freq == 0))
24810352Sjoerg		freq = FREQUENCY;
24910352Sjoerg
25010352Sjoerg#ifdef SPEAKER
25110352Sjoerg	if (pflag) {
25210352Sjoerg		if ((spkr = open(SPEAKER, O_WRONLY, 0)) == -1) {
25310352Sjoerg			perror(SPEAKER);
25410352Sjoerg			exit(1);
25510352Sjoerg		}
25610352Sjoerg		dot_clock = wpm / 2.4;		/* dots/sec */
25710352Sjoerg		dot_clock = 1 / dot_clock;	/* duration of a dot */
25810352Sjoerg		dot_clock = dot_clock / 2;	/* dot_clock runs at twice */
25910352Sjoerg						/* the dot rate */
26010352Sjoerg		dot_clock = dot_clock * 100;	/* scale for ioctl */
26110352Sjoerg	}
26210352Sjoerg#endif
2632490Sjkh	argc -= optind;
2642490Sjkh	argv += optind;
2652490Sjkh
26629018Sache	if((p = getenv("LC_CTYPE")) ||
26729018Sache	   (p = getenv("LC_ALL")) ||
26829018Sache	   (p = getenv("LANG"))) {
26929018Sache		if(strlen(p) >= sizeof(".KOI8-R") &&
27029018Sache		   strcasecmp(&p[strlen(p) + 1 - sizeof(".KOI8-R")], ".KOI8-R") == 0)
27110352Sjoerg			hightab = koi8rtab;
27210352Sjoerg	}
27329018Sache	(void) setlocale(LC_CTYPE, "");
27410352Sjoerg
27510352Sjoerg	if (*argv) {
2762490Sjkh		do {
27710352Sjoerg			for (p = *argv; *p; ++p) {
27829018Sache				morse(*p);
27910352Sjoerg			}
28029018Sache			morse(' ');
2812490Sjkh		} while (*++argv);
28210352Sjoerg	} else {
28310352Sjoerg		while ((ch = getchar()) != EOF)
28410352Sjoerg			morse(ch);
28510352Sjoerg	}
28610352Sjoerg	exit(0);
2872490Sjkh}
2882490Sjkh
28910352Sjoergvoid
29010352Sjoergmorse(char c)
2912490Sjkh{
29254622Sbillf	const struct morsetab *m;
29310352Sjoerg
29429018Sache	if (isalpha((unsigned char)c))
29529018Sache		c = tolower((unsigned char)c);
29610352Sjoerg	if ((c == '\r') || (c == '\n'))
29710352Sjoerg		c = ' ';
29810352Sjoerg	if (c == ' ') {
29910352Sjoerg		if (pflag) {
30010352Sjoerg			play(" ");
30110352Sjoerg			return;
30210352Sjoerg		} else {
30310352Sjoerg			show("");
30410352Sjoerg			return;
30510352Sjoerg		}
30610352Sjoerg	}
30710352Sjoerg	for (m = ((unsigned char)c < 0x80? mtab: hightab);
30810352Sjoerg	     m->inchar != '\0';
30910352Sjoerg	     m++) {
31010352Sjoerg		if (m->inchar == c) {
31110352Sjoerg			if (pflag) {
31210352Sjoerg				play(m->morse);
31310352Sjoerg			} else
31410352Sjoerg				show(m->morse);
31510352Sjoerg		}
31610352Sjoerg	}
3172490Sjkh}
3182490Sjkh
31910352Sjoergvoid
32010352Sjoergshow(const char *s)
3212490Sjkh{
3222490Sjkh	if (sflag)
3232490Sjkh		printf(" %s", s);
32410352Sjoerg	else
32510352Sjoerg		for (; *s; ++s)
32610352Sjoerg			printf(" %s", *s == '.' ? "dit" : "dah");
32710352Sjoerg	printf("\n");
3282490Sjkh}
32910352Sjoerg
33010352Sjoergvoid
33110352Sjoergplay(const char *s)
33210352Sjoerg{
33310352Sjoerg#ifdef SPEAKER
33410352Sjoerg	const char *c;
33510352Sjoerg
33610352Sjoerg	for (c = s; *c != '\0'; c++) {
33729018Sache		switch (*c) {
33810352Sjoerg		case '.':
33910352Sjoerg			sound.frequency = freq;
34010352Sjoerg			sound.duration = dot_clock;
34110352Sjoerg			break;
34210352Sjoerg		case '-':
34310352Sjoerg			sound.frequency = freq;
34410352Sjoerg			sound.duration = dot_clock * DASH_LEN;
34510352Sjoerg			break;
34610352Sjoerg		case ' ':
34710352Sjoerg			sound.frequency = 0;
34810352Sjoerg			sound.duration = dot_clock * WORD_SPACE;
34910352Sjoerg			break;
35010352Sjoerg		default:
35110352Sjoerg			sound.duration = 0;
35210352Sjoerg		}
35310352Sjoerg		if (sound.duration) {
35410352Sjoerg			if (ioctl(spkr, SPKRTONE, &sound) == -1) {
35510352Sjoerg				perror("ioctl play");
35610352Sjoerg				exit(1);
35710352Sjoerg			}
35810352Sjoerg		}
35910352Sjoerg		sound.frequency = 0;
36010352Sjoerg		sound.duration = dot_clock;
36110352Sjoerg		if (ioctl(spkr, SPKRTONE, &sound) == -1) {
36210352Sjoerg			perror("ioctl rest");
36310352Sjoerg			exit(1);
36410352Sjoerg		}
36510352Sjoerg	}
36610352Sjoerg	sound.frequency = 0;
36710352Sjoerg	sound.duration = dot_clock * CHAR_SPACE;
36810352Sjoerg	ioctl(spkr, SPKRTONE, &sound);
36910352Sjoerg#endif
37010352Sjoerg}
371