morse.c revision 53920
1/* 2 * Copyright (c) 1988, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 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. 20 * 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 31 * SUCH DAMAGE. 32 */ 33 34/* 35 * Taught to send *real* morse by Lyndon Nerenberg (VE7TCP/VE6BBM) 36 * <lyndon@orthanc.com> 37 */ 38 39#ifndef lint 40static const char copyright[] = 41"@(#) Copyright (c) 1988, 1993\n\ 42 The Regents of the University of California. All rights reserved.\n"; 43#endif /* not lint */ 44 45#ifndef lint 46#if 0 47static char sccsid[] = "@(#)morse.c 8.1 (Berkeley) 5/31/93"; 48#endif 49static const char rcsid[] = 50 "$FreeBSD: head/games/morse/morse.c 53920 1999-11-30 03:50:02Z billf $"; 51#endif /* not lint */ 52 53#include <stdio.h> 54#include <ctype.h> 55#include <locale.h> 56#include <stdlib.h> 57#include <string.h> 58 59#ifdef SPEAKER 60#include <machine/speaker.h> 61#include <fcntl.h> 62#endif 63 64struct morsetab { 65 char inchar; 66 char *morse; 67}; 68 69static struct morsetab mtab[] = { 70 71 /* letters */ 72 73 'a', ".-", 74 'b', "-...", 75 'c', "-.-.", 76 'd', "-..", 77 'e', ".", 78 'f', "..-.", 79 'g', "--.", 80 'h', "....", 81 'i', "..", 82 'j', ".---", 83 'k', "-.-", 84 'l', ".-..", 85 'm', "--", 86 'n', "-.", 87 'o', "---", 88 'p', ".--.", 89 'q', "--.-", 90 'r', ".-.", 91 's', "...", 92 't', "-", 93 'u', "..-", 94 'v', "...-", 95 'w', ".--", 96 'x', "-..-", 97 'y', "-.--", 98 'z', "--..", 99 100 /* digits */ 101 102 '0', "-----", 103 '1', ".----", 104 '2', "..---", 105 '3', "...--", 106 '4', "....-", 107 '5', ".....", 108 '6', "-....", 109 '7', "--...", 110 '8', "---..", 111 '9', "----.", 112 113 /* punctuation */ 114 115 ',', "--..--", 116 '.', ".-.-.-", 117 '?', "..--..", 118 '/', "-..-.", 119 '-', "-....-", 120 '=', "-...-", /* BT */ 121 ':', "---...", 122 ';', "-.-.-.", 123 '(', "-.--.", /* KN */ 124 ')', "-.--.-", 125 '$', "...-..-", 126 '+', ".-.-.", /* AR */ 127 128 /* prosigns without already assigned values */ 129 130 '#', ".-...", /* AS */ 131 '@', "...-.-", /* SK */ 132 '*', "...-.", /* VE */ 133 '%', "-...-.-", /* BK */ 134 135 '\0', "" 136}; 137 138 139static struct morsetab iso8859tab[] = { 140 '�', ".--.-", 141 '�', ".--.-", 142 '�', ".--.-", 143 '�', ".-.-", 144 '�', "-.-..", 145 '�', "..-..", 146 '�', "..-..", 147 '�', "-..-.", 148 '�', "---.", 149 '�', "..--", 150 151 '\0', "" 152}; 153 154static struct morsetab koi8rtab[] = { 155 /* 156 * the cyrillic alphabet; you'll need a KOI8R font in order 157 * to see the actual characters 158 */ 159 '�', ".-", /* a */ 160 '�', "-...", /* be */ 161 '�', ".--", /* ve */ 162 '�', "--.", /* ge */ 163 '�', "-..", /* de */ 164 '�', ".", /* ye */ 165 '�', ".", /* yo, the same as ye */ 166 '�', "...-", /* she */ 167 '�', "--..", /* ze */ 168 '�', "..", /* i */ 169 '�', ".---", /* i kratkoye */ 170 '�', "-.-", /* ka */ 171 '�', ".-..", /* el */ 172 '�', "--", /* em */ 173 '�', "-.", /* en */ 174 '�', "---", /* o */ 175 '�', ".--.", /* pe */ 176 '�', ".-.", /* er */ 177 '�', "...", /* es */ 178 '�', "-", /* te */ 179 '�', "..-", /* u */ 180 '�', "..-.", /* ef */ 181 '�', "....", /* kha */ 182 '�', "-.-.", /* ce */ 183 '�', "---.", /* che */ 184 '�', "----", /* sha */ 185 '�', "--.-", /* shcha */ 186 '�', "-.--", /* yi */ 187 '�', "-..-", /* myakhkij znak */ 188 '�', "..-..", /* ae */ 189 '�', "..--", /* yu */ 190 '�', ".-.-", /* ya */ 191 192 '\0', "" 193}; 194 195void show(const char *), play(const char *), morse(char); 196 197static int pflag, sflag; 198static int wpm = 20; /* words per minute */ 199#define FREQUENCY 600 200static int freq = FREQUENCY; 201 202#ifdef SPEAKER 203#define DASH_LEN 3 204#define CHAR_SPACE 3 205#define WORD_SPACE (7 - CHAR_SPACE - 1) 206static float dot_clock; 207int spkr; 208tone_t sound; 209#endif 210 211static struct morsetab *hightab = iso8859tab; 212 213int 214main(int argc, char **argv) 215{ 216 extern char *optarg; 217 extern int optind; 218 int ch; 219 char *p; 220 221 while ((ch = getopt(argc, argv, "spw:f:")) != -1) 222 switch ((char) ch) { 223 case 'f': 224 freq = atoi(optarg); 225 break; 226 case 'p': 227 pflag = 1; 228 break; 229 case 's': 230 sflag = 1; 231 break; 232 case 'w': 233 wpm = atoi(optarg); 234 break; 235 case '?': 236 default: 237 fputs("usage: morse [-s] [-p] [-w speed] [-f frequency] [string ...]\n", stderr); 238 exit(1); 239 } 240 if (pflag && sflag) { 241 fputs("morse: only one of -p and -s allowed\n", stderr); 242 exit(1); 243 } 244 if (pflag && ((wpm < 1) || (wpm > 60))) { 245 fputs("morse: insane speed\n", stderr); 246 exit(1); 247 } 248 if (pflag && (freq == 0)) 249 freq = FREQUENCY; 250 251#ifdef SPEAKER 252 if (pflag) { 253 if ((spkr = open(SPEAKER, O_WRONLY, 0)) == -1) { 254 perror(SPEAKER); 255 exit(1); 256 } 257 dot_clock = wpm / 2.4; /* dots/sec */ 258 dot_clock = 1 / dot_clock; /* duration of a dot */ 259 dot_clock = dot_clock / 2; /* dot_clock runs at twice */ 260 /* the dot rate */ 261 dot_clock = dot_clock * 100; /* scale for ioctl */ 262 } 263#endif 264 argc -= optind; 265 argv += optind; 266 267 if((p = getenv("LC_CTYPE")) || 268 (p = getenv("LC_ALL")) || 269 (p = getenv("LANG"))) { 270 if(strlen(p) >= sizeof(".KOI8-R") && 271 strcasecmp(&p[strlen(p) + 1 - sizeof(".KOI8-R")], ".KOI8-R") == 0) 272 hightab = koi8rtab; 273 } 274 (void) setlocale(LC_CTYPE, ""); 275 276 if (*argv) { 277 do { 278 for (p = *argv; *p; ++p) { 279 morse(*p); 280 } 281 morse(' '); 282 } while (*++argv); 283 } else { 284 while ((ch = getchar()) != EOF) 285 morse(ch); 286 } 287 exit(0); 288} 289 290void 291morse(char c) 292{ 293 struct morsetab *m; 294 295 if (isalpha((unsigned char)c)) 296 c = tolower((unsigned char)c); 297 if ((c == '\r') || (c == '\n')) 298 c = ' '; 299 if (c == ' ') { 300 if (pflag) { 301 play(" "); 302 return; 303 } else { 304 show(""); 305 return; 306 } 307 } 308 for (m = ((unsigned char)c < 0x80? mtab: hightab); 309 m->inchar != '\0'; 310 m++) { 311 if (m->inchar == c) { 312 if (pflag) { 313 play(m->morse); 314 } else 315 show(m->morse); 316 } 317 } 318} 319 320void 321show(const char *s) 322{ 323 if (sflag) 324 printf(" %s", s); 325 else 326 for (; *s; ++s) 327 printf(" %s", *s == '.' ? "dit" : "dah"); 328 printf("\n"); 329} 330 331void 332play(const char *s) 333{ 334#ifdef SPEAKER 335 const char *c; 336 337 for (c = s; *c != '\0'; c++) { 338 switch (*c) { 339 case '.': 340 sound.frequency = freq; 341 sound.duration = dot_clock; 342 break; 343 case '-': 344 sound.frequency = freq; 345 sound.duration = dot_clock * DASH_LEN; 346 break; 347 case ' ': 348 sound.frequency = 0; 349 sound.duration = dot_clock * WORD_SPACE; 350 break; 351 default: 352 sound.duration = 0; 353 } 354 if (sound.duration) { 355 if (ioctl(spkr, SPKRTONE, &sound) == -1) { 356 perror("ioctl play"); 357 exit(1); 358 } 359 } 360 sound.frequency = 0; 361 sound.duration = dot_clock; 362 if (ioctl(spkr, SPKRTONE, &sound) == -1) { 363 perror("ioctl rest"); 364 exit(1); 365 } 366 } 367 sound.frequency = 0; 368 sound.duration = dot_clock * CHAR_SPACE; 369 ioctl(spkr, SPKRTONE, &sound); 370#endif 371} 372