morse.c revision 35857
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 402490Sjkhstatic 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 462490Sjkhstatic char sccsid[] = "@(#)morse.c 8.1 (Berkeley) 5/31/93"; 472490Sjkh#endif /* not lint */ 482490Sjkh 492490Sjkh#include <stdio.h> 502490Sjkh#include <ctype.h> 5110352Sjoerg#include <locale.h> 5210352Sjoerg#include <stdlib.h> 5335857Sjb#include <string.h> 542490Sjkh 5510352Sjoerg#ifdef SPEAKER 5610352Sjoerg#include <machine/speaker.h> 5710352Sjoerg#include <fcntl.h> 5810352Sjoerg#endif 5910352Sjoerg 6010352Sjoergstruct morsetab { 6110352Sjoerg char inchar; 6210352Sjoerg char *morse; 632490Sjkh}; 642490Sjkh 6510352Sjoergstatic struct morsetab mtab[] = { 662490Sjkh 6710352Sjoerg /* letters */ 6810352Sjoerg 6910352Sjoerg 'a', ".-", 7010352Sjoerg 'b', "-...", 7110352Sjoerg 'c', "-.-.", 7210352Sjoerg 'd', "-..", 7310352Sjoerg 'e', ".", 7410352Sjoerg 'f', "..-.", 7510352Sjoerg 'g', "--.", 7610352Sjoerg 'h', "....", 7710352Sjoerg 'i', "..", 7810352Sjoerg 'j', ".---", 7910352Sjoerg 'k', "-.-", 8010352Sjoerg 'l', ".-..", 8110352Sjoerg 'm', "--", 8210352Sjoerg 'n', "-.", 8310352Sjoerg 'o', "---", 8410352Sjoerg 'p', ".--.", 8510352Sjoerg 'q', "--.-", 8610352Sjoerg 'r', ".-.", 8710352Sjoerg 's', "...", 8810352Sjoerg 't', "-", 8910352Sjoerg 'u', "..-", 9010352Sjoerg 'v', "...-", 9110352Sjoerg 'w', ".--", 9210352Sjoerg 'x', "-..-", 9310352Sjoerg 'y', "-.--", 9410352Sjoerg 'z', "--..", 9510352Sjoerg 9610352Sjoerg /* digits */ 9710352Sjoerg 9810352Sjoerg '0', "-----", 9910352Sjoerg '1', ".----", 10010352Sjoerg '2', "..---", 10110352Sjoerg '3', "...--", 10210352Sjoerg '4', "....-", 10310352Sjoerg '5', ".....", 10410352Sjoerg '6', "-....", 10510352Sjoerg '7', "--...", 10610352Sjoerg '8', "---..", 10710352Sjoerg '9', "----.", 10810352Sjoerg 10910352Sjoerg /* punctuation */ 11010352Sjoerg 11110352Sjoerg ',', "--..--", 11210352Sjoerg '.', ".-.-.-", 11310352Sjoerg '?', "..--..", 11410352Sjoerg '/', "-..-.", 11510352Sjoerg '-', "-....-", 11610352Sjoerg '=', "-...-", /* BT */ 11710352Sjoerg ':', "---...", 11810352Sjoerg ';', "-.-.-.", 11910352Sjoerg '(', "-.--.", /* KN */ 12010352Sjoerg ')', "-.--.-", 12110352Sjoerg '$', "...-..-", 12210352Sjoerg '+', ".-.-.", /* AR */ 12310352Sjoerg 12410352Sjoerg /* prosigns without already assigned values */ 12510352Sjoerg 12610352Sjoerg '#', ".-...", /* AS */ 12710352Sjoerg '@', "...-.-", /* SK */ 12810352Sjoerg '*', "...-.", /* VE */ 12910352Sjoerg '%', "-...-.-", /* BK */ 13010352Sjoerg 13110352Sjoerg '\0', "" 13210352Sjoerg}; 13310352Sjoerg 13410352Sjoerg 13510352Sjoergstatic struct morsetab iso8859tab[] = { 13610352Sjoerg '�', ".--.-", 13710352Sjoerg '�', ".--.-", 13810352Sjoerg '�', ".--.-", 13910352Sjoerg '�', ".-.-", 14010352Sjoerg '�', "-.-..", 14110352Sjoerg '�', "..-..", 14210352Sjoerg '�', "..-..", 14310352Sjoerg '�', "-..-.", 14410352Sjoerg '�', "---.", 14510352Sjoerg '�', "..--", 14610352Sjoerg 14710352Sjoerg '\0', "" 14810352Sjoerg}; 14910352Sjoerg 15010352Sjoergstatic struct morsetab koi8rtab[] = { 15110352Sjoerg /* 15210352Sjoerg * the cyrillic alphabet; you'll need a KOI8R font in order 15310352Sjoerg * to see the actual characters 15410352Sjoerg */ 15510352Sjoerg '�', ".-", /* a */ 15610352Sjoerg '�', "-...", /* be */ 15710352Sjoerg '�', ".--", /* ve */ 15810352Sjoerg '�', "--.", /* ge */ 15910352Sjoerg '�', "-..", /* de */ 16010352Sjoerg '�', ".", /* ye */ 16129018Sache '�', ".", /* yo, the same as ye */ 16210352Sjoerg '�', "...-", /* she */ 16310352Sjoerg '�', "--..", /* ze */ 16410352Sjoerg '�', "..", /* i */ 16510352Sjoerg '�', ".---", /* i kratkoye */ 16610352Sjoerg '�', "-.-", /* ka */ 16710352Sjoerg '�', ".-..", /* el */ 16810352Sjoerg '�', "--", /* em */ 16910352Sjoerg '�', "-.", /* en */ 17010352Sjoerg '�', "---", /* o */ 17110352Sjoerg '�', ".--.", /* pe */ 17210352Sjoerg '�', ".-.", /* er */ 17310352Sjoerg '�', "...", /* es */ 17410352Sjoerg '�', "-", /* te */ 17510352Sjoerg '�', "..-", /* u */ 17610352Sjoerg '�', "..-.", /* ef */ 17710352Sjoerg '�', "....", /* kha */ 17810352Sjoerg '�', "-.-.", /* ce */ 17910352Sjoerg '�', "---.", /* che */ 18010352Sjoerg '�', "----", /* sha */ 18110352Sjoerg '�', "--.-", /* shcha */ 18210352Sjoerg '�', "-.--", /* yi */ 18310352Sjoerg '�', "-..-", /* myakhkij znak */ 18410352Sjoerg '�', "..-..", /* ae */ 18510352Sjoerg '�', "..--", /* yu */ 18610352Sjoerg '�', ".-.-", /* ya */ 18710352Sjoerg 18810352Sjoerg '\0', "" 18910352Sjoerg}; 19010352Sjoerg 19110352Sjoergvoid show(const char *), play(const char *), morse(char); 19210352Sjoerg 19310352Sjoergstatic int pflag, sflag; 19410352Sjoergstatic int wpm = 20; /* words per minute */ 19510352Sjoerg#define FREQUENCY 600 19610352Sjoergstatic int freq = FREQUENCY; 19710352Sjoerg 19810352Sjoerg#ifdef SPEAKER 19910352Sjoerg#define DASH_LEN 3 20010352Sjoerg#define CHAR_SPACE 3 20110352Sjoerg#define WORD_SPACE (7 - CHAR_SPACE - 1) 20210352Sjoergstatic float dot_clock; 20310352Sjoergint spkr; 20410352Sjoergtone_t sound; 20510352Sjoerg#endif 20610352Sjoerg 20710352Sjoergstatic struct morsetab *hightab = iso8859tab; 20810352Sjoerg 20910352Sjoergint 21010352Sjoergmain(int argc, char **argv) 2112490Sjkh{ 21210352Sjoerg extern char *optarg; 21310352Sjoerg extern int optind; 21410352Sjoerg register int ch; 21510352Sjoerg register char *p; 2162490Sjkh 21733937Sjkh while ((ch = getopt(argc, argv, "spw:f:")) != -1) 21810352Sjoerg switch ((char) ch) { 21910352Sjoerg case 'f': 22010352Sjoerg freq = atoi(optarg); 22110352Sjoerg break; 22210352Sjoerg case 'p': 22310352Sjoerg pflag = 1; 22410352Sjoerg break; 2252490Sjkh case 's': 2262490Sjkh sflag = 1; 2272490Sjkh break; 22810352Sjoerg case 'w': 22910352Sjoerg wpm = atoi(optarg); 23010352Sjoerg break; 2312490Sjkh case '?': 2322490Sjkh default: 23310352Sjoerg fputs("usage: morse [-s] [-p] [-w speed] [-f frequency] [string ...]\n", stderr); 2342490Sjkh exit(1); 2352490Sjkh } 23610352Sjoerg if (pflag && sflag) { 23710352Sjoerg fputs("morse: only one of -p and -s allowed\n", stderr); 23810352Sjoerg exit(1); 23910352Sjoerg } 24010352Sjoerg if (pflag && ((wpm < 1) || (wpm > 60))) { 24110352Sjoerg fputs("morse: insane speed\n", stderr); 24210352Sjoerg exit(1); 24310352Sjoerg } 24410352Sjoerg if (pflag && (freq == 0)) 24510352Sjoerg freq = FREQUENCY; 24610352Sjoerg 24710352Sjoerg#ifdef SPEAKER 24810352Sjoerg if (pflag) { 24910352Sjoerg if ((spkr = open(SPEAKER, O_WRONLY, 0)) == -1) { 25010352Sjoerg perror(SPEAKER); 25110352Sjoerg exit(1); 25210352Sjoerg } 25310352Sjoerg dot_clock = wpm / 2.4; /* dots/sec */ 25410352Sjoerg dot_clock = 1 / dot_clock; /* duration of a dot */ 25510352Sjoerg dot_clock = dot_clock / 2; /* dot_clock runs at twice */ 25610352Sjoerg /* the dot rate */ 25710352Sjoerg dot_clock = dot_clock * 100; /* scale for ioctl */ 25810352Sjoerg } 25910352Sjoerg#endif 2602490Sjkh argc -= optind; 2612490Sjkh argv += optind; 2622490Sjkh 26329018Sache if((p = getenv("LC_CTYPE")) || 26429018Sache (p = getenv("LC_ALL")) || 26529018Sache (p = getenv("LANG"))) { 26629018Sache if(strlen(p) >= sizeof(".KOI8-R") && 26729018Sache strcasecmp(&p[strlen(p) + 1 - sizeof(".KOI8-R")], ".KOI8-R") == 0) 26810352Sjoerg hightab = koi8rtab; 26910352Sjoerg } 27029018Sache (void) setlocale(LC_CTYPE, ""); 27110352Sjoerg 27210352Sjoerg if (*argv) { 2732490Sjkh do { 27410352Sjoerg for (p = *argv; *p; ++p) { 27529018Sache morse(*p); 27610352Sjoerg } 27729018Sache morse(' '); 2782490Sjkh } while (*++argv); 27910352Sjoerg } else { 28010352Sjoerg while ((ch = getchar()) != EOF) 28110352Sjoerg morse(ch); 28210352Sjoerg } 28310352Sjoerg exit(0); 2842490Sjkh} 2852490Sjkh 28610352Sjoergvoid 28710352Sjoergmorse(char c) 2882490Sjkh{ 28910352Sjoerg struct morsetab *m; 29010352Sjoerg 29129018Sache if (isalpha((unsigned char)c)) 29229018Sache c = tolower((unsigned char)c); 29310352Sjoerg if ((c == '\r') || (c == '\n')) 29410352Sjoerg c = ' '; 29510352Sjoerg if (c == ' ') { 29610352Sjoerg if (pflag) { 29710352Sjoerg play(" "); 29810352Sjoerg return; 29910352Sjoerg } else { 30010352Sjoerg show(""); 30110352Sjoerg return; 30210352Sjoerg } 30310352Sjoerg } 30410352Sjoerg for (m = ((unsigned char)c < 0x80? mtab: hightab); 30510352Sjoerg m->inchar != '\0'; 30610352Sjoerg m++) { 30710352Sjoerg if (m->inchar == c) { 30810352Sjoerg if (pflag) { 30910352Sjoerg play(m->morse); 31010352Sjoerg } else 31110352Sjoerg show(m->morse); 31210352Sjoerg } 31310352Sjoerg } 3142490Sjkh} 3152490Sjkh 31610352Sjoergvoid 31710352Sjoergshow(const char *s) 3182490Sjkh{ 3192490Sjkh if (sflag) 3202490Sjkh printf(" %s", s); 32110352Sjoerg else 32210352Sjoerg for (; *s; ++s) 32310352Sjoerg printf(" %s", *s == '.' ? "dit" : "dah"); 32410352Sjoerg printf("\n"); 3252490Sjkh} 32610352Sjoerg 32710352Sjoergvoid 32810352Sjoergplay(const char *s) 32910352Sjoerg{ 33010352Sjoerg#ifdef SPEAKER 33110352Sjoerg const char *c; 33210352Sjoerg 33310352Sjoerg for (c = s; *c != '\0'; c++) { 33429018Sache switch (*c) { 33510352Sjoerg case '.': 33610352Sjoerg sound.frequency = freq; 33710352Sjoerg sound.duration = dot_clock; 33810352Sjoerg break; 33910352Sjoerg case '-': 34010352Sjoerg sound.frequency = freq; 34110352Sjoerg sound.duration = dot_clock * DASH_LEN; 34210352Sjoerg break; 34310352Sjoerg case ' ': 34410352Sjoerg sound.frequency = 0; 34510352Sjoerg sound.duration = dot_clock * WORD_SPACE; 34610352Sjoerg break; 34710352Sjoerg default: 34810352Sjoerg sound.duration = 0; 34910352Sjoerg } 35010352Sjoerg if (sound.duration) { 35110352Sjoerg if (ioctl(spkr, SPKRTONE, &sound) == -1) { 35210352Sjoerg perror("ioctl play"); 35310352Sjoerg exit(1); 35410352Sjoerg } 35510352Sjoerg } 35610352Sjoerg sound.frequency = 0; 35710352Sjoerg sound.duration = dot_clock; 35810352Sjoerg if (ioctl(spkr, SPKRTONE, &sound) == -1) { 35910352Sjoerg perror("ioctl rest"); 36010352Sjoerg exit(1); 36110352Sjoerg } 36210352Sjoerg } 36310352Sjoerg sound.frequency = 0; 36410352Sjoerg sound.duration = dot_clock * CHAR_SPACE; 36510352Sjoerg ioctl(spkr, SPKRTONE, &sound); 36610352Sjoerg#endif 36710352Sjoerg} 368