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