morse.c revision 29018
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 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 46static char sccsid[] = "@(#)morse.c 8.1 (Berkeley) 5/31/93"; 47#endif /* not lint */ 48 49#include <stdio.h> 50#include <ctype.h> 51#include <locale.h> 52#include <stdlib.h> 53 54#ifdef SPEAKER 55#include <machine/speaker.h> 56#include <fcntl.h> 57#endif 58 59struct morsetab { 60 char inchar; 61 char *morse; 62}; 63 64static struct morsetab mtab[] = { 65 66 /* letters */ 67 68 'a', ".-", 69 'b', "-...", 70 'c', "-.-.", 71 'd', "-..", 72 'e', ".", 73 'f', "..-.", 74 'g', "--.", 75 'h', "....", 76 'i', "..", 77 'j', ".---", 78 'k', "-.-", 79 'l', ".-..", 80 'm', "--", 81 'n', "-.", 82 'o', "---", 83 'p', ".--.", 84 'q', "--.-", 85 'r', ".-.", 86 's', "...", 87 't', "-", 88 'u', "..-", 89 'v', "...-", 90 'w', ".--", 91 'x', "-..-", 92 'y', "-.--", 93 'z', "--..", 94 95 /* digits */ 96 97 '0', "-----", 98 '1', ".----", 99 '2', "..---", 100 '3', "...--", 101 '4', "....-", 102 '5', ".....", 103 '6', "-....", 104 '7', "--...", 105 '8', "---..", 106 '9', "----.", 107 108 /* punctuation */ 109 110 ',', "--..--", 111 '.', ".-.-.-", 112 '?', "..--..", 113 '/', "-..-.", 114 '-', "-....-", 115 '=', "-...-", /* BT */ 116 ':', "---...", 117 ';', "-.-.-.", 118 '(', "-.--.", /* KN */ 119 ')', "-.--.-", 120 '$', "...-..-", 121 '+', ".-.-.", /* AR */ 122 123 /* prosigns without already assigned values */ 124 125 '#', ".-...", /* AS */ 126 '@', "...-.-", /* SK */ 127 '*', "...-.", /* VE */ 128 '%', "-...-.-", /* BK */ 129 130 '\0', "" 131}; 132 133 134static struct morsetab iso8859tab[] = { 135 '�', ".--.-", 136 '�', ".--.-", 137 '�', ".--.-", 138 '�', ".-.-", 139 '�', "-.-..", 140 '�', "..-..", 141 '�', "..-..", 142 '�', "-..-.", 143 '�', "---.", 144 '�', "..--", 145 146 '\0', "" 147}; 148 149static struct morsetab koi8rtab[] = { 150 /* 151 * the cyrillic alphabet; you'll need a KOI8R font in order 152 * to see the actual characters 153 */ 154 '�', ".-", /* a */ 155 '�', "-...", /* be */ 156 '�', ".--", /* ve */ 157 '�', "--.", /* ge */ 158 '�', "-..", /* de */ 159 '�', ".", /* ye */ 160 '�', ".", /* yo, the same as ye */ 161 '�', "...-", /* she */ 162 '�', "--..", /* ze */ 163 '�', "..", /* i */ 164 '�', ".---", /* i kratkoye */ 165 '�', "-.-", /* ka */ 166 '�', ".-..", /* el */ 167 '�', "--", /* em */ 168 '�', "-.", /* en */ 169 '�', "---", /* o */ 170 '�', ".--.", /* pe */ 171 '�', ".-.", /* er */ 172 '�', "...", /* es */ 173 '�', "-", /* te */ 174 '�', "..-", /* u */ 175 '�', "..-.", /* ef */ 176 '�', "....", /* kha */ 177 '�', "-.-.", /* ce */ 178 '�', "---.", /* che */ 179 '�', "----", /* sha */ 180 '�', "--.-", /* shcha */ 181 '�', "-.--", /* yi */ 182 '�', "-..-", /* myakhkij znak */ 183 '�', "..-..", /* ae */ 184 '�', "..--", /* yu */ 185 '�', ".-.-", /* ya */ 186 187 '\0', "" 188}; 189 190void show(const char *), play(const char *), morse(char); 191 192static int pflag, sflag; 193static int wpm = 20; /* words per minute */ 194#define FREQUENCY 600 195static int freq = FREQUENCY; 196 197#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