morse.c revision 29018
11590Srgrimes/*
21590Srgrimes * Copyright (c) 1988, 1993
31590Srgrimes *	The Regents of the University of California.  All rights reserved.
41590Srgrimes *
51590Srgrimes * Redistribution and use in source and binary forms, with or without
61590Srgrimes * modification, are permitted provided that the following conditions
71590Srgrimes * are met:
81590Srgrimes * 1. Redistributions of source code must retain the above copyright
91590Srgrimes *    notice, this list of conditions and the following disclaimer.
101590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
111590Srgrimes *    notice, this list of conditions and the following disclaimer in the
121590Srgrimes *    documentation and/or other materials provided with the distribution.
131590Srgrimes * 3. All advertising materials mentioning features or use of this software
141590Srgrimes *    must display the following acknowledgement:
151590Srgrimes *	This product includes software developed by the University of
161590Srgrimes *	California, Berkeley and its contributors.
171590Srgrimes * 4. Neither the name of the University nor the names of its contributors
181590Srgrimes *    may be used to endorse or promote products derived from this software
191590Srgrimes *    without specific prior written permission.
201590Srgrimes *
211590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
221590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
231590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
241590Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
251590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
261590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
271590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
281590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
291590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
301590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
311590Srgrimes * SUCH DAMAGE.
321590Srgrimes */
332537Spst
342537Spst/*
352537Spst * Taught to send *real* morse by Lyndon Nerenberg (VE7TCP/VE6BBM)
362537Spst * <lyndon@orthanc.com>
372537Spst */
382537Spst
392537Spst#ifndef lint
402537Spststatic char copyright[] =
412537Spst"@(#) Copyright (c) 1988, 1993\n\
422537Spst	The Regents of the University of California.  All rights reserved.\n";
431590Srgrimes#endif /* not lint */
4467467Sru
451590Srgrimes#ifndef lint
461590Srgrimesstatic char sccsid[] = "@(#)morse.c	8.1 (Berkeley) 5/31/93";
471590Srgrimes#endif /* not lint */
481590Srgrimes
4987628Sdwmalone#include <stdio.h>
501590Srgrimes#include <ctype.h>
5187628Sdwmalone#include <locale.h>
5272109Scharnier#include <stdlib.h>
5387628Sdwmalone
541590Srgrimes#ifdef SPEAKER
5587628Sdwmalone#include <machine/speaker.h>
5687628Sdwmalone#include <fcntl.h>
5787628Sdwmalone#endif
581590Srgrimes
591590Srgrimesstruct morsetab {
601590Srgrimes	char            inchar;
611590Srgrimes	char           *morse;
621590Srgrimes};
631590Srgrimes
641590Srgrimesstatic struct morsetab mtab[] = {
651590Srgrimes
662537Spst	/* letters */
672537Spst
682537Spst	'a', ".-",
692537Spst	'b', "-...",
701590Srgrimes	'c', "-.-.",
711590Srgrimes	'd', "-..",
72100521Sume	'e', ".",
73100521Sume	'f', "..-.",
7423693Speter	'g', "--.",
7523693Speter	'h', "....",
761590Srgrimes	'i', "..",
771590Srgrimes	'j', ".---",
781590Srgrimes	'k', "-.-",
791590Srgrimes	'l', ".-..",
8023693Speter	'm', "--",
8123693Speter	'n', "-.",
82202191Sed	'o', "---",
8311759Sache	'p', ".--.",
8423693Speter	'q', "--.-",
851590Srgrimes	'r', ".-.",
8664775Sbrian	's', "...",
871590Srgrimes	't', "-",
881590Srgrimes	'u', "..-",
891590Srgrimes	'v', "...-",
90168632Sdes	'w', ".--",
91106250Ssobomax	'x', "-..-",
9274586Sache	'y', "-.--",
931590Srgrimes	'z', "--..",
94150316Sdds
951590Srgrimes	/* digits */
9692920Simp
9792920Simp	'0', "-----",
9892920Simp	'1', ".----",
9992920Simp	'2', "..---",
1001590Srgrimes	'3', "...--",
10187229Smarkm	'4', "....-",
102102944Sdwmalone	'5', ".....",
1031590Srgrimes	'6', "-....",
1041590Srgrimes	'7', "--...",
1051590Srgrimes	'8', "---..",
1062589Spst	'9', "----.",
1072537Spst
108168635Sdes	/* punctuation */
1091590Srgrimes
110100521Sume	',', "--..--",
111100521Sume	'.', ".-.-.-",
112100521Sume	'?', "..--..",
113100521Sume	'/', "-..-.",
114100521Sume	'-', "-....-",
115100521Sume	'=', "-...-",		/* BT */
11699249Smini	':', "---...",
11799249Smini	';', "-.-.-.",
11899249Smini	'(', "-.--.",		/* KN */
119117010Sjmallett	')', "-.--.-",
120117010Sjmallett	'$', "...-..-",
121117010Sjmallett	'+', ".-.-.",		/* AR */
1221590Srgrimes
1231590Srgrimes	/* prosigns without already assigned values */
1241590Srgrimes
1251590Srgrimes	'#', ".-...",		/* AS */
1261590Srgrimes	'@', "...-.-",		/* SK */
1271590Srgrimes	'*', "...-.",		/* VE */
1281590Srgrimes	'%', "-...-.-",		/* BK */
1291590Srgrimes
1301590Srgrimes	'\0', ""
1311590Srgrimes};
1321590Srgrimes
1331590Srgrimes
1342537Spststatic struct morsetab iso8859tab[] = {
1352537Spst	'�', ".--.-",
1362537Spst	'�', ".--.-",
1372537Spst	'�', ".--.-",
1382537Spst	'�', ".-.-",
1392537Spst	'�', "-.-..",
1401590Srgrimes	'�', "..-..",
1411590Srgrimes	'�', "..-..",
14227169Scharnier	'�', "-..-.",
1431590Srgrimes	'�', "---.",
1441590Srgrimes	'�', "..--",
1452589Spst
1462589Spst	'\0', ""
1472589Spst};
14827169Scharnier
149102944Sdwmalonestatic struct morsetab koi8rtab[] = {
15027169Scharnier	/*
151146466Sru	 * the cyrillic alphabet; you'll need a KOI8R font in order
152168635Sdes	 * to see the actual characters
15327169Scharnier	 */
15427169Scharnier	'�', ".-",		/* a */
15527169Scharnier	'�', "-...",		/* be */
15627169Scharnier	'�', ".--",		/* ve */
157102944Sdwmalone	'�', "--.",		/* ge */
1582589Spst	'�', "-..",		/* de */
15927169Scharnier	'�', ".",		/* ye */
1602589Spst	'�', ".",               /* yo, the same as ye */
16146662Sobrien	'�', "...-",		/* she */
16287229Smarkm	'�', "--..",		/* ze */
1632589Spst	'�', "..",		/* i */
16446662Sobrien	'�', ".---",		/* i kratkoye */
165150316Sdds	'�', "-.-",		/* ka */
16646662Sobrien	'�', ".-..",		/* el */
167220971Ssimon	'�', "--",		/* em */
168220971Ssimon	'�', "-.",		/* en */
169220971Ssimon	'�', "---",		/* o */
170220971Ssimon	'�', ".--.",		/* pe */
17146662Sobrien	'�', ".-.",		/* er */
172220971Ssimon	'�', "...",		/* es */
173220971Ssimon	'�', "-",		/* te */
174220971Ssimon	'�', "..-",		/* u */
175220971Ssimon	'�', "..-.",		/* ef */
17646662Sobrien	'�', "....",		/* kha */
17746662Sobrien	'�', "-.-.",		/* ce */
17846662Sobrien	'�', "---.",		/* che */
17911811Sache	'�', "----",		/* sha */
18011759Sache	'�', "--.-",		/* shcha */
1812589Spst	'�', "-.--",		/* yi */
1822589Spst	'�', "-..-",		/* myakhkij znak */
1832589Spst	'�', "..-..",		/* ae */
1842589Spst	'�', "..--",		/* yu */
1852589Spst	'�', ".-.-",		/* ya */
1862589Spst
1872589Spst	'\0', ""
1882589Spst};
18987229Smarkm
1902589Spstvoid            show(const char *), play(const char *), morse(char);
1912589Spst
1922589Spststatic int      pflag, sflag;
1932589Spststatic int      wpm = 20;	/* words per minute */
1942589Spst#define FREQUENCY 600
1952589Spststatic int      freq = FREQUENCY;
1962589Spst
1972589Spst#ifdef SPEAKER
1981590Srgrimes#define DASH_LEN 3
1991590Srgrimes#define CHAR_SPACE 3
2001590Srgrimes#define WORD_SPACE (7 - CHAR_SPACE - 1)
2011590Srgrimesstatic float    dot_clock;
2021590Srgrimesint             spkr;
2031590Srgrimestone_t          sound;
2041590Srgrimes#endif
2051590Srgrimes
2061590Srgrimesstatic struct morsetab *hightab = iso8859tab;
2071590Srgrimes
2081590Srgrimesint
2091590Srgrimesmain(int argc, char **argv)
2101590Srgrimes{
2111590Srgrimes	extern char    *optarg;
2121590Srgrimes	extern int      optind;
2131590Srgrimes	register int    ch;
2141590Srgrimes	register char  *p;
2151590Srgrimes
2161590Srgrimes	while ((ch = getopt(argc, argv, "spw:f:")) != EOF)
2171590Srgrimes		switch ((char) ch) {
2181590Srgrimes		case 'f':
2191590Srgrimes			freq = atoi(optarg);
2201590Srgrimes			break;
22148566Sbillf		case 'p':
2221590Srgrimes			pflag = 1;
2231590Srgrimes			break;
2241590Srgrimes		case 's':
2251590Srgrimes			sflag = 1;
22648566Sbillf			break;
22723693Speter		case 'w':
2281590Srgrimes			wpm = atoi(optarg);
2291590Srgrimes			break;
2301590Srgrimes		case '?':
231102944Sdwmalone		default:
2321590Srgrimes			fputs("usage: morse [-s] [-p] [-w speed] [-f frequency] [string ...]\n", stderr);
23387229Smarkm			exit(1);
2341590Srgrimes		}
2351590Srgrimes	if (pflag && sflag) {
236201140Sed		fputs("morse: only one of -p and -s allowed\n", stderr);
23787229Smarkm		exit(1);
2381590Srgrimes	}
239117010Sjmallett	if (pflag && ((wpm < 1) || (wpm > 60))) {
240117010Sjmallett		fputs("morse: insane speed\n", stderr);
241117010Sjmallett		exit(1);
242201140Sed	}
243201140Sed	if (pflag && (freq == 0))
244201140Sed		freq = FREQUENCY;
2451590Srgrimes
246201140Sed#ifdef SPEAKER
247201140Sed	if (pflag) {
2481590Srgrimes		if ((spkr = open(SPEAKER, O_WRONLY, 0)) == -1) {
2495369Sjkh			perror(SPEAKER);
2505369Sjkh			exit(1);
2511590Srgrimes		}
2521590Srgrimes		dot_clock = wpm / 2.4;		/* dots/sec */
253201140Sed		dot_clock = 1 / dot_clock;	/* duration of a dot */
2541590Srgrimes		dot_clock = dot_clock / 2;	/* dot_clock runs at twice */
255201140Sed						/* the dot rate */
2561590Srgrimes		dot_clock = dot_clock * 100;	/* scale for ioctl */
25787229Smarkm	}
25823693Speter#endif
25923693Speter	argc -= optind;
26087229Smarkm	argv += optind;
2611590Srgrimes
26223693Speter	if((p = getenv("LC_CTYPE")) ||
2631590Srgrimes	   (p = getenv("LC_ALL")) ||
2641590Srgrimes	   (p = getenv("LANG"))) {
26523693Speter		if(strlen(p) >= sizeof(".KOI8-R") &&
26623693Speter		   strcasecmp(&p[strlen(p) + 1 - sizeof(".KOI8-R")], ".KOI8-R") == 0)
2671590Srgrimes			hightab = koi8rtab;
2681590Srgrimes	}
2691590Srgrimes	(void) setlocale(LC_CTYPE, "");
2701590Srgrimes
271102944Sdwmalone	if (*argv) {
2721590Srgrimes		do {
27387229Smarkm			for (p = *argv; *p; ++p) {
2741590Srgrimes				morse(*p);
275201140Sed			}
2761590Srgrimes			morse(' ');
27787229Smarkm		} while (*++argv);
2781590Srgrimes	} else {
27964775Sbrian		while ((ch = getchar()) != EOF)
28064775Sbrian			morse(ch);
28164775Sbrian	}
28264775Sbrian	exit(0);
2831590Srgrimes}
2841590Srgrimes
2851590Srgrimesvoid
28623693Spetermorse(char c)
2871590Srgrimes{
2881590Srgrimes	struct morsetab *m;
2891590Srgrimes
290229403Sed	if (isalpha((unsigned char)c))
2911590Srgrimes		c = tolower((unsigned char)c);
2921590Srgrimes	if ((c == '\r') || (c == '\n'))
2931590Srgrimes		c = ' ';
2941590Srgrimes	if (c == ' ') {
2951590Srgrimes		if (pflag) {
2961590Srgrimes			play(" ");
2971590Srgrimes			return;
2981590Srgrimes		} else {
2991590Srgrimes			show("");
3001590Srgrimes			return;
3011590Srgrimes		}
302228992Suqs	}
303228992Suqs	for (m = ((unsigned char)c < 0x80? mtab: hightab);
30466563Sbrian	     m->inchar != '\0';
30566563Sbrian	     m++) {
30666563Sbrian		if (m->inchar == c) {
30766563Sbrian			if (pflag) {
30866563Sbrian				play(m->morse);
30966563Sbrian			} else
31066563Sbrian				show(m->morse);
31166563Sbrian		}
31264775Sbrian	}
31364775Sbrian}
31464775Sbrian
31564775Sbrianvoid
31664775Sbrianshow(const char *s)
31764775Sbrian{
31864775Sbrian	if (sflag)
31964775Sbrian		printf(" %s", s);
32064775Sbrian	else
32164775Sbrian		for (; *s; ++s)
32264775Sbrian			printf(" %s", *s == '.' ? "dit" : "dah");
32364775Sbrian	printf("\n");
32464775Sbrian}
325126960Sbde
32664775Sbrianvoid
32764775Sbrianplay(const char *s)
32864775Sbrian{
32964775Sbrian#ifdef SPEAKER
33064775Sbrian	const char *c;
33164775Sbrian
33264775Sbrian	for (c = s; *c != '\0'; c++) {
33364775Sbrian		switch (*c) {
33464775Sbrian		case '.':
33564775Sbrian			sound.frequency = freq;
3361590Srgrimes			sound.duration = dot_clock;
33765064Sbrian			break;
33865064Sbrian		case '-':
33965064Sbrian			sound.frequency = freq;
3401590Srgrimes			sound.duration = dot_clock * DASH_LEN;
3411590Srgrimes			break;
34266675Sru		case ' ':
34366675Sru			sound.frequency = 0;
34465064Sbrian			sound.duration = dot_clock * WORD_SPACE;
34565064Sbrian			break;
34666675Sru		default:
34765064Sbrian			sound.duration = 0;
34865064Sbrian		}
34965064Sbrian		if (sound.duration) {
3501590Srgrimes			if (ioctl(spkr, SPKRTONE, &sound) == -1) {
35165787Sbrian				perror("ioctl play");
3521590Srgrimes				exit(1);
35365064Sbrian			}
35465787Sbrian		}
35565064Sbrian		sound.frequency = 0;
35665787Sbrian		sound.duration = dot_clock;
3571590Srgrimes		if (ioctl(spkr, SPKRTONE, &sound) == -1) {
3581590Srgrimes			perror("ioctl rest");
3591590Srgrimes			exit(1);
3605369Sjkh		}
3611590Srgrimes	}
3621590Srgrimes	sound.frequency = 0;
36327169Scharnier	sound.duration = dot_clock * CHAR_SPACE;
3641590Srgrimes	ioctl(spkr, SPKRTONE, &sound);
3651590Srgrimes#endif
3661590Srgrimes}
3674991Spst