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