Make morse(6) realling playing the characters on the speaker.

Minor additions by me, mostly taken from the suggestion in PR # bin/709.

Submitted by:	lyndon@orthanc.com (Lyndon Nerenberg, VE7TCP/VE6BBM)
This commit is contained in:
Joerg Wunsch 1995-08-27 14:06:15 +00:00
parent bce1959ae5
commit d273a5f24f
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=10352
3 changed files with 365 additions and 76 deletions

View File

@ -45,14 +45,18 @@
.Nm ppt
.Op Ar string ...
.Nm morse
.Op Fl s Ar string ...
.Op Fl p
.Op Fl w Ar speed
.Op Fl f Ar frequency
.Op Fl s
.Op Ar string ...
.Sh DESCRIPTION
The commands
.Nm bcd ,
.Nm ppt
and
.Nm morse
reads the given input and reformats it in the form of punched cards,
read the given input and reformat it in the form of punched cards,
paper tape or morse code respectively.
Acceptable input are command line arguments or the standard input.
.Pp
@ -62,6 +66,70 @@ Available option:
The
.Fl s
option for morse produces dots and dashes rather than words.
.It Fl p
Send morse the real way. This only works if your system has sound
support and if the program understands your audio hardware.
.It Fl w Ar speed
Set the sending speed in words per minute. If not specified the default
speed of 20 WPM is used.
.It Fl f Ar frequency
Set the sidetone frequency to something other than the default 600 Hz.
.El
.Pp
The
.Fl w
and
.Fl f
flags only work in conjunction with the
.Fl p
flag.
.Pp
Not all prosigns have corresponding characters. Use
.Ql #
for
.Em AS ,
.Ql @
for
.Em SK ,
.Ql *
for
.Em VE
and
.Ql %
for
.Em BK .
The more common prosigns are
.Ql =
for
.Em BT ,
.Ql (
for
.Em KN
and
.Ql +
for
.Em AR .
.Sh FILES
.SH HISTORY
.Bl -tag -width /dev/speaker -compact
.It Pa /dev/speaker
speaker device file
.El
.Sh ENVIRONMENT
.Bl -tag -width LC_CTYPE
.It Ev LC_CTYPE
.It Ev LANG
If one of these variables is set to a locale ending in
.Ql KOI8-R ,
characters with the high-order bit set are being interpreted as
cyrillic characters. In all other cases, they are being interpreted
as belonging to the
.Ql ISO_8859-1
character set.
.Sh HISTORY
Sound support added by Lyndon Nerenberg (VE7TCP/VE6BBM) <lyndon@orthanc.com>.
.Sh BUGS
Does only understand a few European characters (namely German and
French), but neither Asian ones, or the continental landline code.
.Pp
Sends a bit slower than it should due to system overhead. Some people
would call this a feature.

View File

@ -3,6 +3,6 @@
PROG= morse
NOMAN= noman
HIDEGAME=hidegame
CFLAGS += -DSPEAKER=\"/dev/speaker\"
.include <bsd.prog.mk>

View File

@ -31,6 +31,11 @@
* SUCH DAMAGE.
*/
/*
* Taught to send *real* morse by Lyndon Nerenberg (VE7TCP/VE6BBM)
* <lyndon@orthanc.com>
*/
#ifndef lint
static char copyright[] =
"@(#) Copyright (c) 1988, 1993\n\
@ -43,103 +48,319 @@ static char sccsid[] = "@(#)morse.c 8.1 (Berkeley) 5/31/93";
#include <stdio.h>
#include <ctype.h>
#include <locale.h>
#include <stdlib.h>
static char
*digit[] = {
"-----",
".----",
"..---",
"...--",
"....-",
".....",
"-....",
"--...",
"---..",
"----.",
},
*alph[] = {
".-",
"-...",
"-.-.",
"-..",
".",
"..-.",
"--.",
"....",
"..",
".---",
"-.-",
".-..",
"--",
"-.",
"---",
".--.",
"--.-",
".-.",
"...",
"-",
"..-",
"...-",
".--",
"-..-",
"-.--",
"--..",
#ifdef SPEAKER
#include <machine/speaker.h>
#include <fcntl.h>
#endif
struct morsetab {
char inchar;
char *morse;
};
static int sflag;
static struct morsetab mtab[] = {
main(argc, argv)
int argc;
char **argv;
/* letters */
'a', ".-",
'b', "-...",
'c', "-.-.",
'd', "-..",
'e', ".",
'f', "..-.",
'g', "--.",
'h', "....",
'i', "..",
'j', ".---",
'k', "-.-",
'l', ".-..",
'm', "--",
'n', "-.",
'o', "---",
'p', ".--.",
'q', "--.-",
'r', ".-.",
's', "...",
't', "-",
'u', "..-",
'v', "...-",
'w', ".--",
'x', "-..-",
'y', "-.--",
'z', "--..",
/* digits */
'0', "-----",
'1', ".----",
'2', "..---",
'3', "...--",
'4', "....-",
'5', ".....",
'6', "-....",
'7', "--...",
'8', "---..",
'9', "----.",
/* punctuation */
',', "--..--",
'.', ".-.-.-",
'?', "..--..",
'/', "-..-.",
'-', "-....-",
'=', "-...-", /* BT */
':', "---...",
';', "-.-.-.",
'(', "-.--.", /* KN */
')', "-.--.-",
'$', "...-..-",
'+', ".-.-.", /* AR */
/* prosigns without already assigned values */
'#', ".-...", /* AS */
'@', "...-.-", /* SK */
'*', "...-.", /* VE */
'%', "-...-.-", /* BK */
'\0', ""
};
static struct morsetab iso8859tab[] = {
'á', ".--.-",
'à', ".--.-",
'â', ".--.-",
'ä', ".-.-",
'ç', "-.-..",
'é', "..-..",
'è', "..-..",
'ê', "-..-.",
'ö', "---.",
'ü', "..--",
'\0', ""
};
static struct morsetab koi8rtab[] = {
/*
* the cyrillic alphabet; you'll need a KOI8R font in order
* to see the actual characters
*/
'Á', ".-", /* a */
'Â', "-...", /* be */
'×', ".--", /* ve */
'Ç', "--.", /* ge */
'Ä', "-..", /* de */
'Å', ".", /* ye */
'Ö', "...-", /* she */
'Ú', "--..", /* ze */
'É', "..", /* i */
'Ê', ".---", /* i kratkoye */
'Ë', "-.-", /* ka */
'Ì', ".-..", /* el */
'Í', "--", /* em */
'Î', "-.", /* en */
'Ï', "---", /* o */
'Ð', ".--.", /* pe */
'Ò', ".-.", /* er */
'Ó', "...", /* es */
'Ô', "-", /* te */
'Õ', "..-", /* u */
'Æ', "..-.", /* ef */
'È', "....", /* kha */
'Ã', "-.-.", /* ce */
'Þ', "---.", /* che */
'Û', "----", /* sha */
'Ý', "--.-", /* shcha */
'Ù', "-.--", /* yi */
'Ø', "-..-", /* myakhkij znak */
'Ü', "..-..", /* ae */
'À', "..--", /* yu */
'Ñ', ".-.-", /* ya */
'\0', ""
};
void show(const char *), play(const char *), morse(char);
static int pflag, sflag;
static int wpm = 20; /* words per minute */
#define FREQUENCY 600
static int freq = FREQUENCY;
#ifdef SPEAKER
#define DASH_LEN 3
#define CHAR_SPACE 3
#define WORD_SPACE (7 - CHAR_SPACE - 1)
static float dot_clock;
int spkr;
tone_t sound;
#endif
static struct morsetab *hightab = iso8859tab;
int
main(int argc, char **argv)
{
extern char *optarg;
extern int optind;
register int ch;
register char *p;
extern char *optarg;
extern int optind;
register int ch;
register char *p;
while ((ch = getopt(argc, argv, "s")) != EOF)
switch((char)ch) {
while ((ch = getopt(argc, argv, "spw:f:")) != EOF)
switch ((char) ch) {
case 'f':
freq = atoi(optarg);
break;
case 'p':
pflag = 1;
break;
case 's':
sflag = 1;
break;
case 'w':
wpm = atoi(optarg);
break;
case '?':
default:
fprintf(stderr, "usage: morse [string ...]");
fputs("usage: morse [-s] [-p] [-w speed] [-f frequency] [string ...]\n", stderr);
exit(1);
}
if (pflag && sflag) {
fputs("morse: only one of -p and -s allowed\n", stderr);
exit(1);
}
if (pflag && ((wpm < 1) || (wpm > 60))) {
fputs("morse: insane speed\n", stderr);
exit(1);
}
if (pflag && (freq == 0))
freq = FREQUENCY;
(void)setuid(getuid());
#ifdef SPEAKER
if (pflag) {
if ((spkr = open(SPEAKER, O_WRONLY, 0)) == -1) {
perror(SPEAKER);
exit(1);
}
dot_clock = wpm / 2.4; /* dots/sec */
dot_clock = 1 / dot_clock; /* duration of a dot */
dot_clock = dot_clock / 2; /* dot_clock runs at twice */
/* the dot rate */
dot_clock = dot_clock * 100; /* scale for ioctl */
}
#endif
argc -= optind;
argv += optind;
if (*argv)
if((p = getenv("LC_CTYPE")) || (p = getenv("LANG"))) {
if(strlen(p) >= strlen("KOI8-R") &&
strcasecmp(&p[strlen(p) - strlen("KOI8-R")], "KOI8-R") == 0)
hightab = koi8rtab;
setlocale(LC_CTYPE, p);
} else {
setlocale(LC_CTYPE, "");
}
if (*argv) {
do {
for (p = *argv; *p; ++p)
morse((int)*p);
for (p = *argv; *p; ++p) {
morse((int) *p);
}
morse((int) ' ');
} while (*++argv);
else while ((ch = getchar()) != EOF)
morse(ch);
} else {
while ((ch = getchar()) != EOF)
morse(ch);
}
exit(0);
}
morse(c)
register int c;
void
morse(char c)
{
struct morsetab *m;
if (isalpha(c))
show(alph[c - (isupper(c) ? 'A' : 'a')]);
else if (isdigit(c))
show(digit[c - '0']);
else if (c == ',')
show("--..--");
else if (c == '.')
show(".-.-.-");
else if (isspace(c))
show(" ...\n");
c = tolower(c);
if ((c == '\r') || (c == '\n'))
c = ' ';
if (c == ' ') {
if (pflag) {
play(" ");
return;
} else {
show("");
return;
}
}
for (m = ((unsigned char)c < 0x80? mtab: hightab);
m->inchar != '\0';
m++) {
if (m->inchar == c) {
if (pflag) {
play(m->morse);
} else
show(m->morse);
}
}
}
show(s)
register char *s;
void
show(const char *s)
{
if (sflag)
printf(" %s", s);
else for (; *s; ++s)
printf(" %s", *s == '.' ? "dit" : "daw");
printf(",\n");
else
for (; *s; ++s)
printf(" %s", *s == '.' ? "dit" : "dah");
printf("\n");
}
void
play(const char *s)
{
#ifdef SPEAKER
const char *c;
for (c = s; *c != '\0'; c++) {
switch ((int) *c) {
case '.':
sound.frequency = freq;
sound.duration = dot_clock;
break;
case '-':
sound.frequency = freq;
sound.duration = dot_clock * DASH_LEN;
break;
case ' ':
sound.frequency = 0;
sound.duration = dot_clock * WORD_SPACE;
break;
default:
sound.duration = 0;
}
if (sound.duration) {
if (ioctl(spkr, SPKRTONE, &sound) == -1) {
perror("ioctl play");
exit(1);
}
}
sound.frequency = 0;
sound.duration = dot_clock;
if (ioctl(spkr, SPKRTONE, &sound) == -1) {
perror("ioctl rest");
exit(1);
}
}
sound.frequency = 0;
sound.duration = dot_clock * CHAR_SPACE;
ioctl(spkr, SPKRTONE, &sound);
#endif
}