debian/0000755000000000000000000000000012242230601007156 5ustar debian/gen.10000644000000000000000000000406311302144451010017 0ustar .\" Hey, EMACS: -*- nroff -*- .\" First parameter, NAME, should be all caps .\" Second parameter, SECTION, should be 1-8, maybe w/ subsection .\" other parameters are allowed: see man(7), man(1) .TH MULTIMON 1 "June 19, 2000" .\" Please adjust this date whenever revising the manpage. .\" .\" Some roff macros, for reference: .\" .nh disable hyphenation .\" .hy enable hyphenation .\" .ad l left justify .\" .ad b justify to both left and right margins .\" .nf disable filling .\" .fi enable filling .\" .br insert line break .\" .sp insert n+1 empty lines .\" for manpage-specific macros, see man(7) .SH NAME gen \- program to generate test files of radio transmission modulation .SH SYNOPSIS .B gen .RI [ options ]\ output_file .SH DESCRIPTION This manual page documents briefly the .B gen .br command. This manual page was written for the Debian GNU/Linux distribution because the original program does not have a manual page. .PP .\" TeX users may be more comfortable with the \fB\fP and .\" \fI\fP escape sequences to invode bold face and italics, .\" respectively. \fBmultimon\fP is a program that decodes radio transmissions, \fBgen\fP generates modulated files suitable for decoding with \fBmultimon\fP. .SH OPTIONS .TP .B \-t output file type (any other type than raw requires sox). .br allowed types: raw aiff au hcom sf voc cdr dat smp wav maud vwe .TP .B \-a amplitude. .TP .B \-d encode DTMF string. .TP .B \-z encode ZVEI string. .TP .B \-s encode sine of given frequency. .TP .B \-p encode hdlc packet using specified text. .SH EXAMPLE Create a file /tmp/message.wav containing sound samples of packet radio message: .br gen \-p "This is a message." \-t raw /tmp/message.wav .PP To dial a number directly to the sound card output: .br gen \-d 8675309 .SH SEE ALSO .BR multimon (1) .SH AUTHOR This manual page was written by A. Maitland Bottoms , for the Debian GNU/Linux system (but may be used by others). debian/copyright0000644000000000000000000000124211302154246011116 0ustar This package was debianized by A. Maitland Bottoms on Mon, 19 Jun 2000 17:14:30 -0400. It was downloaded from http://www.ife.ee.ethz.ch/~sailer/ham/linux/multimon.html it is still available at: http://www.baycom.org/~tom/ham/linux/multimon.tar.bz2 Upstream Author: Thomas Sailer Copyright (C) 1996, 1997, 2009 Thomas Sailer (sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu) The added demod_eas.c file and Emergency Alert System demodulator patches: Copyright (C) 2000 A. Maitland Bottoms The software is published under the GNU GPL V2 a copy of which is located in the file /usr/share/common-licenses/GPL-2 debian/patches/0000755000000000000000000000000012242230601010605 5ustar debian/patches/sox-argument.patch0000644000000000000000000000121112230056741014262 0ustar --- a/gen.c +++ b/gen.c @@ -320,7 +320,7 @@ perror("dup2"); close(pipedes[0]); /* close reading pipe end */ execlp("sox", "sox", - "-t", "raw", "-s", "-w", "-r", srate, "-", + "-t", "raw", "-s", "-2", "-r", srate, "-", "-t", type, fname, NULL); perror("execlp"); --- a/unixinput.c +++ b/unixinput.c @@ -323,7 +323,7 @@ close(pipedes[1]); /* close writing pipe end */ execlp("sox", "sox", "-t", type, fname, - "-t", "raw", "-s", "-w", "-r", srate, "-", + "-t", "raw", "-s", "-2", "-r", srate, "-", NULL); perror("execlp"); exit(10); debian/patches/flush-stdout.patch0000644000000000000000000000045512230056741014303 0ustar --- a/unixinput.c +++ b/unixinput.c @@ -73,8 +73,10 @@ va_list args; va_start(args, fmt); - if (verb_level <= verbose_level) + if (verb_level <= verbose_level) { vfprintf(stdout, fmt, args); + fflush(stdout); + } va_end(args); } debian/patches/quiet-output.patch0000644000000000000000000000550012230056741014323 0ustar --- a/unixinput.c +++ b/unixinput.c @@ -371,12 +371,15 @@ "(C) 1996 by Thomas Sailer HB9JNX/AE4WA\n" " -t : input file type (any other type than raw requires sox)\n" " -a : add demodulator\n" -" -s : subtract demodulator\n"; +" -s : subtract demodulator\n" +" -v : verbosity level (0-10)\n" +" -q : quiet output messages\n"; int main(int argc, char *argv[]) { int c; int errflg = 0; + int quiet = 0; int i; char **itype; int mask_first = 1; @@ -384,17 +387,16 @@ unsigned int overlap = 0; char *input_type = "hw"; - fprintf(stdout, "multimod (C) 1996/1997 by Tom Sailer HB9JNX/AE4WA\n" - "available demodulators:"); - for (i = 0; i < NUMDEMOD; i++) - fprintf(stdout, " %s", dem[i]->name); - fprintf(stdout, "\n"); - while ((c = getopt(argc, argv, "t:a:s:v:")) != EOF) { + while ((c = getopt(argc, argv, "t:a:s:v:q")) != EOF) { switch (c) { case '?': errflg++; break; + case 'q': + quiet++; + break; + case 'v': verbose_level = strtoul(optarg, 0, 0); break; @@ -446,17 +448,33 @@ } } + + if (!quiet) + { + fprintf (stdout, "multimod (C) 1996/1997 by Tom Sailer HB9JNX/AE4WA\n" + "available demodulators:"); + for (i = 0; i < NUMDEMOD; i++) + fprintf (stdout, " %s", dem[i]->name); + fprintf (stdout, "\n"); + } + if (errflg) { (void)fprintf(stderr, usage_str); exit(2); } if (mask_first) memset(dem_mask, 0xff, sizeof(dem_mask)); + if (!quiet) + { + fprintf (stdout, "Enabled demodulators:"); + } - fprintf(stdout, "Enabled demodulators:"); for (i = 0; i < NUMDEMOD; i++) if (MASK_ISSET(i)) { - fprintf(stdout, " %s", dem[i]->name); + if (!quiet) + { + fprintf (stdout, " %s", dem[i]->name); + } memset(dem_st+i, 0, sizeof(dem_st[i])); dem_st[i].dem_par = dem[i]; if (dem[i]->init) @@ -464,16 +482,24 @@ if (sample_rate == -1) sample_rate = dem[i]->samplerate; else if (sample_rate != dem[i]->samplerate) { - fprintf(stdout, "\n"); - fprintf(stderr, "Error: Current sampling rate %d, " - " demodulator \"%s\" requires %d\n", - sample_rate, dem[i]->name, dem[i]->samplerate); - exit(3); - } + + if (!quiet) + { + fprintf (stdout, "\n"); + fprintf (stderr, "Error: Current sampling rate %d, " + " demodulator \"%s\" requires %d\n", + sample_rate, dem[i]->name, dem[i]->samplerate); + } + + exit(3); + } if (dem[i]->overlap > overlap) overlap = dem[i]->overlap; } - fprintf(stdout, "\n"); + if (!quiet) + { + fprintf (stdout, "\n"); + } if (!strcmp(input_type, "hw")) { if ((argc - optind) >= 1) debian/patches/gen-xdisplay-updates-2009.patch0000644000000000000000000000253312230056741016300 0ustar Description: newer versions from Thomas Sailer * Include newer gen.c and xdisplay.c versions from Thomas Sailer dated 2009-03-24. (Closes: #247857) --- multimon-1.0.orig/gen.c +++ multimon-1.0/gen.c @@ -299,8 +299,8 @@ static void output_file(unsigned int sam exit(10); } } else { - if (stat(fname, &statbuf)) { - perror("stat"); + if (!stat(fname, &statbuf)) { + fprintf(stderr, "file already exists: %s\n",fname); exit(10); } if (pipe(pipedes)) { --- multimon-1.0.orig/xdisplay.c +++ multimon-1.0/xdisplay.c @@ -1,8 +1,8 @@ /* * xdisplay.c -- actually displaying things * - * Copyright (C) 1996 - * Thomas Sailer (sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu) + * Copyright (C) 1996, 2009 + * Thomas Sailer (t.sailer@alumni.ee.ethz.ch) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -336,6 +336,8 @@ void xdisp_terminate(int cnum) { if (cnum < 0 || cnum >= NUMCLI) return; + if (!cli[cnum].used) + return; kill(cli[cnum].pid, SIGTERM); } @@ -403,6 +405,8 @@ int xdisp_update(int cnum, float *f) if (cnum < 0 || cnum >= NUMCLI) return 0; + if (!cli[cnum].used) + return 0; i = read(cli[cnum].cmdfd, &c, 1); if (i < 0 && errno != EAGAIN) { perror("read"); debian/patches/debian-build.patch0000644000000000000000000000435712230056741014166 0ustar --- a/Makefile +++ b/Makefile @@ -1,33 +1,26 @@ DEBUG =n OS =$(shell uname) -MACH =$(shell uname -m) +ARCHITECTURE =$(shell dpkg --print-architecture) -CFLAGS =-Wall -Wstrict-prototypes -I/usr/X11R6/include +CFLAGS +=-Wall -Wstrict-prototypes -I/usr/X11R6/include ifeq ($(OS),SunOS) ifeq ($(DEBUG),y) CFLAGS +=-g -O -DSUN_AUDIO -DARCH_SPARC else CFLAGS +=-O3 -DSUN_AUDIO -DARCH_SPARC endif -LDFLAGSX =-lX11 -L/usr/X11R6/lib -R/usr/X11R6/lib -lsocket -lnsl +LDFLAGSX +=-lX11 -L/usr/X11R6/lib -R/usr/X11R6/lib -lsocket -lnsl else -ifeq ($(MACH),x86_64) ifeq ($(DEBUG),y) -CFLAGS +=-g -O -DARCH_X86_64 +CFLAGS +=-g -O else -CFLAGS +=-O3 -DARCH_X86_64 +CFLAGS +=-O3 endif -LDFLAGSX =-lX11 -L/usr/X11R6/lib64 -else -ifeq ($(DEBUG),y) -CFLAGS +=-g -O -march=i486 -mtune=pentium4 -falign-loops=2 -falign-jumps=2 \ - -malign-functions=2 -DARCH_I386 -else -CFLAGS +=-O3 -march=i486 -mtune=pentium4 -falign-loops=2 -falign-jumps=2 \ +ifeq ($(ARCHITECTURE),i386) +CFLAGS += -march=i486 -falign-loops=2 -falign-jumps=2 \ -falign-functions=2 -DARCH_I386 endif -LDFLAGSX =-lX11 -L/usr/X11R6/lib -endif +LDFLAGSX +=-lX11 -L/usr/X11R6/lib endif @@ -38,7 +31,7 @@ AS =as LD =ld -LDFLAGS =-lm +LDFLAGS +=-lm HOSTCC =gcc CC =gcc MAKE =make @@ -60,7 +53,7 @@ SRC_L2 =hdlc.c pocsag.c SRC_L1 =demod_afsk12.c demod_afsk24.c demod_afsk24_2.c -SRC_L1 +=demod_hapn48.c demod_fsk96.c +SRC_L1 +=demod_hapn48.c demod_fsk96.c demod_eas.c SRC_L1 +=demod_poc5.c demod_poc12.c demod_poc24.c SRC_L1 +=demod_dtmf.c demod_zvei.c demod_display.c SRC_MISC =unixinput.c costabf.c xdisplay.c @@ -91,17 +84,12 @@ clean: $(RM) -f core `find . -name '*.[oas]' -print` $(RM) -f core `find . -name 'core' -print` - $(RM) -f core costabi.c costabf.c *~ multimon.tar.bz2 - $(RM) -rf bin-* + $(RM) -f core costabi.c costabf.c *~ -depend dep: $(BINDIR) costabi.c costabf.c +depend dep: $(CPP) -M $(CFLAGS) $(SRC_MISC) $(SRC_L1) $(SRC_L2) $(SRC_GEN) mkcostab.c > $(BINDIR)/.depend -dist: - tar cjf multimon.tar.bz2 COPYING Makefile filter.h filter-i386.h gen.h multimon.h \ - $(SRC_MISC) $(SRC_L1) $(SRC_L2) $(SRC_GEN) mkcostab.c - ifeq ($(BINDIR)/.depend,$(wildcard $(BINDIR)/.depend)) include $(BINDIR)/.depend endif debian/patches/demod-eas.patch0000644000000000000000000001441012230056741013474 0ustar Description: demod_eas Demodulate Emergency Alert System tones. --- multimon-1.0.orig/filter-i386.h +++ multimon-1.0/filter-i386.h @@ -263,6 +263,10 @@ extern inline float __mac_c(const float "r" (b) : "memory"); return f; + case 42: + /* Thomas, Help! EAS needs this optimized. -Maitland */ + return __mac_g(a, b, size); + default: printf("Warning: optimize __mac_c(..., ..., %d)\n", size); return __mac_g(a, b, size); @@ -271,7 +275,3 @@ extern inline float __mac_c(const float /* ---------------------------------------------------------------------- */ #endif /* _FILTER_I386_H */ - - - - --- multimon-1.0.orig/multimon.h +++ multimon-1.0/multimon.h @@ -1,6 +1,8 @@ /* * multimon.h -- Monitor for many different modulation formats * + * Added eas parts - A. Maitland Bottoms 27 June 2000 + * * Copyright (C) 1996 * Thomas Sailer (sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu) * @@ -74,6 +76,13 @@ struct demod_state { unsigned int sphase; } poc24; + struct l1_state_eas { + unsigned int dcd_shreg; + unsigned int sphase; + unsigned int lasts; + unsigned int subsamp; + } eas; + struct l1_state_afsk12 { unsigned int dcd_shreg; unsigned int sphase; @@ -137,6 +146,8 @@ extern const struct demod_param demod_po extern const struct demod_param demod_poc12; extern const struct demod_param demod_poc24; +extern const struct demod_param demod_eas; + extern const struct demod_param demod_afsk1200; extern const struct demod_param demod_afsk2400; extern const struct demod_param demod_afsk2400_2; @@ -149,7 +160,7 @@ extern const struct demod_param demod_zv extern const struct demod_param demod_scope; -#define ALL_DEMOD &demod_poc5, &demod_poc12, &demod_poc24, \ +#define ALL_DEMOD &demod_poc5, &demod_poc12, &demod_poc24, &demod_eas, \ &demod_afsk1200, &demod_afsk2400, &demod_afsk2400_2, &demod_hapn4800, \ &demod_fsk9600, &demod_dtmf, &demod_zvei, &demod_scope --- /dev/null +++ multimon-1.0/demod_eas.c @@ -0,0 +1,140 @@ +/* + * demod_eas.c -- Emergency Alert System demodulator + * + * See http://www.nws.noaa.gov/nwr/nwrsame.htm + * + * Copyright (C) 2000 + * A. Maitland Bottoms + * + * Licensed under same terms and based upon the + * demod_afsk12.c -- 1200 baud AFSK demodulator + * + * Copyright (C) 1996 + * Thomas Sailer (sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* ---------------------------------------------------------------------- */ + +#include "multimon.h" +#include "filter.h" +#include +#include + +/* ---------------------------------------------------------------------- */ + +/* + * Standard TCM3105 clock frequency: 4.4336MHz + * Bit Parameters + * The following definitions of a bit are based on a bit period equaling + * 1920 microseconds (± one microsecond). + * a.) The speed is 520.83 bits per second + * b.) Logic zero is 1562.5 Hz. + * c.) Logic one is 2083.3 Hz + */ + +#define FREQ_MARK 1083.3 +#define FREQ_SPACE 1562.5 +#define FREQ_SAMP 22050 +#define BAUD 520.83 +#define SUBSAMP 2 + +/* ---------------------------------------------------------------------- */ + +#define CORRLEN ((int)(FREQ_SAMP/BAUD)) +#define SPHASEINC (0x10000u*BAUD*SUBSAMP/FREQ_SAMP) + +static float corr_mark_i[CORRLEN]; +static float corr_mark_q[CORRLEN]; +static float corr_space_i[CORRLEN]; +static float corr_space_q[CORRLEN]; + +/* ---------------------------------------------------------------------- */ + +static void eas_init(struct demod_state *s) +{ + float f; + int i; + + hdlc_init(s); + memset(&s->l1.eas, 0, sizeof(s->l1.eas)); + for (f = 0, i = 0; i < CORRLEN; i++) { + corr_mark_i[i] = cos(f); + corr_mark_q[i] = sin(f); + f += 2.0*M_PI*FREQ_MARK/FREQ_SAMP; + } + for (f = 0, i = 0; i < CORRLEN; i++) { + corr_space_i[i] = cos(f); + corr_space_q[i] = sin(f); + f += 2.0*M_PI*FREQ_SPACE/FREQ_SAMP; + } +} + +/* ---------------------------------------------------------------------- */ + +static void eas_demod(struct demod_state *s, float *buffer, int length) +{ + float f; + unsigned char curbit; + + if (s->l1.eas.subsamp) { + int numfill = SUBSAMP - s->l1.eas.subsamp; + if (length < numfill) { + s->l1.eas.subsamp += length; + return; + } + buffer += numfill; + length -= numfill; + s->l1.eas.subsamp = 0; + } + for (; length >= SUBSAMP; length -= SUBSAMP, buffer += SUBSAMP) { + f = fsqr(mac(buffer, corr_mark_i, CORRLEN)) + + fsqr(mac(buffer, corr_mark_q, CORRLEN)) - + fsqr(mac(buffer, corr_space_i, CORRLEN)) - + fsqr(mac(buffer, corr_space_q, CORRLEN)); + s->l1.eas.dcd_shreg <<= 1; + s->l1.eas.dcd_shreg |= (f > 0); + verbprintf(10, "%c", '0'+(s->l1.eas.dcd_shreg & 1)); + /* + * check if transition + */ + if ((s->l1.eas.dcd_shreg ^ (s->l1.eas.dcd_shreg >> 1)) & 1) { + if (s->l1.eas.sphase < (0x8000u-(SPHASEINC/2))) + s->l1.eas.sphase += SPHASEINC/8; + else + s->l1.eas.sphase -= SPHASEINC/8; + } + s->l1.eas.sphase += SPHASEINC; + if (s->l1.eas.sphase >= 0x10000u) { + s->l1.eas.sphase &= 0xffffu; + s->l1.eas.lasts <<= 1; + s->l1.eas.lasts |= s->l1.eas.dcd_shreg & 1; + curbit = (s->l1.eas.lasts ^ + (s->l1.eas.lasts >> 1) ^ 1) & 1; + verbprintf(9, " %c ", '0'+curbit); + hdlc_rxbit(s, curbit); + } + } + s->l1.eas.subsamp = length; +} + +/* ---------------------------------------------------------------------- */ + +const struct demod_param demod_eas = { + "EAS", FREQ_SAMP, CORRLEN, eas_init, eas_demod +}; + +/* ---------------------------------------------------------------------- */ debian/patches/ccir-added.patch0000644000000000000000000003203411423643147013624 0ustar diff -u multimon-1.0/demod_ccir.c multimon-alfa-partly/demod_ccir.c --- multimon-1.0/demod_ccir.c 2010-07-27 22:47:43.045912226 +0200 +++ multimon-alfa-partly/demod_ccir.c 2010-07-27 22:46:55.000000000 +0200 @@ -0,0 +1,149 @@ +/* + * demod_ccir.c -- CCIR signalling demodulator/decoder + * + * Copyright (C) 1996 + * Thomas Sailer (sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * + * Copied from demod_zvei.c and modified by Mathias Bøhn Grytemark, 2010, by idea of Mathias Nilsen. +*/ + +/* ---------------------------------------------------------------------- */ + +#include "multimon.h" +#include "filter.h" +#include +#include + +/* ---------------------------------------------------------------------- */ + +#define SAMPLE_RATE 22050 +#define BLOCKLEN (SAMPLE_RATE/100) /* 10ms blocks */ +#define BLOCKNUM 4 /* must match numbers in multimon.h */ + +#define PHINC(x) ((x)*0x10000/SAMPLE_RATE) + +static const unsigned int ccir_freq[16] = { + PHINC(1981), PHINC(1124), PHINC(1197), PHINC(1275), + PHINC(1358), PHINC(1446), PHINC(1540), PHINC(1640), + PHINC(1747), PHINC(1860), PHINC(2400), PHINC(930), + PHINC(2247), PHINC(991), PHINC(2110), PHINC(1055) +}; + +static const unsigned int ccirs_freq[16] = { + PHINC(1981), PHINC(1124), PHINC(1197), PHINC(1275), + PHINC(1358), PHINC(1446), PHINC(1540), PHINC(1640), + PHINC(1747), PHINC(1860), PHINC(2400), PHINC(930), + PHINC(2247), PHINC(991), PHINC(2110), PHINC(1055) +}; + +/* ---------------------------------------------------------------------- */ + +static void ccir_init(struct demod_state *s) +{ + memset(&s->l1.ccir, 0, sizeof(s->l1.ccir)); +} + +/* ---------------------------------------------------------------------- */ + +static int find_max_idx(const float *f) +{ + float en = 0; + int idx = -1, i; + + for (i = 0; i < 16; i++) + if (f[i] > en) { + en = f[i]; + idx = i; + } + if (idx < 0) + return -1; + en *= 0.1; + for (i = 0; i < 16; i++) + if (idx != i && f[i] > en) + return -1; + return idx; +} + +/* ---------------------------------------------------------------------- */ + +static inline int process_block(struct demod_state *s) +{ + float tote; + float totte[32]; + int i, j; + + tote = 0; + for (i = 0; i < BLOCKNUM; i++) + tote += s->l1.ccir.energy[i]; + for (i = 0; i < 32; i++) { + totte[i] = 0; + for (j = 0; j < BLOCKNUM; j++) + totte[i] += s->l1.ccir.tenergy[j][i]; + } + for (i = 0; i < 16; i++) + totte[i] = fsqr(totte[i]) + fsqr(totte[i+16]); + memmove(s->l1.ccir.energy+1, s->l1.ccir.energy, + sizeof(s->l1.ccir.energy) - sizeof(s->l1.ccir.energy[0])); + s->l1.ccir.energy[0] = 0; + memmove(s->l1.ccir.tenergy+1, s->l1.ccir.tenergy, + sizeof(s->l1.ccir.tenergy) - sizeof(s->l1.ccir.tenergy[0])); + memset(s->l1.ccir.tenergy, 0, sizeof(s->l1.ccir.tenergy[0])); + tote *= (BLOCKNUM*BLOCKLEN*0.5); /* adjust for block lengths */ + verbprintf(10, "CCIR: Energies: %8.5f %8.5f %8.5f %8.5f %8.5f %8.5f %8.5f %8.5f %8.5f" + " %8.5f %8.5f %8.5f %8.5f %8.5f %8.5f %8.5f %8.5f\n", + tote, totte[0], totte[1], totte[2], totte[3], totte[4], totte[5], totte[6], totte[7], + totte[8], totte[9], totte[10], totte[11], totte[12], totte[13], totte[14], totte[15]); + if ((i = find_max_idx(totte)) < 0) + return -1; + if ((tote * 0.4) > totte[i]) + return -1; + return i; +} + +/* ---------------------------------------------------------------------- */ + +static void ccir_demod(struct demod_state *s, float *buffer, int length) +{ + float s_in; + int i; + + for (; length > 0; length--, buffer++) { + s_in = *buffer; + s->l1.ccir.energy[0] += fsqr(s_in); + for (i = 0; i < 16; i++) { + s->l1.ccir.tenergy[0][i] += COS(s->l1.ccir.ph[i]) * s_in; + s->l1.ccir.tenergy[0][i+16] += SIN(s->l1.ccir.ph[i]) * s_in; + s->l1.ccir.ph[i] += ccir_freq[i]; + } + if ((s->l1.ccir.blkcount--) <= 0) { + s->l1.ccir.blkcount = BLOCKLEN; + i = process_block(s); + if (i != s->l1.ccir.lastch && i >= 0) + verbprintf(0, "CCIR: %1x\n", i); + s->l1.ccir.lastch = i; + } + } +} + +/* ---------------------------------------------------------------------- */ + +const struct demod_param demod_ccir = { + "CCIR", SAMPLE_RATE, 0, ccir_init, ccir_demod +}; + +/* ---------------------------------------------------------------------- */ Common subdirectories: multimon-1.0/filter and multimon-alfa-partly/filter diff -u multimon-1.0/gen.c multimon-alfa-partly/gen.c --- multimon-1.0/gen.c 2010-07-27 22:46:07.069912183 +0200 +++ multimon-alfa-partly/gen.c 2010-07-27 22:46:55.753412205 +0200 @@ -73,11 +73,11 @@ typedef int (*t_gen_procs)(signed short *, int, struct gen_params *, struct gen_state *); static const t_init_procs init_procs[] = { - gen_init_dtmf, gen_init_sine, gen_init_zvei, gen_init_hdlc + gen_init_dtmf, gen_init_sine, gen_init_zvei, gen_init_ccir, gen_init_hdlc }; static const t_gen_procs gen_procs[] = { - gen_dtmf, gen_sine, gen_zvei, gen_hdlc + gen_dtmf, gen_sine, gen_zvei, gen_ccir, gen_hdlc }; /* ---------------------------------------------------------------------- */ @@ -364,6 +364,7 @@ " -a : amplitude\n" " -d : encode DTMF string\n" " -z : encode ZVEI string\n" +" -c : encode CCIR string\n" " -s : encode sine\n" " -p : encode hdlc packet\n"; @@ -376,7 +377,7 @@ char *cp; fprintf(stdout, "gen - (C) 1997 by Tom Sailer HB9JNX/AE4WA\n"); - while ((c = getopt(argc, argv, "t:a:d:s:z:p:")) != EOF) { + while ((c = getopt(argc, argv, "t:a:d:s:z:c:p:")) != EOF) { switch (c) { case '?': errflg++; @@ -453,6 +454,20 @@ strncpy(params[num_gen-1].p.zvei.str, optarg, sizeof(params[num_gen-1].p.dtmf.str)); break; + case 'c': + num_gen++; + if (num_gen > MAX_GEN) { + fprintf(stderr, "too many generators\n"); + errflg++; + break; + } + params[num_gen-1].type = gentype_ccir; + params[num_gen-1].ampl = 16384; + params[num_gen-1].p.ccir.duration = MS(100); + params[num_gen-1].p.ccir.pause = MS(10); + strncpy(params[num_gen-1].p.ccir.str, optarg, sizeof(params[num_gen-1].p.dtmf.str)); + break; + case 'p': num_gen++; if (num_gen > MAX_GEN) { diff -u multimon-1.0/gen_ccir.c multimon-alfa-partly/gen_ccir.c --- multimon-1.0/gen_ccir.c 2010-07-27 22:47:36.209912392 +0200 +++ multimon-alfa-partly/gen_ccir.c 2010-07-27 22:46:55.000000000 +0200 @@ -0,0 +1,90 @@ +/* + * gen_ccir.c -- generate DTMF sequences + * + * Copyright (C) 1997 + * Thomas Sailer (sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * + * Copied from gen_zvei.c and modified by Mathias Bøhn Grytemark, 2010, by idea of Mathias Nilsen. +*/ + +/* ---------------------------------------------------------------------- */ + +#include "gen.h" +#include +#include +#include + +/* ---------------------------------------------------------------------- */ + +#define PHINC(x) ((float)(x)*0x10000/SAMPLE_RATE) + +static const unsigned int ccir_freq[16] = { + PHINC(1981), PHINC(1124), PHINC(1197), PHINC(1275), + PHINC(1358), PHINC(1446), PHINC(1540), PHINC(1640), + PHINC(1747), PHINC(1860), PHINC(2400), PHINC(930), + PHINC(2247), PHINC(991), PHINC(2110), PHINC(1055) +}; + +static const unsigned int ccirs_freq[16] = { + PHINC(1981), PHINC(1124), PHINC(1197), PHINC(1275), + PHINC(1358), PHINC(1446), PHINC(1540), PHINC(1640), + PHINC(1747), PHINC(1860), PHINC(2400), PHINC(930), + PHINC(2247), PHINC(991), PHINC(2110), PHINC(1055) +}; + +void gen_init_ccir(struct gen_params *p, struct gen_state *s) +{ + memset(s, 0, sizeof(struct gen_state)); +} + +int gen_ccir(signed short *buf, int buflen, struct gen_params *p, struct gen_state *s) +{ + char c; + int num = 0, i; + + for (; buflen > 0; buflen--, buf++, num++) { + if (s->s.ccir.time <= 0) { + c = p->p.ccir.str[s->s.ccir.ch_idx]; + if (!c) + return num; + s->s.ccir.ch_idx++; + if (!isxdigit(c)) { + s->s.ccir.time = s->s.ccir.time2 = 1; + fprintf(stderr, "gen: ccir; invalid char '%c'\n", c); + } else { + s->s.ccir.time = p->p.ccir.duration + p->p.ccir.pause; + s->s.ccir.time2 = p->p.ccir.duration; + if (c >= '0' && c <= '9') + i = c - '0'; + else if (c >= 'A' && c <= 'F') + i = c - 'A' + 10; + else + i = c - 'a' + 10; + s->s.ccir.phinc = ccir_freq[i & 0xf]; + } + } else if (!s->s.ccir.time2) { + s->s.ccir.phinc = 0; + s->s.ccir.ph = 0xc000; + } + s->s.ccir.time--; + s->s.ccir.time2--; + *buf += (p->ampl * COS(s->s.ccir.ph)) >> 15; + s->s.ccir.ph += s->s.ccir.phinc; + } + return num; +} diff -u multimon-1.0/gen.h multimon-alfa-partly/gen.h --- multimon-1.0/gen.h 2002-12-04 03:49:15.000000000 +0100 +++ multimon-alfa-partly/gen.h 2010-07-27 22:46:55.774837599 +0200 @@ -28,7 +28,7 @@ #define COS(x) costabi[(((x)>>6)&0x3ffu)] -enum gen_type { gentype_dtmf, gentype_sine, gentype_zvei, gentype_hdlc }; +enum gen_type { gentype_dtmf, gentype_sine, gentype_zvei, gentype_ccir, gentype_hdlc }; struct gen_params { enum gen_type type; @@ -49,6 +49,11 @@ char str[256]; } zvei; struct { + int duration; + int pause; + char str[256]; + } ccir; + struct { int modulation; int txdelay; int pktlen; @@ -74,6 +79,11 @@ int time, time2; } zvei; struct { + int ch_idx; + int ph, phinc; + int time, time2; + } ccir; + struct { int lastb; int ch_idx, bitmask; unsigned int ph, phinc, bitph; @@ -92,6 +102,9 @@ extern void gen_init_zvei(struct gen_params *p, struct gen_state *s); extern int gen_zvei(signed short *buf, int buflen, struct gen_params *p, struct gen_state *s); +extern void gen_init_ccir(struct gen_params *p, struct gen_state *s); +extern int gen_ccir(signed short *buf, int buflen, struct gen_params *p, struct gen_state *s); + extern void gen_init_hdlc(struct gen_params *p, struct gen_state *s); extern int gen_hdlc(signed short *buf, int buflen, struct gen_params *p, struct gen_state *s); diff -u multimon-1.0/Makefile multimon-alfa-partly/Makefile --- multimon-1.0/Makefile 2010-07-27 22:29:08.000000000 +0200 +++ multimon-alfa-partly/Makefile 2010-07-27 22:46:55.774837599 +0200 @@ -55,10 +55,10 @@ SRC_L1 =demod_afsk12.c demod_afsk24.c demod_afsk24_2.c SRC_L1 +=demod_hapn48.c demod_fsk96.c demod_eas.c SRC_L1 +=demod_poc5.c demod_poc12.c demod_poc24.c -SRC_L1 +=demod_dtmf.c demod_zvei.c demod_display.c +SRC_L1 +=demod_dtmf.c demod_zvei.c demod_ccir.c demod_display.c SRC_MISC =unixinput.c costabf.c xdisplay.c -SRC_GEN =gen.c gen_dtmf.c gen_sin.c gen_zvei.c gen_hdlc.c costabi.c +SRC_GEN =gen.c gen_dtmf.c gen_sin.c gen_zvei.c gen_ccir.c gen_hdlc.c costabi.c OBJ_L2 =$(SRC_L2:%.c=$(BINDIR)/%.o) OBJ_L1 =$(SRC_L1:%.c=$(BINDIR)/%.o) diff -u multimon-1.0/multimon.h multimon-alfa-partly/multimon.h --- multimon-1.0/multimon.h 2010-07-27 22:29:08.000000000 +0200 +++ multimon-alfa-partly/multimon.h 2010-07-27 22:46:55.774837599 +0200 @@ -123,6 +123,14 @@ int blkcount; int lastch; } zvei; + + struct l1_state_ccir { + unsigned int ph[16]; + float energy[4]; + float tenergy[4][32]; + int blkcount; + int lastch; + } ccir; struct l1_state_scope { int datalen; @@ -157,12 +165,13 @@ extern const struct demod_param demod_dtmf; extern const struct demod_param demod_zvei; +extern const struct demod_param demod_ccir; extern const struct demod_param demod_scope; #define ALL_DEMOD &demod_poc5, &demod_poc12, &demod_poc24, &demod_eas, \ &demod_afsk1200, &demod_afsk2400, &demod_afsk2400_2, &demod_hapn4800, \ -&demod_fsk9600, &demod_dtmf, &demod_zvei, &demod_scope +&demod_fsk9600, &demod_dtmf, &demod_zvei, &demod_ccir, &demod_scope /* ---------------------------------------------------------------------- */ debian/patches/multimon-endian.patch0000644000000000000000000000111612230056741014735 0ustar --- a/unixinput.c +++ b/unixinput.c @@ -182,13 +182,12 @@ perror("open"); exit (10); } - sndparam = AFMT_S16_LE; /* we want 16 bits/sample signed */ - /* little endian; works only on little endian systems! */ + sndparam = AFMT_S16_NE; /* we want 16 bits/sample signed */ if (ioctl(fd, SNDCTL_DSP_SETFMT, &sndparam) == -1) { perror("ioctl: SNDCTL_DSP_SETFMT"); exit (10); } - if (sndparam != AFMT_S16_LE) { + if (sndparam != AFMT_S16_NE) { fmt = 1; sndparam = AFMT_U8; if (ioctl(fd, SNDCTL_DSP_SETFMT, &sndparam) == -1) { debian/patches/series0000644000000000000000000000026412242227301012027 0ustar gen-xdisplay-updates-2009.patch multimon-endian.patch sox-argument.patch debian-build.patch demod-eas.patch flush-stdout.patch quiet-output.patch fix-stereo.patch ccir-added.patch debian/patches/fix-stereo.patch0000644000000000000000000000345012230056741013725 0ustar --- a/unixinput.c +++ b/unixinput.c @@ -106,6 +106,7 @@ unsigned int fbuf_cnt = 0; int i; short *sp; + int stereo = 0; if ((fd = open(ifname ? ifname : "/dev/audio", O_RDONLY)) < 0) { perror("open"); @@ -179,17 +180,19 @@ short *sp; unsigned char *bp; int fmt = 0; + int stereo = 0; if ((fd = open(ifname ? ifname : "/dev/dsp", O_RDONLY)) < 0) { perror("open"); exit (10); } - sndparam = AFMT_S16_NE; /* we want 16 bits/sample signed */ + sndparam = AFMT_S16_LE; /* we want 16 bits/sample signed */ + /* little endian; works only on little endian systems! */ if (ioctl(fd, SNDCTL_DSP_SETFMT, &sndparam) == -1) { perror("ioctl: SNDCTL_DSP_SETFMT"); exit (10); } - if (sndparam != AFMT_S16_NE) { + if (sndparam != AFMT_S16_LE) { fmt = 1; sndparam = AFMT_U8; if (ioctl(fd, SNDCTL_DSP_SETFMT, &sndparam) == -1) { @@ -206,6 +209,11 @@ perror("ioctl: SNDCTL_DSP_STEREO"); exit (10); } + if (sndparam == 1) { + fprintf(stderr, "soundif: Warning, cannot set the channel " + "number to 1, will use stereo\n"); + stereo=1; + } else if (sndparam != 0) { fprintf(stderr, "soundif: Error, cannot set the channel " "number to 1\n"); @@ -262,8 +270,13 @@ if (!i) break; if (i > 0) { - for (; i >= sizeof(b.s[0]); i -= sizeof(b.s[0]), sp++) - fbuf[fbuf_cnt++] = (*sp) * (1.0/32768.0); + if (stereo) { + for (; i >= sizeof(b.s[0]); i -= (sizeof(b.s[0])*2), sp+=2) + fbuf[fbuf_cnt++] = (*sp) * (1.0/32768.0); + } else { + for (; i >= sizeof(b.s[0]); i -= sizeof(b.s[0]), sp++) + fbuf[fbuf_cnt++] = (*sp) * (1.0/32768.0); + } if (i) fprintf(stderr, "warning: noninteger number of samples read\n"); if (fbuf_cnt > overlap) { debian/control0000644000000000000000000000241312230057024010564 0ustar Source: multimon Section: hamradio Priority: optional Maintainer: A. Maitland Bottoms Build-Depends: debhelper (>= 9), libx11-dev, x11proto-core-dev Standards-Version: 3.9.4 Package: multimon Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends}, sox Recommends: alsa-oss Description: Linux Radio Transmission Decoder The multimon software can decode a variety of digital transmission modes commonly found on UHF radio. A standard PC soundcard is used to acquire the signal from a transceiver. The decoding is done completely in software. Currently, the following modes are supported: AX.25 1200 Baud AFSK 2400 Baud AFSK (2 variants) 4800 Baud HAPN 9600 Baud FSK (G3RUH) POCSAG 512 Baud 1200 Baud 2400 Baud Miscellaneous DTMF ZVEI An arbitrary set of the above modes may run concurrently on the same input signal (provided the CPU power is sufficient), so you do not have to know in advance which mode is used. Note however that some modes might require modifications to the radio (especially the 9600 baud FSK and the POCSAG modes) to work properly. POCSAG (Post Office Code Standards Advisory Group) is a common paging transmission format. debian/dirs0000644000000000000000000000003311302144451010041 0ustar usr/bin usr/share/man/man1 debian/changelog0000644000000000000000000000525512242230257011046 0ustar multimon (1.0-7) unstable; urgency=low * demod_ccir.c, gen.c, gen_ccir.c, gen.h, Makefile, multimon.h: Apply patch from Mathias Bøhn Grytemark adding support for CCIR output and decoding. -- A. Maitland Bottoms Sun, 17 Nov 2013 16:09:59 -0500 multimon (1.0-6) unstable; urgency=low * apply sox fix to gen.c as well (Closes: #592754) * Use AFMT_S16_NE "native"-endian sound format (Closes: #563295) * Incorporate Daniel Bair's patch collection: * Fix for stereo only systems * Fix to completely flush the buffer on verbprint (LP: #729299) * Added option to quiet output messages * Added example dtmf_insert.pl script * Updated man page to reflect changes -- A. Maitland Bottoms Wed, 16 Oct 2013 23:02:41 -0400 multimon (1.0-5) unstable; urgency=low * Include newer gen.c and xdisplay.c versions from Thomas Sailer dated 2009-03-24. (Closes: #247857) * Include Joerg Woelke's patch to run sox correctly. (Closes: #536228) * depend upon sox. (Closes: #555391) * The man pages added in 1.0-4 must help, no recent complaints. (Closes: #205003) -- A. Maitland Bottoms Sun, 22 Nov 2009 00:18:25 -0500 multimon (1.0-4.1) unstable; urgency=low * Non-maintainer upload. * Update build depend from x-dev to x11proto-core-dev. * Replace -m486 with -march=i486 in CGLAGS to get it building with GCC 4.3. Patch by Evgeni Golov. (Closes: #474873) * Move compat version to debian/compat. * Make clean target do not ignore all errors. -- Ana Beatriz Guerrero Lopez Wed, 23 Apr 2008 20:07:45 +0200 multimon (1.0-4) unstable; urgency=low * Update standards version, use non-native package format * refine X library dependencies due to removed xlibs-dev (Closes: #347013) * tidy up manpage situation, answer questions raised in bug reports: refer to /usr/share/doc/multimon (Closes: #282540 #332421) add some usage example text (Closes: #183190) -- A. Maitland Bottoms Mon, 16 Jan 2006 11:17:52 -0500 multimon (1.0-3) unstable; urgency=low * Update standards version, add Build-Depends line * Rebuild to update X library dependencies (Closes: #170233) -- A. Maitland Bottoms Sun, 1 Dec 2002 12:14:44 -0500 multimon (1.0-2) unstable; urgency=low * test for Intel architecture before using (e.g. -m486) flags, (closes:Bug#66281) * Initial Emergency Alert System (EAS) decoder hacking -- A. Maitland Bottoms Tue, 27 Jun 2000 22:28:14 -0400 multimon (1.0-1) unstable; urgency=low * Initial Release. -- A. Maitland Bottoms Mon, 19 Jun 2000 17:14:30 -0400 debian/README.Debian0000644000000000000000000000141311302144451011221 0ustar multimon for Debian ---------------------- Source was taken from http://www.ife.ee.ethz.ch/~sailer/ham/linux/multimon.html, although it appears that Sourceforge.net has it too. TODO: Add hooks to use this with a sound data multiplexer, so that I might have multimon running while also shipping the sound data off over speak-freely. Decode data bursts from EBS and NOAA weather radio - and make use of that data. -- A. Maitland Bottoms , Mon Jan 16 11:22:38 2006 Source for non-native package: wget http://www.baycom.org/~tom/ham/linux/multimon.tar.bz2 mkdir multimon-1.0 cd multimon-1.0 tar jxvf ../multimon.tar.bz2 cd .. tar zcf multimon_1.0.orig.tar.gz multimon-1.0 -- A. Maitland Bottoms Mon, 16 Jan 2006 11:17:52 -0500 debian/examples0000644000000000000000000000002612230057013010716 0ustar debian/dtmf_insert.pl debian/menu0000644000000000000000000000015411302146605010053 0ustar ?package(multimon):needs="X11" section="Applications/Sound"\ title="multimon" command="/usr/bin/multimon" debian/dtmf_insert.pl0000644000000000000000000000207012230057002012027 0ustar #!/usr/bin/perl # Path to multimon # $mm = "/usr/bin/multimon -a DTMF 2> /dev/null"; $mm = "aoss multimon -q -a DTMF"; # Tone/DTMF string to trigger on # $on_str = "123"; $on_str = "*43"; @on_arr = split(//,"$on_str"); # Command or script to execute # $on_cmd = "echo Fire Fire Fire | mail -s Fire you@cellphone.com"; $on_cmd = "bash run_rml_on_dtmf_trigger.sh"; select STDOUT; $| = 1; $l = 0; $l = 0; $ans = ""; sub System { if ((0xffff & system $args) != 0 ) { print STDERR "error: $!\n"; exit 1; } } open M, "$mm |" || die "Can't open $mm: $!\n"; while () { ($a, $b) = split ':'; # $b =~ tr/0-9*#ABCD//csd; # Allow 0-9 * # A B C D $b =~ tr/0-9*#//csd; # Allow 0-9 * # $i = length $ans; if ($b eq $on_arr[$i]) { $ans .= $b; } elsif ($l ge "5") { $l = 0; $ans = ""; } $l++; if ((length $ans) == (length $on_str)) { print localtime()."\n$ans detected. Running $on_cmd\n"; if ($ans eq $on_str) { System($args = $on_cmd); $l = 0; $ans = ""; } else { $l = 0; $ans = ""; } } } debian/source/0000755000000000000000000000000012230057052010462 5ustar debian/source/format0000644000000000000000000000001411671413411011673 0ustar 3.0 (quilt) debian/compat0000644000000000000000000000000212230056765010372 0ustar 9 debian/rules0000755000000000000000000000003512230057027010242 0ustar #!/usr/bin/make -f %: dh $@ debian/multimon.10000644000000000000000000000753212230056776011133 0ustar .\" Hey, EMACS: -*- nroff -*- .\" First parameter, NAME, should be all caps .\" Second parameter, SECTION, should be 1-8, maybe w/ subsection .\" other parameters are allowed: see man(7), man(1) .TH MULTIMON 1 "June 19, 2000" .\" Please adjust this date whenever revising the manpage. .\" .\" Some roff macros, for reference: .\" .nh disable hyphenation .\" .hy enable hyphenation .\" .ad l left justify .\" .ad b justify to both left and right margins .\" .nf disable filling .\" .fi enable filling .\" .br insert line break .\" .sp insert n+1 empty lines .\" for manpage-specific macros, see man(7) .SH NAME multimon \- program to decode radio transmissions .SH SYNOPSIS .B multimon .RI [ options ]\ [input_file] .SH DESCRIPTION This manual page documents briefly the .B multimon command. This manual page was written for the Debian GNU/Linux distribution because the original program does not have a manual page. .PP .\" TeX users may be more comfortable with the \fB\fP and .\" \fI\fP escape sequences to invode bold face and italics, .\" respectively. The \fBmultimon\fP software can decode a variety of digital transmission modes commonly found on UHF radio. A standard PC soundcard is used to acquire the signal from a transceiver. The decoding is done completely in software. Currently, the following modes are supported: .PP .TP * AX.25 o 1200 Baud AFSK o 2400 Baud AFSK (2 variants) o 4800 Baud HAPN o 9600 Baud FSK (G3RUH) .TP * POCSAG o 512 Baud o 1200 Baud o 2400 Baud .TP * Miscellaneous o DTMF o ZVEI o SCOPE .PP An arbitrary set of the above modes may run concurrently on the same input signal (provided the CPU power is sufficient), so you do not have to know in advance which mode is used. Note however that some modes might require modifications to the radio (especially the 9600 baud FSK and the POCSAG modes) to work properly. .PP AX.25 - Amateur Packet Radio protocol datagram format .br POCSAG (Post Office Code Standards Advisory Group) is a common paging transmission format. .br DTMF - Dual Tone Multi Frequency. Commonly used in in-band telephone dialing. .br ZVEI- The German Electrical and Electronic Manufacturers' Association - paging tone format. .br SCOPE - show samples in a rudimentary oscilloscope display on an X server. .PP Multimon does not decode Morse code signals. .SH OPTIONS .TP .B \-t input file type (any other type than raw requires sox) .br allowed types: raw aiff au hcom sf voc cdr dat smp wav maud vwe .TP .B \-a add demodulator .TP .B \-s subtract demodulator .TP .B \-v verbosity level (0-10) .TP .B \-q quiet output messages .PP Where is one of: POCSAG512 POCSAG1200 POCSAG2400 EAS AFSK1200 AFSK2400 AFSK2400_2 HAPN4800 FSK9600 DTMF ZVEI SCOPE .br The \-a and \-s options may be given multiple times to specify the desired list of demodulators. .SH EXAMPLE Decode signal modulations from a sound file /tmp/message.wav without using a SCOPE display: .br multimon \-s SCOPE \-t wav /tmp/message.wav .PP With no input file specified, the program listens directly to the sound card using the /dev/dsp interface. So to decode (only) DTMF tones on the sound card input: .br multimon -a DTMF .SH NOTICE Please note that monitoring commercial services may be prohibited in some countries, this software should therefore only be used to monitor the amateur radio service. .SH SEE ALSO .BR gen(1) .BR http://www.qsl.net/kb9mwr/projects/pager/Two-Tone%20Pager%20Decoding%20Using%20Multimon.pdf .SH BUGS The DTMF and ZVEI decoders have more frequent spurious detection reports. .SH AUTHOR This manual page was written by A. Maitland Bottoms , for the Debian GNU/Linux system (but may be used by others). debian/install0000644000000000000000000000015711302157204010555 0ustar bin-*/gen usr/bin bin-*/multimon usr/bin debian/multimon.1 usr/share/man/man1 debian/gen.1 usr/share/man/man1