summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--games/bcd/bcd.648
-rw-r--r--games/morse/morse.c150
2 files changed, 179 insertions, 19 deletions
diff --git a/games/bcd/bcd.6 b/games/bcd/bcd.6
index e06dafe..732a4ee 100644
--- a/games/bcd/bcd.6
+++ b/games/bcd/bcd.6
@@ -47,6 +47,8 @@
.Op Ar string ...
.Nm morse
.Op Fl p
+.Op Fl d Ar device
+.Op Fl e
.Op Fl w Ar speed
.Op Fl f Ar frequency
.Op Fl s
@@ -61,28 +63,44 @@ 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
-Available option:
+Available options for program
+.Nm morse :
.Bl -tag -width flag
.It Fl s
The
.Fl s
-option for morse produces dots and dashes rather than words.
+option 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.
+Send morse the real way. This only works if your system has
+.Xr speaker 4
+support.
.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.
+.It Fl d Ar device
+Similar to
+.Fl p ,
+but use the RTS line of
+.Ar device
+.Pq which must by a tty device
+in order to emit the morse code.
+.It Fl e
+echo each character before it is sent, used together with either
+.Fl p
+or
+.Fl d .
.El
.Pp
The
.Fl w
and
.Fl f
-flags only work in conjunction with the
+flags only work in conjunction with either the
.Fl p
+or the
+.Fl d
flag.
.Pp
Not all prosigns have corresponding characters. Use
@@ -110,6 +128,19 @@ and
.Ql +
for
.Em AR .
+.Pp
+Using flag
+.Fl d Ar device
+it is possible to key an external device, like a sidetone generator with
+a headset for training purposes, or even your ham radio transceiver. For
+the latter, simply connect an NPN transistor to the serial port
+.Ar device ,
+emitter connected to ground, base connected through a resistor
+(few kiloohms) to RTS, collector to the key line of your transceiver
+(assuming the transceiver has a positive key supply voltage and is keyed
+by grounding the key input line). A capacitor (some nanofarads) between
+base and ground is advisable to keep stray RF away, and to supress the
+minor glitch that is generated during program startup.
.Sh FILES
.Bl -tag -width /dev/speaker -compact
.It Pa /dev/speaker
@@ -131,10 +162,17 @@ Cyrillic characters. In all other cases, they are being interpreted
as belonging to the
.Ql ISO_8859-1
character set.
+.Sh SEE ALSO
+.Xr speaker 4
.Sh HISTORY
Sound support for
.Nm morse
added by Lyndon Nerenberg (VE7TCP/VE6BBM) <lyndon@orthanc.com>.
+.Pp
+Ability to key an external device added by
+.ie t J\(:org Wunsch
+.el Joerg Wunsch
+(DL8DTL).
.Sh BUGS
Does only understand a few European characters (namely German and
French), but neither Asian ones, or the continental landline code.
diff --git a/games/morse/morse.c b/games/morse/morse.c
index a05f83f..38293a7 100644
--- a/games/morse/morse.c
+++ b/games/morse/morse.c
@@ -50,16 +50,20 @@ static const char rcsid[] =
"$FreeBSD$";
#endif /* not lint */
-#include <stdio.h>
+#include <sys/time.h>
+
#include <ctype.h>
+#include <fcntl.h>
#include <locale.h>
+#include <signal.h>
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <termios.h>
#include <unistd.h>
#ifdef SPEAKER
#include <machine/speaker.h>
-#include <fcntl.h>
#endif
struct morsetab {
@@ -194,19 +198,34 @@ static const struct morsetab koi8rtab[] = {
};
void show(const char *), play(const char *), morse(char);
+void ttyout(const char *);
+void sighandler(int);
+
+#define GETOPTOPTS "d:ef:sw:"
+#define USAGE \
+"usage: morse [-s] [-e] [-d device] [-w speed] [-f frequency] [string ...]\n"
-static int pflag, sflag;
+static int pflag, sflag, eflag;
static int wpm = 20; /* words per minute */
#define FREQUENCY 600
static int freq = FREQUENCY;
+static char *device; /* for tty-controlled generator */
-#ifdef SPEAKER
#define DASH_LEN 3
#define CHAR_SPACE 3
#define WORD_SPACE (7 - CHAR_SPACE - 1)
static float dot_clock;
-int spkr;
+int spkr, line;
+struct termios otty, ntty;
+int olflags;
+
+#ifdef SPEAKER
tone_t sound;
+#undef GETOPTOPTS
+#define GETOPTOPTS "d:ef:psw:"
+#undef USAGE
+#define USAGE \
+"usage: morse [-s] [-p] [-e] [-d device] [-w speed] [-f frequency] [string ...]\n"
#endif
static const struct morsetab *hightab = iso8859tab;
@@ -214,17 +233,26 @@ static const struct morsetab *hightab = iso8859tab;
int
main(int argc, char **argv)
{
- int ch;
+ int ch, lflags;
char *p;
- while ((ch = getopt(argc, argv, "spw:f:")) != -1)
+ while ((ch = getopt(argc, argv, GETOPTOPTS)) != -1)
switch ((char) ch) {
+ case 'd':
+ device = optarg;
+ break;
+ case 'e':
+ eflag = 1;
+ setvbuf(stdout, 0, _IONBF, 0);
+ break;
case 'f':
freq = atoi(optarg);
break;
+#ifdef SPEAKER
case 'p':
pflag = 1;
break;
+#endif
case 's':
sflag = 1;
break;
@@ -233,18 +261,18 @@ main(int argc, char **argv)
break;
case '?':
default:
- fputs("usage: morse [-s] [-p] [-w speed] [-f frequency] [string ...]\n", stderr);
+ fputs(USAGE, stderr);
exit(1);
}
- if (pflag && sflag) {
- fputs("morse: only one of -p and -s allowed\n", stderr);
+ if ((pflag || device) && sflag) {
+ fputs("morse: only one of -p, -d and -s allowed\n", stderr);
exit(1);
}
- if (pflag && ((wpm < 1) || (wpm > 60))) {
+ if ((pflag || device) && ((wpm < 1) || (wpm > 60))) {
fputs("morse: insane speed\n", stderr);
exit(1);
}
- if (pflag && (freq == 0))
+ if ((pflag || device) && (freq == 0))
freq = FREQUENCY;
#ifdef SPEAKER
@@ -253,13 +281,40 @@ main(int argc, char **argv)
perror(SPEAKER);
exit(1);
}
+ } else
+#endif
+ if (device) {
+ if ((line = open(device, O_WRONLY | O_NONBLOCK)) == -1) {
+ perror("open tty line");
+ exit(1);
+ }
+ if (tcgetattr(line, &otty) == -1) {
+ perror("tcgetattr() failed");
+ exit(1);
+ }
+ ntty = otty;
+ ntty.c_cflag |= CLOCAL;
+ tcsetattr(line, TCSANOW, &ntty);
+ lflags = fcntl(line, F_GETFL);
+ lflags &= ~O_NONBLOCK;
+ fcntl(line, F_SETFL, &lflags);
+ ioctl(line, TIOCMGET, &lflags);
+ lflags &= ~TIOCM_RTS;
+ olflags = lflags;
+ ioctl(line, TIOCMSET, &lflags);
+ (void)signal(SIGHUP, sighandler);
+ (void)signal(SIGINT, sighandler);
+ (void)signal(SIGQUIT, sighandler);
+ (void)signal(SIGTERM, sighandler);
+ }
+ if (pflag || device) {
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;
@@ -275,14 +330,23 @@ main(int argc, char **argv)
if (*argv) {
do {
for (p = *argv; *p; ++p) {
+ if (eflag)
+ putchar(*p);
morse(*p);
}
+ if (eflag)
+ putchar(' ');
morse(' ');
} while (*++argv);
} else {
- while ((ch = getchar()) != EOF)
+ while ((ch = getchar()) != EOF) {
+ if (eflag)
+ putchar(ch);
morse(ch);
+ }
}
+ if (device)
+ tcsetattr(line, TCSANOW, &otty);
exit(0);
}
@@ -299,6 +363,9 @@ morse(char c)
if (pflag) {
play(" ");
return;
+ } else if (device) {
+ ttyout(" ");
+ return;
} else {
show("");
return;
@@ -310,6 +377,8 @@ morse(char c)
if (m->inchar == c) {
if (pflag) {
play(m->morse);
+ } else if (device) {
+ ttyout(m->morse);
} else
show(m->morse);
}
@@ -368,3 +437,56 @@ play(const char *s)
ioctl(spkr, SPKRTONE, &sound);
#endif
}
+
+void
+ttyout(const char *s)
+{
+ const char *c;
+ int duration, on, lflags;
+
+ for (c = s; *c != '\0'; c++) {
+ switch (*c) {
+ case '.':
+ on = 1;
+ duration = dot_clock;
+ break;
+ case '-':
+ on = 1;
+ duration = dot_clock * DASH_LEN;
+ break;
+ case ' ':
+ on = 0;
+ duration = dot_clock * WORD_SPACE;
+ break;
+ default:
+ on = 0;
+ duration = 0;
+ }
+ if (on) {
+ ioctl(line, TIOCMGET, &lflags);
+ lflags |= TIOCM_RTS;
+ ioctl(line, TIOCMSET, &lflags);
+ }
+ duration *= 10000;
+ if (duration)
+ usleep(duration);
+ ioctl(line, TIOCMGET, &lflags);
+ lflags &= ~TIOCM_RTS;
+ ioctl(line, TIOCMSET, &lflags);
+ duration = dot_clock * 10000;
+ usleep(duration);
+ }
+ duration = dot_clock * CHAR_SPACE * 10000;
+ usleep(duration);
+}
+
+void
+sighandler(int signo)
+{
+
+ ioctl(line, TIOCMSET, &olflags);
+ tcsetattr(line, TCSANOW, &otty);
+
+ signal(signo, SIG_DFL);
+ (void)kill(getpid(), signo);
+}
OpenPOWER on IntegriCloud