morse.c revision 29018
1156230Smux/* 2156230Smux * Copyright (c) 1988, 1993 3156230Smux * The Regents of the University of California. All rights reserved. 4156230Smux * 5156230Smux * Redistribution and use in source and binary forms, with or without 6156230Smux * modification, are permitted provided that the following conditions 7156230Smux * are met: 8156230Smux * 1. Redistributions of source code must retain the above copyright 9156230Smux * notice, this list of conditions and the following disclaimer. 10156230Smux * 2. Redistributions in binary form must reproduce the above copyright 11156230Smux * notice, this list of conditions and the following disclaimer in the 12156230Smux * documentation and/or other materials provided with the distribution. 13156230Smux * 3. All advertising materials mentioning features or use of this software 14156230Smux * must display the following acknowledgement: 15156230Smux * This product includes software developed by the University of 16156230Smux * California, Berkeley and its contributors. 17156230Smux * 4. Neither the name of the University nor the names of its contributors 18156230Smux * may be used to endorse or promote products derived from this software 19156230Smux * without specific prior written permission. 20156230Smux * 21156230Smux * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22156230Smux * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23156230Smux * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24156230Smux * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25156230Smux * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26156230Smux * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27156230Smux * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28156230Smux * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29156230Smux * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30156230Smux * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31156230Smux * SUCH DAMAGE. 32216370Sjoel */ 33216370Sjoel 34156230Smux/* 35156230Smux * Taught to send *real* morse by Lyndon Nerenberg (VE7TCP/VE6BBM) 36156230Smux * <lyndon@orthanc.com> 37156230Smux */ 38156230Smux 39156230Smux#ifndef lint 40156230Smuxstatic char copyright[] = 41156230Smux"@(#) Copyright (c) 1988, 1993\n\ 42156230Smux The Regents of the University of California. All rights reserved.\n"; 43156230Smux#endif /* not lint */ 44156230Smux 45156230Smux#ifndef lint 46156230Smuxstatic char sccsid[] = "@(#)morse.c 8.1 (Berkeley) 5/31/93"; 47156230Smux#endif /* not lint */ 48156230Smux 49156230Smux#include <stdio.h> 50156230Smux#include <ctype.h> 51156230Smux#include <locale.h> 52156230Smux#include <stdlib.h> 53156230Smux 54156230Smux#ifdef SPEAKER 55156230Smux#include <machine/speaker.h> 56156230Smux#include <fcntl.h> 57156230Smux#endif 58156230Smux 59156230Smuxstruct morsetab { 60156230Smux char inchar; 61156230Smux char *morse; 62156230Smux}; 63156230Smux 64156230Smuxstatic struct morsetab mtab[] = { 65156230Smux 66156230Smux /* letters */ 67156230Smux 68156230Smux 'a', ".-", 69156230Smux 'b', "-...", 70156230Smux 'c', "-.-.", 71156230Smux 'd', "-..", 72156230Smux 'e', ".", 73156230Smux 'f', "..-.", 74156230Smux 'g', "--.", 75156230Smux 'h', "....", 76156230Smux 'i', "..", 77156230Smux 'j', ".---", 78156230Smux 'k', "-.-", 79156230Smux 'l', ".-..", 80156230Smux 'm', "--", 81156230Smux 'n', "-.", 82156230Smux 'o', "---", 83156230Smux 'p', ".--.", 84156230Smux 'q', "--.-", 85156230Smux 'r', ".-.", 86156230Smux 's', "...", 87156230Smux 't', "-", 88156230Smux 'u', "..-", 89156230Smux 'v', "...-", 90156230Smux 'w', ".--", 91156230Smux 'x', "-..-", 92156230Smux 'y', "-.--", 93156230Smux 'z', "--..", 94156230Smux 95156230Smux /* digits */ 96156230Smux 97156230Smux '0', "-----", 98156230Smux '1', ".----", 99156230Smux '2', "..---", 100156230Smux '3', "...--", 101156230Smux '4', "....-", 102156230Smux '5', ".....", 103156230Smux '6', "-....", 104156230Smux '7', "--...", 105156230Smux '8', "---..", 106156230Smux '9', "----.", 107156230Smux 108156230Smux /* punctuation */ 109156230Smux 110156230Smux ',', "--..--", 111156230Smux '.', ".-.-.-", 112156230Smux '?', "..--..", 113156230Smux '/', "-..-.", 114156230Smux '-', "-....-", 115156230Smux '=', "-...-", /* BT */ 116156230Smux ':', "---...", 117156230Smux ';', "-.-.-.", 118156230Smux '(', "-.--.", /* KN */ 119156230Smux ')', "-.--.-", 120156230Smux '$', "...-..-", 121156230Smux '+', ".-.-.", /* AR */ 122156230Smux 123156230Smux /* prosigns without already assigned values */ 124156230Smux 125156230Smux '#', ".-...", /* AS */ 126156230Smux '@', "...-.-", /* SK */ 127156230Smux '*', "...-.", /* VE */ 128156230Smux '%', "-...-.-", /* BK */ 129156230Smux 130156230Smux '\0', "" 131156230Smux}; 132156230Smux 133156230Smux 134156230Smuxstatic struct morsetab iso8859tab[] = { 135156230Smux '�', ".--.-", 136156230Smux '�', ".--.-", 137156230Smux '�', ".--.-", 138156230Smux '�', ".-.-", 139156230Smux '�', "-.-..", 140156230Smux '�', "..-..", 141156230Smux '�', "..-..", 142156230Smux '�', "-..-.", 143156230Smux '�', "---.", 144156230Smux '�', "..--", 145156230Smux 146156230Smux '\0', "" 147156230Smux}; 148156230Smux 149156230Smuxstatic struct morsetab koi8rtab[] = { 150156230Smux /* 151156230Smux * the cyrillic alphabet; you'll need a KOI8R font in order 152156230Smux * to see the actual characters 153156230Smux */ 154156230Smux '�', ".-", /* a */ 155156230Smux '�', "-...", /* be */ 156156230Smux '�', ".--", /* ve */ 157156230Smux '�', "--.", /* ge */ 158156230Smux '�', "-..", /* de */ 159156230Smux '�', ".", /* ye */ 160156230Smux '�', ".", /* yo, the same as ye */ 161156230Smux '�', "...-", /* she */ 162156230Smux '�', "--..", /* ze */ 163156230Smux '�', "..", /* i */ 164156230Smux '�', ".---", /* i kratkoye */ 165156230Smux '�', "-.-", /* ka */ 166156230Smux '�', ".-..", /* el */ 167156230Smux '�', "--", /* em */ 168156230Smux '�', "-.", /* en */ 169156230Smux '�', "---", /* o */ 170156230Smux '�', ".--.", /* pe */ 171156230Smux '�', ".-.", /* er */ 172156230Smux '�', "...", /* es */ 173156230Smux '�', "-", /* te */ 174156230Smux '�', "..-", /* u */ 175156230Smux '�', "..-.", /* ef */ 176156230Smux '�', "....", /* kha */ 177156230Smux '�', "-.-.", /* ce */ 178156230Smux '�', "---.", /* che */ 179156230Smux '�', "----", /* sha */ 180156230Smux '�', "--.-", /* shcha */ 181156230Smux '�', "-.--", /* yi */ 182156230Smux '�', "-..-", /* myakhkij znak */ 183156230Smux '�', "..-..", /* ae */ 184156230Smux '�', "..--", /* yu */ 185156230Smux '�', ".-.-", /* ya */ 186156230Smux 187156230Smux '\0', "" 188156230Smux}; 189156230Smux 190156230Smuxvoid show(const char *), play(const char *), morse(char); 191156230Smux 192156230Smuxstatic int pflag, sflag; 193156230Smuxstatic int wpm = 20; /* words per minute */ 194156230Smux#define FREQUENCY 600 195156230Smuxstatic int freq = FREQUENCY; 196156230Smux 197156230Smux#ifdef SPEAKER 198#define DASH_LEN 3 199#define CHAR_SPACE 3 200#define WORD_SPACE (7 - CHAR_SPACE - 1) 201static float dot_clock; 202int spkr; 203tone_t sound; 204#endif 205 206static struct morsetab *hightab = iso8859tab; 207 208int 209main(int argc, char **argv) 210{ 211 extern char *optarg; 212 extern int optind; 213 register int ch; 214 register char *p; 215 216 while ((ch = getopt(argc, argv, "spw:f:")) != EOF) 217 switch ((char) ch) { 218 case 'f': 219 freq = atoi(optarg); 220 break; 221 case 'p': 222 pflag = 1; 223 break; 224 case 's': 225 sflag = 1; 226 break; 227 case 'w': 228 wpm = atoi(optarg); 229 break; 230 case '?': 231 default: 232 fputs("usage: morse [-s] [-p] [-w speed] [-f frequency] [string ...]\n", stderr); 233 exit(1); 234 } 235 if (pflag && sflag) { 236 fputs("morse: only one of -p and -s allowed\n", stderr); 237 exit(1); 238 } 239 if (pflag && ((wpm < 1) || (wpm > 60))) { 240 fputs("morse: insane speed\n", stderr); 241 exit(1); 242 } 243 if (pflag && (freq == 0)) 244 freq = FREQUENCY; 245 246#ifdef SPEAKER 247 if (pflag) { 248 if ((spkr = open(SPEAKER, O_WRONLY, 0)) == -1) { 249 perror(SPEAKER); 250 exit(1); 251 } 252 dot_clock = wpm / 2.4; /* dots/sec */ 253 dot_clock = 1 / dot_clock; /* duration of a dot */ 254 dot_clock = dot_clock / 2; /* dot_clock runs at twice */ 255 /* the dot rate */ 256 dot_clock = dot_clock * 100; /* scale for ioctl */ 257 } 258#endif 259 argc -= optind; 260 argv += optind; 261 262 if((p = getenv("LC_CTYPE")) || 263 (p = getenv("LC_ALL")) || 264 (p = getenv("LANG"))) { 265 if(strlen(p) >= sizeof(".KOI8-R") && 266 strcasecmp(&p[strlen(p) + 1 - sizeof(".KOI8-R")], ".KOI8-R") == 0) 267 hightab = koi8rtab; 268 } 269 (void) setlocale(LC_CTYPE, ""); 270 271 if (*argv) { 272 do { 273 for (p = *argv; *p; ++p) { 274 morse(*p); 275 } 276 morse(' '); 277 } while (*++argv); 278 } else { 279 while ((ch = getchar()) != EOF) 280 morse(ch); 281 } 282 exit(0); 283} 284 285void 286morse(char c) 287{ 288 struct morsetab *m; 289 290 if (isalpha((unsigned char)c)) 291 c = tolower((unsigned char)c); 292 if ((c == '\r') || (c == '\n')) 293 c = ' '; 294 if (c == ' ') { 295 if (pflag) { 296 play(" "); 297 return; 298 } else { 299 show(""); 300 return; 301 } 302 } 303 for (m = ((unsigned char)c < 0x80? mtab: hightab); 304 m->inchar != '\0'; 305 m++) { 306 if (m->inchar == c) { 307 if (pflag) { 308 play(m->morse); 309 } else 310 show(m->morse); 311 } 312 } 313} 314 315void 316show(const char *s) 317{ 318 if (sflag) 319 printf(" %s", s); 320 else 321 for (; *s; ++s) 322 printf(" %s", *s == '.' ? "dit" : "dah"); 323 printf("\n"); 324} 325 326void 327play(const char *s) 328{ 329#ifdef SPEAKER 330 const char *c; 331 332 for (c = s; *c != '\0'; c++) { 333 switch (*c) { 334 case '.': 335 sound.frequency = freq; 336 sound.duration = dot_clock; 337 break; 338 case '-': 339 sound.frequency = freq; 340 sound.duration = dot_clock * DASH_LEN; 341 break; 342 case ' ': 343 sound.frequency = 0; 344 sound.duration = dot_clock * WORD_SPACE; 345 break; 346 default: 347 sound.duration = 0; 348 } 349 if (sound.duration) { 350 if (ioctl(spkr, SPKRTONE, &sound) == -1) { 351 perror("ioctl play"); 352 exit(1); 353 } 354 } 355 sound.frequency = 0; 356 sound.duration = dot_clock; 357 if (ioctl(spkr, SPKRTONE, &sound) == -1) { 358 perror("ioctl rest"); 359 exit(1); 360 } 361 } 362 sound.frequency = 0; 363 sound.duration = dot_clock * CHAR_SPACE; 364 ioctl(spkr, SPKRTONE, &sound); 365#endif 366} 367