1.4 development snapshot C.

IBEACON for IGate statistics.  NMEA style waypoints.  Clean up compile warnings and header file use for Windows.
This commit is contained in:
WB2OSZ 2016-07-03 18:09:34 -04:00
parent 48aeb43829
commit 3e9118ba17
83 changed files with 1492 additions and 894 deletions

View File

@ -3,15 +3,27 @@
----------
## Version 1.4 -- Development snapshot B -- April 2016 ##
## Version 1.4 -- Development snapshot C -- June 2016 ##
This is a snapshot at some semi-stable point in the development of the next version. It is not well tested. New features might be incomplete, poorly documented, and subject to change.
### New Features: ###
- New beacon type, IBEACON, for sending IGate statistics.
- 2400 & 4800 bps PSK modems. See ***2400-4800-PSK-for-APRS-Packet-Radio.pdf*** in the doc directory for discussion.
- The top speed of 9600 bps has been increased to 38400. You will need a sound card capable of 96k or 192k samples per second for the higher rates. Radios must also have adequate bandwidth. See ***Going-beyond-9600-baud.pdf*** in the doc directory for more details.
- Better decoder performance for 9600 and higher especially for low audio sample rate to baud ratios.
- Generate waypoint sentences for use by AvMap G5 / G6 or other mapping devices or applications. Formats include
- $GPWPL - NMEA generic with only location and name.
- $PGRMW - Garmin, adds altitude, symbol, and comment to previously named waypoint.
- $PMGNWPL - Magellan, more complete for stationary objects.
- $PKWDWPL - Kenwood with APRS style symbol but missing comment.
### Bugs Fixed: ###
@ -31,9 +43,11 @@ received frames are not being printed. After a while this message will appear:
another application is not reading the frames from the other side.*
- The Windows version 1.3 would crash when starting to transmit on Windows XP. There have also been some other reports of erratic behavior on Windows. The crashing problem was fixed in in the 1.3.1 patch release. Linux version was not affected.
----------
## Version 1.3 -- Beta Test -- March 2016 ##
## Version 1.3 -- May 2016 ##
### New Features: ###

View File

@ -229,13 +229,13 @@ z := $(notdir ${CURDIR})
direwolf : direwolf.o config.o recv.o demod.o dsp.o demod_afsk.o demod_psk.o demod_9600.o hdlc_rec.o \
hdlc_rec2.o multi_modem.o redecode.o rdq.o rrbb.o dlq.o \
hdlc_rec2.o multi_modem.o rdq.o rrbb.o dlq.o \
fcs_calc.o ax25_pad.o \
decode_aprs.o symbols.o server.o kiss.o kissnet.o kiss_frame.o hdlc_send.o fcs_calc.o \
gen_tone.o audio.o audio_stats.o digipeater.o pfilter.o dedupe.o tq.o xmit.o morse.o \
ptt.o beacon.o encode_aprs.o latlong.o encode_aprs.o latlong.o textcolor.o \
dtmf.o aprs_tt.o tt_user.o tt_text.o igate.o waypoint.o serial_port.o log.o telemetry.o \
dwgps.o dwgpsnmea.o dwgpsd.o dtime_now.o \
dwgps.o dwgpsnmea.o dwgpsd.o dtime_now.o mheard.o \
misc.a geotranz.a
$(CC) -o $@ $^ $(LDFLAGS)
ifneq ($(enable_gpsd),)
@ -333,7 +333,7 @@ gen_packets : gen_packets.c ax25_pad.c hdlc_send.c fcs_calc.c gen_tone.c morse.c
atest : atest.c demod.o demod_afsk.o demod_psk.o demod_9600.o \
dsp.o hdlc_rec.o hdlc_rec2.o multi_modem.o rrbb.o \
fcs_calc.o ax25_pad.o decode_aprs.o dwgpsnmea.o \
dwgps.o dwgpsd.o serial_port.o telemetry.o latlong.o symbols.o tt_text.o textcolor.o \
dwgps.o dwgpsd.o serial_port.o telemetry.o dtime_now.o latlong.o symbols.o tt_text.o textcolor.o \
misc.a
$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
@ -606,14 +606,14 @@ check-modem300 : gen_packets atest
check-modem9600 : gen_packets atest
./gen_packets -B9600 -n 100 -o /tmp/test96.wav
./atest -B9600 -F0 -L57 -G61 /tmp/test96.wav
./atest -B9600 -F1 -L64 -G67 /tmp/test96.wav
./atest -B9600 -F0 -L50 -G54 /tmp/test96.wav
./atest -B9600 -F1 -L55 -G59 /tmp/test96.wav
rm /tmp/test96.wav
check-modem19200 : gen_packets atest
./gen_packets -r 96000 -B19200 -n 100 -o /tmp/test19.wav
./atest -B19200 -F0 -L62 -G64 /tmp/test19.wav
./atest -B19200 -F1 -L69 -G71 /tmp/test19.wav
./atest -B19200 -F0 -L55 -G59 /tmp/test19.wav
./atest -B19200 -F1 -L60 -G64 /tmp/test19.wav
rm /tmp/test19.wav
check-modem2400 : gen_packets atest
@ -743,11 +743,26 @@ tune.h :
testagc : atest.c demod.c dsp.c demod_afsk.c demod_psk.c demod_9600.c hdlc_rec.o hdlc_rec2.o multi_modem.o rrbb.o \
fcs_calc.o ax25_pad.o decode_aprs.o telemetry.o latlong.o symbols.o tune.h textcolor.o misc.a
fcs_calc.o ax25_pad.o decode_aprs.o telemetry.o dtime_now.o latlong.o symbols.o tune.h textcolor.o misc.a
$(CC) $(CFLAGS) -o atest $^ $(LDFLAGS)
./atest 02_Track_2.wav | grep "packets decoded in" > atest.out
testagc96 : atest.c fsk_fast_filter.h tune.h demod.c demod_afsk.c demod_psk.c demod_9600.c \
dsp.o hdlc_rec.o hdlc_rec2.o multi_modem.o \
rrbb.o fcs_calc.o ax25_pad.o decode_aprs.o \
dwgpsnmea.o dwgps.o dwgpsd.o serial_port.o latlong.o \
symbols.o tt_text.o textcolor.o telemetry.o dtime_now.o \
misc.a
rm -f atest96
$(CC) $(CFLAGS) -o atest96 $^ $(LDFLAGS)
./atest96 -B 9600 ../walkabout9600c.wav | grep "packets decoded in" >atest.out
#./atest96 -B 9600 noisy96.wav | grep "packets decoded in" >atest.out
#./atest96 -B 9600 19990303_0225_9600_8bis_22kHz.wav | grep "packets decoded in" >atest.out
#./atest96 -B 9600 19990303_0225_9600_16bit_22kHz.wav | grep "packets decoded in" >atest.out
#./atest96 -B 9600 -P + z8-22k.wav| grep "packets decoded in" >atest.out
#./atest96 -B 9600 test9600.wav | grep "packets decoded in" >atest.out
echo " " > tune.h

View File

@ -227,9 +227,9 @@ direwolf : direwolf.o aprs_tt.o audio_portaudio.o audio_stats.o ax25_pad.o beaco
encode_aprs.o encode_aprs.o fcs_calc.o fcs_calc.o gen_tone.o \
geotranz.a hdlc_rec.o hdlc_rec2.o hdlc_send.o igate.o kiss_frame.o \
kiss.o kissnet.o latlong.o latlong.o log.o morse.o multi_modem.o \
waypoint.o serial_port.o pfilter.o ptt.o rdq.o recv.o redecode.o rrbb.o server.o \
waypoint.o serial_port.o pfilter.o ptt.o rdq.o recv.o rrbb.o server.o \
symbols.o telemetry.o textcolor.o tq.o tt_text.o tt_user.o xmit.o \
dwgps.o dwgpsnmea.o
dwgps.o dwgpsnmea.o mheard.o
$(CC) $(CFLAGS) -o $@ $^ -lpthread $(LDLIBS) -lm
@ -453,7 +453,7 @@ tune.h :
testagc : atest.c demod.c dsp.c demod_afsk.c demod_9600.c hdlc_rec.c hdlc_rec2.o multi_modem.o rrbb.o \
fcs_calc.c ax25_pad.c decode_aprs.c telemetry.c latlong.c symbols.c tune.h textcolor.c
fcs_calc.c ax25_pad.c decode_aprs.c telemetry.c dtime_now.o latlong.c symbols.c tune.h textcolor.c
$(CC) $(CFLAGS) -o atest $^ -lm
./atest 02_Track_2.wav | grep "packets decoded in" > atest.out
@ -461,7 +461,7 @@ testagc : atest.c demod.c dsp.c demod_afsk.c demod_9600.c hdlc_rec.c hdlc_rec2.o
# Unit test for demodulators
atest : atest.c demod.c dsp.c demod_afsk.c demod_psk.c demod_9600.c hdlc_rec.c hdlc_rec2.o multi_modem.o rrbb.o \
fcs_calc.c ax25_pad.c decode_aprs.c dwgpsnmea.o dwgps.o serial_port.o telemetry.c latlong.c symbols.c textcolor.c tt_text.c
fcs_calc.c ax25_pad.c decode_aprs.c dwgpsnmea.o dwgps.o serial_port.o telemetry.c dtest_now.o latlong.c symbols.c textcolor.c tt_text.c
$(CC) $(CFLAGS) -o $@ $^ -lm
#atest : atest.c fsk_fast_filter.h demod.c dsp.c demod_afsk.c demod_psk.c demod_9600.c hdlc_rec.c hdlc_rec2.o multi_modem.o rrbb.o \
# fcs_calc.c ax25_pad.c decode_aprs.c dwgpsnmea.o dwgps.o serial_port.o telemetry.c latlong.c symbols.c textcolor.c tt_text.c

View File

@ -21,13 +21,24 @@ all : direwolf decode_aprs text2tt tt2text ll2utm utm2ll aclients log2gpx gen_pa
# People say we need -mthreads option for threads to work properly.
# They also say it creates a dependency on mingwm10.dll but I'm not seeing that.
# Maybe that is for pthreads. We are using the Windows threads.
# -Ofast was added in gcc 4.6 which was the MinGW version back in 2012.
CC := gcc
CFLAGS := -Wall -Ofast -march=pentium3 -msse -Iregex -Iutm -Igeotranz -mthreads -DUSE_REGEX_STATIC
#CFLAGS := -Wall -march=pentium3 -msse -Iregex -Iutm -Igeotranz -mthreads -DUSE_REGEX_STATIC
AR := ar
CFLAGS += -g
# For version 1.4, we upgrade from 4.6.2 to 4.9.3.
# gcc 4.8 adds these. Try them just for fun.
# No, it needs libasan which is not on Windows.
#CFLAGS += -fsanitize=address -fno-omit-frame-pointer
# TODO: Development in progress. Don't try using yet.
#CFLAGS += -DNEW14
@ -78,13 +89,13 @@ demod_psk.o : fsk_demod_state.h
# later ax25_link.o
direwolf : direwolf.o config.o recv.o demod.o dsp.o demod_afsk.o demod_psk.o demod_9600.o hdlc_rec.o \
hdlc_rec2.o multi_modem.o redecode.o rdq.o rrbb.o dlq.o \
hdlc_rec2.o multi_modem.o rdq.o rrbb.o dlq.o \
fcs_calc.o ax25_pad.o ax25_pad2.o \
decode_aprs.o symbols.o server.o kiss.o kissnet.o kiss_frame.o hdlc_send.o fcs_calc.o \
gen_tone.o morse.o audio_win.o audio_stats.o digipeater.o pfilter.o dedupe.o tq.o xmit.o \
ptt.o beacon.o dwgps.o encode_aprs.o latlong.o textcolor.o \
dtmf.o aprs_tt.o tt_user.o tt_text.o igate.o waypoint.o serial_port.o log.o telemetry.o \
dwgps.o dwgpsnmea.o dtime_now.o \
dwgps.o dwgpsnmea.o dtime_now.o mheard.o \
dw-icon.o regex.a misc.a geotranz.a
$(CC) $(CFLAGS) -o $@ $^ -lwinmm -lws2_32
@ -269,16 +280,16 @@ check-modem300 : gen_packets atest
check-modem9600 : gen_packets atest
gen_packets -B9600 -n 100 -o test96.wav
sleep 1
atest -B9600 -F0 -L57 -G62 test96.wav
atest -B9600 -F1 -L65 -G67 test96.wav
atest -B9600 -F0 -L50 -G54 test96.wav
atest -B9600 -F1 -L55 -G59 test96.wav
sleep 1
rm test96.wav
check-modem19200 : gen_packets atest
gen_packets -r 96000 -B19200 -n 100 -o test19.wav
sleep 1
atest -B19200 -F0 -L63 -G64 test19.wav
atest -B19200 -F1 -L69 -G70 test19.wav
atest -B19200 -F0 -L55 -G59 test19.wav
atest -B19200 -F1 -L60 -G64 test19.wav
sleep 1
rm test19.wav
@ -288,7 +299,7 @@ check-modem2400 : gen_packets atest
atest -B2400 -F0 -L70 -G78 test24.wav
atest -B2400 -F1 -L80 -G87 test24.wav
sleep 1
#rm test24.wav
rm test24.wav
check-modem4800 : gen_packets atest
gen_packets -B4800 -n 100 -o test48.wav
@ -296,7 +307,7 @@ check-modem4800 : gen_packets atest
atest -B4800 -F0 -L70 -G74 test48.wav
atest -B4800 -F1 -L79 -G84 test48.wav
sleep 1
#rm test48.wav
rm test48.wav
# Unit test for demodulators
@ -305,7 +316,7 @@ atest : atest.c fsk_fast_filter.h demod.c demod_afsk.c demod_psk.c demod_9600.c
dsp.o hdlc_rec.o hdlc_rec2.o multi_modem.o \
rrbb.o fcs_calc.o ax25_pad.o decode_aprs.o \
dwgpsnmea.o dwgps.o serial_port.o latlong.c \
symbols.c tt_text.c textcolor.c telemetry.c \
symbols.c tt_text.c textcolor.c telemetry.c dtime_now.o \
misc.a regex.a
echo " " > tune.h
$(CC) $(CFLAGS) -o $@ $^
@ -314,7 +325,7 @@ atest : atest.c fsk_fast_filter.h demod.c demod_afsk.c demod_psk.c demod_9600.c
#atest za100.wav
atest9 : atest.c demod.c dsp.c demod_afsk.c demod_psk.c demod_9600.c hdlc_rec.c hdlc_rec2.c multi_modem.c \
rrbb.c fcs_calc.c ax25_pad.c decode_aprs.c latlong.c symbols.c textcolor.c telemetry.c misc.a regex.a \
rrbb.c fcs_calc.c ax25_pad.c decode_aprs.c latlong.c symbols.c textcolor.c telemetry.c dtime_now.o misc.a regex.a \
fsk_fast_filter.h
echo " " > tune.h
$(CC) $(CFLAGS) -o $@ $^
@ -415,7 +426,7 @@ demod_psk.o : tune.h
testagc : atest.c demod.c dsp.c demod_afsk.c demod_psk.c demod_9600.o fsk_demod_agc.h \
hdlc_rec.o hdlc_rec2.o multi_modem.o \
rrbb.o fcs_calc.o ax25_pad.o decode_aprs.o latlong.o symbols.o textcolor.o telemetry.o \
dwgpsnmea.o dwgps.o serial_port.o tt_text.o regex.a misc.a
dwgpsnmea.o dwgps.o serial_port.o tt_text.o dtime_now.o regex.a misc.a
rm -f atest.exe
$(CC) $(CFLAGS) -o atest $^
./atest -P GGG- -F 0 ../02_Track_2.wav | grep "packets decoded in" >atest.out
@ -426,7 +437,7 @@ noisy3.wav : gen_packets
./gen_packets -B 300 -n 100 -o noisy3.wav
testagc3 : atest.c demod.c dsp.c demod_afsk.c demod_psk.c demod_9600.c hdlc_rec.c hdlc_rec2.c multi_modem.c \
rrbb.c fcs_calc.c ax25_pad.c decode_aprs.c latlong.c symbols.c textcolor.c telemetry.c regex.a misc.a \
rrbb.c fcs_calc.c ax25_pad.c decode_aprs.c latlong.c symbols.c textcolor.c telemetry.c dtime_now.o regex.a misc.a \
tune.h
rm -f atest3.exe
$(CC) $(CFLAGS) -o atest3 $^
@ -437,20 +448,27 @@ testagc3 : atest.c demod.c dsp.c demod_afsk.c demod_psk.c demod_9600.c hdlc_rec.
noisy96.wav : gen_packets
./gen_packets -B 9600 -n 100 -o noisy96.wav
testagc96 : atest.c demod.c dsp.c demod_afsk.c demod_psk.c demod_9600.c hdlc_rec.c hdlc_rec2.c multi_modem.c \
rrbb.c fcs_calc.c ax25_pad.c decode_aprs.c latlong.c symbols.c textcolor.c telemetry.c regex.a misc.a \
tune.h
rm -f atest9.exe
$(CC) $(CFLAGS) -o atest9 $^
./atest9 -B 9600 ../walkabout9600.wav | grep "packets decoded in" >atest.out
#./atest9 -B 9600 noisy96.wav | grep "packets decoded in" >atest.out
testagc96 : atest.c fsk_fast_filter.h tune.h demod.c demod_afsk.c demod_psk.c demod_9600.c \
dsp.o hdlc_rec.o hdlc_rec2.o multi_modem.o \
rrbb.o fcs_calc.o ax25_pad.o decode_aprs.o \
dwgpsnmea.o dwgps.o serial_port.o latlong.o \
symbols.o tt_text.o textcolor.o telemetry.o dtime_now.o \
misc.a regex.a
rm -f atest96.exe
$(CC) $(CFLAGS) -o atest96 $^
./atest96 -B 9600 ../walkabout9600c.wav | grep "packets decoded in" >atest.out
#./atest96 -B 9600 noisy96.wav | grep "packets decoded in" >atest.out
#./atest96 -B 9600 19990303_0225_9600_8bis_22kHz.wav | grep "packets decoded in" >atest.out
#./atest96 -B 9600 19990303_0225_9600_16bit_22kHz.wav | grep "packets decoded in" >atest.out
#./atest96 -B 9600 -P + z8-22k.wav| grep "packets decoded in" >atest.out
#./atest96 -B 9600 test9600.wav | grep "packets decoded in" >atest.out
echo " " > tune.h
testagc24 : atest.c fsk_fast_filter.h tune.h demod.c demod_afsk.c demod_psk.c demod_9600.c \
dsp.o hdlc_rec.o hdlc_rec2.o multi_modem.o \
rrbb.o fcs_calc.o ax25_pad.o decode_aprs.o \
dwgpsnmea.o dwgps.o serial_port.o latlong.o \
symbols.o tt_text.o textcolor.o telemetry.o \
symbols.o tt_text.o textcolor.o telemetry.o dtime_now.o \
misc.a regex.a
rm -f atest24.exe
sleep 1
@ -462,7 +480,7 @@ testagc48 : atest.c fsk_fast_filter.h tune.h demod.c demod_afsk.c demod_psk.c de
dsp.o hdlc_rec.o hdlc_rec2.o multi_modem.o \
rrbb.o fcs_calc.o ax25_pad.o decode_aprs.o \
dwgpsnmea.o dwgps.o serial_port.o latlong.o \
symbols.o tt_text.o textcolor.o telemetry.o \
symbols.o tt_text.o textcolor.o telemetry.o dtime_now.o \
misc.a regex.a
rm -f atest48.exe
sleep 1
@ -570,67 +588,6 @@ dist-win : direwolf.exe decode_aprs.exe text2tt.exe tt2text.exe ll2utm.exe utm2l
dwespeak.bat \
telemetry-toolkit/*
.PHONY: dist-src
dist-src : README.md CHANGES.md \
doc/User-Guide.pdf \
doc/Raspberry-Pi-APRS.pdf \
doc/Raspberry-Pi-APRS-Tracker.pdf \
doc/APRStt-Implementation-Notes.pdf \
doc/APRS-Telemetry-Toolkit.pdf \
dw-start.sh dwespeak.bat dwespeak.sh \
tocalls.txt symbols-new.txt symbolsX.txt direwolf.spec
rm -f fsk_fast_filter.h
echo " " > tune.h
rm -f ../$z-src.zip
dos2unix generic.conf
dos2unix Makefile
dos2unix Makefile.linux
dos2unix Makefile.macosx
dos2unix telemetry-toolkit/telem-balloon.conf
dos2unix telemetry-toolkit/telem-balloon.pl
dos2unix telemetry-toolkit/telem-bits.pl
dos2unix telemetry-toolkit/telem-data.pl
dos2unix telemetry-toolkit/telem-data91.pl
dos2unix telemetry-toolkit/telem-eqns.pl
dos2unix telemetry-toolkit/telem-m0xer-3.txt
dos2unix telemetry-toolkit/telem-parm.pl
dos2unix telemetry-toolkit/telem-unit.pl
dos2unix telemetry-toolkit/telem-volts.py
dos2unix telemetry-toolkit/telem-volts.conf
(cd .. ; zip $z-src.zip \
$z/README.md \
$z/CHANGES.md \
$z/LICENSE* \
$z/doc/User-Guide.pdf \
$z/doc/Raspberry-Pi-APRS.pdf \
$z/doc/Raspberry-Pi-APRS-Tracker.pdf \
$z/doc/APRStt-Implementation-Notes.pdf \
$z/doc/APRS-Telemetry-Toolkit.pdf \
$z/Makefile.win $z/Makefile.linux $z/Makefile.macosx $z/Makefile \
$z/*.c $z/*.h \
$z/regex/* $z/misc/* $z/geotranz/* \
$z/man1/* \
$z/generic.conf \
$z/tocalls.txt $z/symbols-new.txt $z/symbolsX.txt \
$z/dw-icon.png $z/dw-icon.rc $z/dw-icon.ico \
$z/dw-start.sh $z/direwolf.spec \
$z/dwespeak.bat $z/dwespeak.sh \
$z/telemetry-toolkit/* )
unix2dos Makefile
unix2dos Makefile.linux
unix2dos Makefile.macosx
unix2dos telemetry-toolkit/telem-balloon.conf
unix2dos telemetry-toolkit/telem-balloon.pl
dos2unix telemetry-toolkit/telem-bits.pl
unix2dos telemetry-toolkit/telem-data.pl
unix2dos telemetry-toolkit/telem-data91.pl
unix2dos telemetry-toolkit/telem-eqns.pl
unix2dos telemetry-toolkit/telem-m0xer-3.txt
unix2dos telemetry-toolkit/telem-parm.pl
unix2dos telemetry-toolkit/telem-unit.pl
unix2dos telemetry-toolkit/telem-volts.py
unix2dos telemetry-toolkit/telem-volts.conf
# Reminders if pdf files are not up to date.

View File

@ -15,7 +15,7 @@ Decodes more than 1000 error-free frames from [WA8LMF TNC Test CD](http://wa8lmf
- Ideal for building a Raspberry Pi digipeater & IGate.
- 300, 1200, and 9600 baud operation.
- Data rates: 300 AFSK, 1200 AFSK, 2400 QPSK, 4800 8PSK, and 9600/19200/38400 K9NG/G3RUH.
- Interface with applications by
- [AGW](http://uz7.ho.ua/includes/agwpeapi.htm) network protocol
@ -24,6 +24,8 @@ Decodes more than 1000 error-free frames from [WA8LMF TNC Test CD](http://wa8lmf
- Decoding of received information for troubleshooting.
- Conversion from APRS to waypoint sentences in popular formats: $GPWPL, $PGRMW, $PMGNWPL, $PKWDWPL.
- Logging and conversion to GPX file format.
- Beaconing for yourself or other nearby entities.

View File

@ -51,14 +51,13 @@
* Linux: Use the BSD socket interface.
*/
#include "direwolf.h" // Sets _WIN32_WINNT for XP API level needed by ws2tcpip.h
#if __WIN32__
#include <winsock2.h>
// default is 0x0400
#undef _WIN32_WINNT
#define _WIN32_WINNT 0x0501 /* Minimum OS version is XP. */
#include <ws2tcpip.h>
#include <ws2tcpip.h> // _WIN32_WINNT must be set to 0x0501 before including this
#else
//#define __USE_XOPEN2KXSI 1
//#define __USE_XOPEN 1
@ -83,7 +82,6 @@
#include <time.h>
#include "direwolf.h"
#include "ax25_pad.h"
#include "textcolor.h"
#include "version.h"

View File

@ -39,6 +39,8 @@
#define APRS_TT_C 1
#include "direwolf.h"
// TODO: clean up terminolgy.
// "Message" has a specific meaning in APRS and this is not it.
@ -56,7 +58,6 @@
#include <ctype.h>
#include <assert.h>
#include "direwolf.h"
#include "version.h"
#include "ax25_pad.h"
#include "hdlc_rec2.h" /* for process_rec_frame */
@ -105,7 +106,9 @@ static int parse_aprstt3_call (char *e);
static int parse_location (char *e);
static int parse_comment (char *e);
static int expand_macro (char *e);
#ifndef TT_MAIN
static void raw_tt_data_to_app (int chan, char *msg);
#endif
static int find_ttloc_match (char *e, char *xstr, char *ystr, char *zstr, char *bstr, char *dstr, size_t valstrsize);
#if TT_MAIN
@ -378,6 +381,7 @@ void aprs_tt_sequence (int chan, char *msg)
#endif
#if TT_MAIN
(void)err; // suppress variable set but not used warning.
check_result (); // for unit testing.
#else
@ -1658,6 +1662,7 @@ static int parse_comment (char *e)
*
*----------------------------------------------------------------*/
#ifndef TT_MAIN
static void raw_tt_data_to_app (int chan, char *msg)
{
@ -1668,9 +1673,6 @@ static void raw_tt_data_to_app (int chan, char *msg)
char src[10], dest[10];
char raw_tt_msg[256];
packet_t pp;
char *c, *s;
int i;
int err;
alevel_t alevel;
@ -1716,6 +1718,7 @@ static void raw_tt_data_to_app (int chan, char *msg)
#endif
}
#endif
/*------------------------------------------------------------------

30
atest.c
View File

@ -59,6 +59,7 @@
// #define X 1
#include "direwolf.h"
#include <stdio.h>
#include <unistd.h>
@ -79,6 +80,7 @@
#include "hdlc_rec2.h"
#include "dlq.h"
#include "ptt.h"
#include "dtime_now.h"
@ -178,7 +180,10 @@ int main (int argc, char *argv[])
int err;
int c;
int channel;
time_t start_time;
double start_time; // Time when we started so we can measure elapsed time.
double duration; // Length of the audio file in seconds.
double elapsed; // Time it took us to process it.
#if defined(EXPERIMENT_G) || defined(EXPERIMENT_H)
@ -430,8 +435,7 @@ int main (int argc, char *argv[])
exit (EXIT_FAILURE);
}
start_time = time(NULL);
start_time = dtime_now();
/*
* Read the file header.
@ -501,13 +505,17 @@ int main (int argc, char *argv[])
if (format.nchannels == 2) my_audio_config.achan[1].valid = 1;
text_color_set(DW_COLOR_INFO);
dw_printf ("%d samples per second\n", my_audio_config.adev[0].samples_per_sec);
dw_printf ("%d bits per sample\n", my_audio_config.adev[0].bits_per_sample);
dw_printf ("%d audio channels\n", my_audio_config.adev[0].num_channels);
dw_printf ("%d audio bytes in file\n", (int)(wav_data.datasize));
dw_printf ("%d samples per second. %d bits per sample. %d audio channels.\n",
my_audio_config.adev[0].samples_per_sec,
my_audio_config.adev[0].bits_per_sample,
my_audio_config.adev[0].num_channels);
duration = (double) wav_data.datasize /
((my_audio_config.adev[0].bits_per_sample / 8) * my_audio_config.adev[0].num_channels * my_audio_config.adev[0].samples_per_sec);
dw_printf ("%d audio bytes in file. Duration = %.1f seconds.\n",
(int)(wav_data.datasize),
duration);
dw_printf ("Fix Bits level = %d\n", my_audio_config.achan[0].fix_bits);
/*
* Initialize the AFSK demodulator and HDLC decoder.
*/
@ -563,7 +571,11 @@ int main (int argc, char *argv[])
dw_printf ("%d\n", count[j]);
}
#endif
dw_printf ("%d packets decoded in %d seconds.\n", packets_decoded, (int)(time(NULL) - start_time));
elapsed = dtime_now() - start_time;
dw_printf ("%d packets decoded in %.3f seconds. %.1f x realtime\n", packets_decoded, elapsed, duration/elapsed);
if (error_if_less_than != -1 && packets_decoded < error_if_less_than) {
text_color_set(DW_COLOR_ERROR);

View File

@ -60,6 +60,7 @@
*
*---------------------------------------------------------------*/
#include "direwolf.h"
#include <stdio.h>
#include <unistd.h>
@ -88,7 +89,6 @@
#endif
#include "direwolf.h"
#include "audio.h"
#include "audio_stats.h"
#include "textcolor.h"

View File

@ -37,6 +37,8 @@
#if defined(USE_PORTAUDIO)
#include "direwolf.h"
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
@ -54,7 +56,6 @@
#include <errno.h>
#include <pthread.h>
#include "direwolf.h"
#include "audio.h"
#include "audio_stats.h"
#include "textcolor.h"

View File

@ -50,6 +50,9 @@
*---------------------------------------------------------------*/
#include "direwolf.h"
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
@ -57,8 +60,9 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <assert.h>
#include <time.h>
#include "direwolf.h"
#include "audio_stats.h"
#include "textcolor.h"
#include "dtime_now.h"

View File

@ -39,6 +39,10 @@
*---------------------------------------------------------------*/
#include "direwolf.h" // Sets _WIN32_WINNT for XP API level needed by ws2tcpip.h
// Also includes windows.h.
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
@ -48,7 +52,6 @@
#include <io.h>
#include <fcntl.h>
#include <windows.h>
#include <mmsystem.h>
#ifndef WAVE_FORMAT_96M16
@ -57,11 +60,9 @@
#endif
#include <winsock2.h>
#define _WIN32_WINNT 0x0501
#include <ws2tcpip.h>
#include <ws2tcpip.h> // _WIN32_WINNT must be set to 0x0501 before including this
#include "direwolf.h"
#include "audio.h"
#include "audio_stats.h"
#include "textcolor.h"

View File

@ -146,6 +146,7 @@
#define AX25_PAD_C /* this will affect behavior of ax25_pad.h */
#include "direwolf.h"
#include <stdlib.h>
#include <string.h>
@ -163,7 +164,7 @@
char *strtok_r(char *str, const char *delim, char **saveptr);
#endif
#include "direwolf.h"
#include "ax25_pad.h"
#include "textcolor.h"
#include "fcs_calc.h"

View File

@ -228,7 +228,7 @@ static inline int ax25_get_info_offset (packet_t this_p)
return (ax25_get_control_offset (this_p) + ax25_get_num_control(this_p) + ax25_get_num_pid(this_p));
}
static int ax25_get_num_info (packet_t this_p)
static inline int ax25_get_num_info (packet_t this_p)
{
int len;

View File

@ -136,6 +136,8 @@
#define AX25_PAD_C /* this will affect behavior of ax25_pad.h */
#include "direwolf.h"
#include <stdlib.h>
#include <string.h>
#include <assert.h>
@ -143,9 +145,7 @@
#include <ctype.h>
#include "direwolf.h"
#include "textcolor.h"
#include "ax25_pad.h"
#include "ax25_pad2.h"

View File

@ -1,7 +1,7 @@
//
// This file is part of Dire Wolf, an amateur radio packet TNC.
//
// Copyright (C) 2011, 2013, 2014, 2015 John Langner, WB2OSZ
// Copyright (C) 2011, 2013, 2014, 2015, 2016 John Langner, WB2OSZ
//
// 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
@ -30,6 +30,8 @@
//#define DEBUG 1
#include "direwolf.h"
#include <stdio.h>
#include <unistd.h>
@ -40,7 +42,6 @@
#include <time.h>
#include "direwolf.h"
#include "ax25_pad.h"
#include "textcolor.h"
#include "audio.h"
@ -55,6 +56,7 @@
#include "log.h"
#include "dlq.h"
#include "aprs_tt.h" // for dw_run_cmd - should relocate someday.
#include "mheard.h"
#if __WIN32__
@ -83,6 +85,7 @@ struct tm *localtime_r(time_t *clock, struct tm *res)
static struct audio_s *g_modem_config_p;
static struct misc_config_s *g_misc_config_p;
static struct igate_config_s *g_igate_config_p;
#if __WIN32__
@ -118,6 +121,10 @@ static void beacon_send (int j, dwgps_info_t *gpsinfo);
* Used only to find valid channels.
*
* pconfig - misc. configuration from config file.
* Beacon stuff ended up here.
*
* pigate - IGate configuration.
* Need this for calculating IGate statistics.
*
*
* Outputs: Remember required information for future use.
@ -131,7 +138,7 @@ static void beacon_send (int j, dwgps_info_t *gpsinfo);
void beacon_init (struct audio_s *pmodem, struct misc_config_s *pconfig)
void beacon_init (struct audio_s *pmodem, struct misc_config_s *pconfig, struct igate_config_s *pigate)
{
time_t now;
int j;
@ -156,6 +163,7 @@ void beacon_init (struct audio_s *pmodem, struct misc_config_s *pconfig)
*/
g_modem_config_p = pmodem;
g_misc_config_p = pconfig;
g_igate_config_p = pigate;
/*
* Precompute the packet contents so any errors are
@ -228,6 +236,22 @@ void beacon_init (struct audio_s *pmodem, struct misc_config_s *pconfig)
}
break;
case BEACON_IGATE:
/* Doesn't make sense if IGate is not configured. */
if (strlen(g_igate_config_p->t2_server_name) == 0 ||
strlen(g_igate_config_p->t2_login) == 0 ||
strlen(g_igate_config_p->t2_passcode) == 0) {
text_color_set(DW_COLOR_ERROR);
dw_printf ("Config file, line %d: Doesn't make sense to use IBEACON without IGate Configured.\n", g_misc_config_p->beacon[j].lineno);
dw_printf ("IBEACON has been disabled.\n");
g_misc_config_p->beacon[j].btype = BEACON_IGNORE;
continue;
}
break;
case BEACON_IGNORE:
break;
}
@ -870,6 +894,25 @@ static void beacon_send (int j, dwgps_info_t *gpsinfo)
}
break;
case BEACON_IGATE:
{
int last_minutes = 30;
char stuff[256];
snprintf (stuff, sizeof(stuff), "<IGATE,MSG_CNT=%d,PKT_CNT=%d,DIR_CNT=%d,LOC_CNT=%d,RF_CNT=%d,UPL_CNT=%d,DNL_CNT=%d",
igate_get_msg_cnt(),
igate_get_pkt_cnt(),
mheard_count(0,last_minutes),
mheard_count(g_igate_config_p->max_digi_hops,last_minutes),
mheard_count(8,last_minutes),
igate_get_upl_cnt(),
igate_get_dnl_cnt());
strlcat (beacon_text, stuff, sizeof(beacon_text));
}
break;
case BEACON_IGNORE:
default:
break;

View File

@ -1,6 +1,6 @@
/* beacon.h */
void beacon_init (struct audio_s *pmodem, struct misc_config_s *pconfig);
void beacon_init (struct audio_s *pmodem, struct misc_config_s *pconfig, struct igate_config_s *pigate);
void beacon_tracker_set_debug (int level);

158
config.c
View File

@ -17,7 +17,7 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
#define CONFIG_C 1
#define CONFIG_C 1 // influences behavior of aprs_tt.h
// #define DEBUG 1
@ -34,6 +34,8 @@
*
*---------------------------------------------------------------*/
#include "direwolf.h"
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
@ -451,6 +453,110 @@ static int parse_interval (char *str, int line)
/*------------------------------------------------------------------
*
* Name: check_via_path
*
* Purpose: Check for valid path in beacons, IGate, and APRStt configuration.
*
* Inputs: via_path - Zero or more comma separated stations.
*
* Returns: Maximum number of digipeater hops or -1 for error.
*
* Description: Beacons and IGate can use via paths such as:
*
* WIDE1-1,MA3-3
* N2GH,RARA-7
*
* Each part could be a specific station, an alias, or a path
* from the "New n-N Paradigm."
* In the first example above, the maximum number of digipeater
* hops would be 4. In the second example, 2.
*
*----------------------------------------------------------------*/
// Put something like this in the config file as a quick test.
// Not worth adding to "make check" regression tests.
//
// IBEACON via=
// IBEACON via=W2UB
// IBEACON via=W2UB-7
// IBEACON via=WIDE1-1,WIDE2-2,WIDE3-3
// IBEACON via=Lower
// IBEACON via=T00LONG
// IBEACON via=W2UB-16
// IBEACON via=D1,D2,D3,D4,D5,D6,D7,D8
// IBEACON via=D1,D2,D3,D4,D5,D6,D7,D8,D9
//
// Define below and visually check results.
//#define DEBUG8 1
static int check_via_path (char *via_path)
{
char stemp[AX25_MAX_REPEATERS * (AX25_MAX_ADDR_LEN + 1)];
int num_digi = 0;
int max_digi_hops = 0;
char *r;
char *a;
#if DEBUG8
text_color_set(DW_COLOR_DEBUG);
dw_printf ("check_via_path %s\n", via_path);
#endif
if (strlen(via_path) == 0) {
return (0);
}
strlcpy (stemp, via_path, sizeof(stemp));
r = stemp;
while (( a = strsep(&r,",")) != NULL) {
int strict = 1;
int ok;
char addr[AX25_MAX_ADDR_LEN];
int ssid;
int heard;
num_digi++;
ok = ax25_parse_addr (AX25_REPEATER_1 - 1 + num_digi, a, strict, addr, &ssid, &heard);
if ( ! ok) {
#if DEBUG8
text_color_set(DW_COLOR_DEBUG);
dw_printf ("check_via_path bad address\n");
#endif
return (-1);
}
/* Based on assumption that a callsign can't end with a digit. */
/* For something of the form xxx9-9, we take the ssid as max hop count. */
if (ssid > 0 && strlen(addr) >= 2 && isdigit(addr[strlen(addr)-1])) {
max_digi_hops += ssid;
}
else {
max_digi_hops++;
}
}
if (num_digi > AX25_MAX_REPEATERS) {
text_color_set(DW_COLOR_ERROR);
dw_printf ("Maximum of 8 digipeaters has been exceeded.\n");
return (-1);
}
#if DEBUG8
text_color_set(DW_COLOR_DEBUG);
dw_printf ("check_via_path %d addresses, %d max digi hops\n", num_digi, max_digi_hops);
#endif
return (max_digi_hops);
} /* end check_via_path */
/*-------------------------------------------------------------------
*
* Name: split
@ -3348,8 +3454,13 @@ void config_init (char *fname, struct audio_s *p_audio_config,
t = split(NULL,0);
if (t != NULL) {
// TODO: Should do some validity checking on the path.
strlcpy (p_tt_config->obj_xmit_via, t, sizeof(p_tt_config->obj_xmit_via));
if (check_via_path(t) >= 0) {
strlcpy (p_tt_config->obj_xmit_via, t, sizeof(p_tt_config->obj_xmit_via));
}
else {
text_color_set(DW_COLOR_ERROR);
dw_printf ("Config file, line %d: invalid via path.\n", line);
}
}
}
@ -3600,6 +3711,22 @@ void config_init (char *fname, struct audio_s *p_audio_config,
t = split(NULL,0);
if (t != NULL) {
#if 1 // proper checking
n = check_via_path(t);
if (n >= 0) {
p_igate_config->max_digi_hops = n;
p_igate_config->tx_via[0] = ',';
strlcpy (p_igate_config->tx_via + 1, t, sizeof(p_igate_config->tx_via)-1);
}
else {
text_color_set(DW_COLOR_ERROR);
dw_printf ("Config file, line %d: invalid via path.\n", line);
}
#else // previously
char *p;
p_igate_config->tx_via[0] = ',';
strlcpy (p_igate_config->tx_via + 1, t, sizeof(p_igate_config->tx_via)-1);
@ -3608,6 +3735,7 @@ void config_init (char *fname, struct audio_s *p_audio_config,
*p = toupper(*p); /* silently force upper case. */
}
}
#endif
}
}
@ -3841,7 +3969,7 @@ void config_init (char *fname, struct audio_s *p_audio_config,
}
/*
* WAYPOINT - Generate WPT NMEA sentences for display on map.
* WAYPOINT - Generate WPL NMEA sentences for display on map.
*
* WAYPOINT serial-device [ formats ]
*
@ -3924,6 +4052,7 @@ void config_init (char *fname, struct audio_s *p_audio_config,
* OBEACON keyword=value ...
* TBEACON keyword=value ...
* CBEACON keyword=value ...
* IBEACON keyword=value ...
*
* New style with keywords for options.
*/
@ -3931,7 +4060,8 @@ void config_init (char *fname, struct audio_s *p_audio_config,
else if (strcasecmp(t, "PBEACON") == 0 ||
strcasecmp(t, "OBEACON") == 0 ||
strcasecmp(t, "TBEACON") == 0 ||
strcasecmp(t, "CBEACON") == 0) {
strcasecmp(t, "CBEACON") == 0 ||
strcasecmp(t, "IBEACON") == 0) {
if (p_misc_config->num_beacons < MAX_BEACONS) {
@ -3945,6 +4075,9 @@ void config_init (char *fname, struct audio_s *p_audio_config,
else if (strcasecmp(t, "TBEACON") == 0) {
p_misc_config->beacon[p_misc_config->num_beacons].btype = BEACON_TRACKER;
}
else if (strcasecmp(t, "IBEACON") == 0) {
p_misc_config->beacon[p_misc_config->num_beacons].btype = BEACON_IGATE;
}
else {
p_misc_config->beacon[p_misc_config->num_beacons].btype = BEACON_CUSTOM;
}
@ -4218,12 +4351,27 @@ static int beacon_options(char *cmd, struct beacon_s *b, int line, struct audio_
}
}
else if (strcasecmp(keyword, "VIA") == 0) {
#if 1 // proper checking
if (check_via_path(value) >= 0) {
b->via = strdup(value);
}
else {
text_color_set(DW_COLOR_ERROR);
dw_printf ("Config file, line %d: invalid via path.\n", line);
}
#else // previously
b->via = strdup(value);
for (p = b->via; *p != '\0'; p++) {
if (islower(*p)) {
*p = toupper(*p); /* silently force upper case. */
}
}
#endif
}
else if (strcasecmp(keyword, "INFO") == 0) {
b->custom_info = strdup(value);

View File

@ -23,7 +23,7 @@
* This wasn't thought out. It just happened.
*/
enum beacon_type_e { BEACON_IGNORE, BEACON_POSITION, BEACON_OBJECT, BEACON_TRACKER, BEACON_CUSTOM };
enum beacon_type_e { BEACON_IGNORE, BEACON_POSITION, BEACON_OBJECT, BEACON_TRACKER, BEACON_CUSTOM, BEACON_IGATE };
enum sendto_type_e { SENDTO_XMIT, SENDTO_IGATE, SENDTO_RECV };

View File

@ -33,6 +33,8 @@
*
*------------------------------------------------------------------*/
#include "direwolf.h"
#include <stdio.h>
#include <time.h>
#include <assert.h>
@ -48,7 +50,6 @@
#endif
#include "regex.h"
#include "direwolf.h"
#include "ax25_pad.h"
#include "textcolor.h"
#include "symbols.h"

View File

@ -96,6 +96,7 @@
#define DEDUPE_C
#include "direwolf.h"
#include <stdlib.h>
#include <string.h>

100
demod.c
View File

@ -31,6 +31,7 @@
*
*---------------------------------------------------------------*/
#include "direwolf.h"
#include <stdlib.h>
#include <stdio.h>
@ -41,7 +42,6 @@
#include <assert.h>
#include <ctype.h>
#include "direwolf.h"
#include "audio.h"
#include "demod.h"
#include "tune.h"
@ -61,13 +61,16 @@
static struct audio_s *save_audio_config_p;
// TODO: temp experiment.
static int upsample = 2; // temp experiment.
static int zerostuff = 1; // temp experiment.
// Current state of all the decoders.
static struct demodulator_state_s demodulator_state[MAX_CHANS][MAX_SUBCHANS];
#define UPSAMPLE 2
static int sample_sum[MAX_CHANS][MAX_SUBCHANS];
static int sample_count[MAX_CHANS][MAX_SUBCHANS];
@ -641,11 +644,20 @@ int demod_init (struct audio_s *pa)
#endif
}
#ifdef TUNE_UPSAMPLE
upsample = TUNE_UPSAMPLE;
#endif
#ifdef TUNE_ZEROSTUFF
zerostuff = TUNE_ZEROSTUFF;
#endif
text_color_set(DW_COLOR_DEBUG);
dw_printf ("Channel %d: %d baud, K9NG/G3RUH, %s, %d sample rate x %d",
chan, save_audio_config_p->achan[chan].baud,
save_audio_config_p->achan[chan].profiles,
save_audio_config_p->adev[ACHAN2ADEV(chan)].samples_per_sec, UPSAMPLE);
save_audio_config_p->adev[ACHAN2ADEV(chan)].samples_per_sec, upsample);
if (save_audio_config_p->achan[chan].dtmf_decode != DTMF_DECODE_OFF)
dw_printf (", DTMF decoder enabled");
dw_printf (".\n");
@ -693,7 +705,7 @@ int demod_init (struct audio_s *pa)
dw_printf ("This is a suitable ratio for good performance.\n");
}
demod_9600_init (UPSAMPLE * save_audio_config_p->adev[ACHAN2ADEV(chan)].samples_per_sec, save_audio_config_p->achan[chan].baud, D);
demod_9600_init (upsample * save_audio_config_p->adev[ACHAN2ADEV(chan)].samples_per_sec, save_audio_config_p->achan[chan].baud, D);
if (strchr(save_audio_config_p->achan[chan].profiles, '+') != NULL) {
@ -920,50 +932,50 @@ void demod_process_sample (int chan, int subchan, int sam)
case MODEM_SCRAMBLE:
default:
#define ZEROSTUFF 1
if (zerostuff) {
/* Literature says this is better if followed */
/* by appropriate low pass filter. */
/* So far, both are same in tests with different */
/* optimal low pass filter parameters. */
#if ZEROSTUFF
/* Literature says this is better if followed */
/* by appropriate low pass filter. */
/* So far, both are same in tests with different */
/* optimal low pass filter parameters. */
for (k=1; k<UPSAMPLE; k++) {
demod_9600_process_sample (chan, 0, D);
for (k=1; k<upsample; k++) {
demod_9600_process_sample (chan, 0, D);
}
demod_9600_process_sample (chan, sam * upsample, D);
}
demod_9600_process_sample (chan, sam*UPSAMPLE, D);
#else
/* Linear interpolation. */
static int prev_sam;
switch (UPSAMPLE) {
case 1:
demod_9600_process_sample (chan, sam);
else {
break;
case 2:
demod_9600_process_sample (chan, (prev_sam + sam) / 2, D);
demod_9600_process_sample (chan, sam, D);
break;
case 3:
demod_9600_process_sample (chan, (2 * prev_sam + sam) / 3, D);
demod_9600_process_sample (chan, (prev_sam + 2 * sam) / 3, D);
demod_9600_process_sample (chan, sam, D);
break;
case 4:
demod_9600_process_sample (chan, (3 * prev_sam + sam) / 4, D);
demod_9600_process_sample (chan, (prev_sam + sam) / 2, D);
demod_9600_process_sample (chan, (prev_sam + 3 * sam) / 4, D);
demod_9600_process_sample (chan, sam, D);
break;
default:
assert (0);
break;
/* Linear interpolation. */
static int prev_sam;
switch (upsample) {
case 1:
demod_9600_process_sample (chan, sam, D);
break;
case 2:
demod_9600_process_sample (chan, (prev_sam + sam) / 2, D);
demod_9600_process_sample (chan, sam, D);
break;
case 3:
demod_9600_process_sample (chan, (2 * prev_sam + sam) / 3, D);
demod_9600_process_sample (chan, (prev_sam + 2 * sam) / 3, D);
demod_9600_process_sample (chan, sam, D);
break;
case 4:
demod_9600_process_sample (chan, (3 * prev_sam + sam) / 4, D);
demod_9600_process_sample (chan, (prev_sam + sam) / 2, D);
demod_9600_process_sample (chan, (prev_sam + 3 * sam) / 4, D);
demod_9600_process_sample (chan, sam, D);
break;
default:
assert (0);
break;
}
prev_sam = sam;
}
prev_sam = sam;
#endif
break;
}
} /* switch modem_type */
return;
} /* end demod_process_sample */

View File

@ -18,7 +18,7 @@
//
// #define DEBUG5 1 /* capture 9600 output to log files */
//#define DEBUG4 1 /* capture 9600 output to log files */
/*------------------------------------------------------------------
@ -33,6 +33,8 @@
*
*---------------------------------------------------------------*/
#include "direwolf.h"
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
@ -42,7 +44,6 @@
#include <assert.h>
#include <ctype.h>
#include "direwolf.h"
#include "tune.h"
#include "fsk_demod_state.h"
#include "hdlc_rec.h"
@ -72,25 +73,10 @@ static inline float convolve (const float *__restrict__ data, const float *__res
float sum = 0.0f;
int j;
#if 0
// As suggested here, http://locklessinc.com/articles/vectorize/
// Unfortunately, older compilers don't recognize it.
// Get more information by using -ftree-vectorizer-verbose=5
float *d = __builtin_assume_aligned(data, 16);
float *f = __builtin_assume_aligned(filter, 16);
#pragma GCC ivdep
for (j=0; j<filter_size; j++) {
sum += f[j] * d[j];
}
#else
#pragma GCC ivdep // ignored until gcc 4.9
//#pragma GCC ivdep // ignored until gcc 4.9
for (j=0; j<filter_size; j++) {
sum += filter[j] * data[j];
}
#endif
return (sum);
}
@ -125,11 +111,11 @@ static inline float agc (float in, float fast_attack, float slow_decay, float *p
*
* Name: demod_9600_init
*
* Purpose: Initialize the 9600 baud demodulator.
* Purpose: Initialize the 9600 (or higher) baud demodulator.
*
* Inputs: samples_per_sec - Number of samples per second.
* Might be upsampled in hopes of
* reducing the PLL jitter.
* Might be upsampled in hopes of
* reducing the PLL jitter.
*
* baud - Data rate in bits per second.
*
@ -147,22 +133,34 @@ void demod_9600_init (int samples_per_sec, int baud, struct demodulator_state_s
memset (D, 0, sizeof(struct demodulator_state_s));
D->num_slicers = 1;
//dw_printf ("demod_9600_init(rate=%d, baud=%d, D ptr)\n", samples_per_sec, baud);
// Multiple profiles in future?
// switch (profile) {
// case 'J': // upsample x2 with filtering.
// case 'K': // upsample x3 with filtering.
// case 'L': // upsample x4 with filtering.
D->lp_filter_len_bits = 76 * 9600.0 / (44100.0 * 2.0);
// Works best with odd number in some tests. Even is better in others.
//D->lp_filter_size = ((int) (0.5 * ( D->lp_filter_len_bits * (float)samples_per_sec / (float)baud ))) * 2 + 1;
D->lp_filter_size = (int) (( D->lp_filter_len_bits * (float)samples_per_sec / baud) + 0.5);
D->lp_window = BP_WINDOW_HAMMING;
D->lpf_baud = 0.62;
D->agc_fast_attack = 0.080;
D->agc_slow_decay = 0.00012;
D->pll_locked_inertia = 0.89;
D->pll_searching_inertia = 0.67;
// break;
// }
D->pll_step_per_sample =
(int) round(TICKS_PER_PLL_CYCLE * (double) baud / (double)samples_per_sec);
D->lp_filter_len_bits = 72 * 9600.0 / (44100.0 * 2.0);
D->lp_filter_size = (int) (( D->lp_filter_len_bits * (float)samples_per_sec / baud) + 0.5);
D->lp_window = BP_WINDOW_HAMMING;
D->lpf_baud = 0.59;
D->agc_fast_attack = 0.080;
D->agc_slow_decay = 0.00012;
D->pll_locked_inertia = 0.88;
D->pll_searching_inertia = 0.67;
#ifdef TUNE_LP_WINDOW
D->lp_window = TUNE_LP_WINDOW;
@ -184,8 +182,11 @@ void demod_9600_init (int samples_per_sec, int baud, struct demodulator_state_s
D->agc_slow_decay = TUNE_AGC_SLOW;
#endif
#if defined(TUNE_PLL_LOCKED) && defined(TUNE_PLL_SEARCHING)
#if defined(TUNE_PLL_LOCKED)
D->pll_locked_inertia = TUNE_PLL_LOCKED;
#endif
#if defined(TUNE_PLL_SEARCHING)
D->pll_searching_inertia = TUNE_PLL_SEARCHING;
#endif
@ -260,23 +261,22 @@ void demod_9600_init (int samples_per_sec, int baud, struct demodulator_state_s
*
*--------------------------------------------------------------------*/
static void inline nudge_pll (int chan, int subchan, int slice, int demod_data, struct demodulator_state_s *D);
static void inline nudge_pll (int chan, int subchan, int slice, float demod_out, struct demodulator_state_s *D);
__attribute__((hot))
void demod_9600_process_sample (int chan, int sam, struct demodulator_state_s *D)
{
float fsam;
//float abs_fsam;
float amp;
float demod_out;
#if DEBUG5
#if DEBUG4
static FILE *demod_log_fp = NULL;
static int seq = 0; /* for log file name */
static int log_file_seq = 0; /* Part of log file name */
#endif
//int j;
int subchan = 0;
int demod_data; /* Still scrambled. */
@ -306,6 +306,12 @@ void demod_9600_process_sample (int chan, int sam, struct demodulator_state_s *D
fsam = sam / 16384.0;
#if defined(TUNE_ZEROSTUFF) && TUNE_ZEROSTUFF == 0
// experiment - no filtering.
amp = fsam;
#else
push_sample (fsam, D->raw_cb, D->lp_filter_size);
/*
@ -313,7 +319,7 @@ void demod_9600_process_sample (int chan, int sam, struct demodulator_state_s *D
*/
amp = convolve (D->raw_cb, D->lp_filter, D->lp_filter_size);
#endif
/*
* Version 1.2: Capture the post-filtering amplitude for display.
@ -324,6 +330,8 @@ void demod_9600_process_sample (int chan, int sam, struct demodulator_state_s *D
* Here we keep + and - peaks because there could be a DC bias.
*/
// TODO: probably no need for this. Just use D->m_peak, D->m_valley
if (amp >= D->alevel_mark_peak) {
D->alevel_mark_peak = amp * D->quick_attack + D->alevel_mark_peak * (1. - D->quick_attack);
}
@ -349,28 +357,10 @@ void demod_9600_process_sample (int chan, int sam, struct demodulator_state_s *D
demod_out = agc (amp, D->agc_fast_attack, D->agc_slow_decay, &(D->m_peak), &(D->m_valley));
// TODO: There is potential for multiple decoders with one filter.
//dw_printf ("peak=%.2f valley=%.2f amp=%.2f norm=%.2f\n", D->m_peak, D->m_valley, amp, norm);
/* Throw in a little Hysteresis??? */
/* (Not to be confused with Hysteria.) */
/* Doesn't seem to have any value. */
/* Using a level of .02 makes things worse. */
/* Might want to experiment with this again someday. */
// if (demod_out > 0.03) {
// demod_data = 1;
// }
// else if (demod_out < -0.03) {
// demod_data = 0;
// }
// else {
// demod_data = D->slicer[subchan].prev_demod_data;
// }
if (D->num_slicers <= 1) {
/* Normal case of one demodulator to one HDLC decoder. */
@ -378,7 +368,7 @@ void demod_9600_process_sample (int chan, int sam, struct demodulator_state_s *D
/* AGC should generally keep this around -1 to +1 range. */
demod_data = demod_out > 0;
nudge_pll (chan, subchan, 0, demod_data, D);
nudge_pll (chan, subchan, 0, demod_out, D);
}
else {
int slice;
@ -386,76 +376,147 @@ void demod_9600_process_sample (int chan, int sam, struct demodulator_state_s *D
/* Multiple slicers each feeding its own HDLC decoder. */
for (slice=0; slice<D->num_slicers; slice++) {
demod_data = demod_out > slice_point[slice];
nudge_pll (chan, subchan, slice, demod_data, D);
demod_data = demod_out - slice_point[slice] > 0;
nudge_pll (chan, subchan, slice, demod_out - slice_point[slice], D);
}
}
// demod_data is used only for debug out.
// suppress compiler warning about it not being used.
(void) demod_data;
#if DEBUG4
if (chan == 0) {
if (1) {
//if (hdlc_rec_gathering (chan, subchan, slice)) {
char fname[30];
int slice = 0;
if (demod_log_fp == NULL) {
log_file_seq++;
snprintf (fname, sizeof(fname), "demod/%04d.csv", log_file_seq);
//if (log_file_seq == 1) mkdir ("demod", 0777);
if (log_file_seq == 1) mkdir ("demod");
demod_log_fp = fopen (fname, "w");
text_color_set(DW_COLOR_DEBUG);
dw_printf ("Starting demodulator log file %s\n", fname);
fprintf (demod_log_fp, "Audio, Filtered, Max, Min, Normalized, Sliced, Clock\n");
}
fprintf (demod_log_fp, "%.3f, %.3f, %.3f, %.3f, %.3f, %d, %.2f\n",
fsam + 6,
amp + 4,
D->m_peak + 4,
D->m_valley + 4,
demod_out + 2,
demod_data + 2,
(D->slicer[slice].data_clock_pll & 0x80000000) ? .5 : .0);
fflush (demod_log_fp);
}
else {
if (demod_log_fp != NULL) {
fclose (demod_log_fp);
demod_log_fp = NULL;
}
}
}
#endif
} /* end demod_9600_process_sample */
/*-------------------------------------------------------------------
*
* Name: nudge_pll
*
* Purpose: Update the PLL state for each audio sample.
*
* (2) Descramble it.
* (2) Recover clock and data.
*
* Inputs: chan - Audio channel. 0 for left, 1 for right.
*
* subchan - Which demodulator. We could have several running in parallel.
*
* slice - Determines which Slicing level & HDLC decoder to use.
*
* demod_out_f - Demodulator output, possibly shifted by slicing level
* It will be compared with 0.0 to bit binary value out.
*
* D - Demodulator state for this channel / subchannel.
*
* Returns: None
*
* Descripton: A PLL is used to sample near the centers of the data bits.
*
* D->data_clock_pll is a SIGNED 32 bit variable.
* When it overflows from a large positive value to a negative value, we
* sample a data bit from the demodulated signal.
*
* Ideally, the the demodulated signal transitions should be near
* zero we we sample mid way between the transitions.
*
* Nudge the PLL by removing some small fraction from the value of
* data_clock_pll, pushing it closer to zero.
*
* This adjustment will never change the sign so it won't cause
* any erratic data bit sampling.
*
* If we adjust it too quickly, the clock will have too much jitter.
* If we adjust it too slowly, it will take too long to lock on to a new signal.
*
* I don't think the optimal value will depend on the audio sample rate
* because this happens for each transition from the demodulator.
*
* Version 1.4: Previously, we would always pull the PLL phase toward 0 after
* after a zero crossing was detetected. This adds extra jitter,
* especially when the ratio of audio sample rate to baud is low.
* Now, we interpolate between the two samples to get an estimate
* on when the zero crossing happened. The PLL is pulled toward
* this point.
*
* Results??? TBD
*
*--------------------------------------------------------------------*/
__attribute__((hot))
static void inline nudge_pll (int chan, int subchan, int slice, int demod_data, struct demodulator_state_s *D)
static void inline nudge_pll (int chan, int subchan, int slice, float demod_out_f, struct demodulator_state_s *D)
{
/*
* Next, a PLL is used to sample near the centers of the data bits.
*
* D->data_clock_pll is a SIGNED 32 bit variable.
* When it overflows from a large positive value to a negative value, we
* sample a data bit from the demodulated signal.
*
* Ideally, the the demodulated signal transitions should be near
* zero we we sample mid way between the transitions.
*
* Nudge the PLL by removing some small fraction from the value of
* data_clock_pll, pushing it closer to zero.
*
* This adjustment will never change the sign so it won't cause
* any erratic data bit sampling.
*
* If we adjust it too quickly, the clock will have too much jitter.
* If we adjust it too slowly, it will take too long to lock on to a new signal.
*
* I don't think the optimal value will depend on the audio sample rate
* because this happens for each transition from the demodulator.
*
* This was optimized for 1200 baud AFSK. There might be some opportunity
* for improvement here.
*/
D->slicer[slice].prev_d_c_pll = D->slicer[slice].data_clock_pll;
D->slicer[slice].data_clock_pll += D->pll_step_per_sample;
if (D->slicer[slice].data_clock_pll < 0 && D->slicer[slice].prev_d_c_pll > 0) {
if ( D->slicer[slice].prev_d_c_pll > 1000000000 && D->slicer[slice].data_clock_pll < -1000000000) {
/* Overflow. */
/* Overflow. Was large positive, wrapped around, now large negative. */
/*
* At this point, we need to descramble the data as
* in hardware based designs by G3RUH and K9NG.
*
* Future Idea: allow unscrambled baseband data.
*
* http://www.amsat.org/amsat/articles/g3ruh/109/fig03.gif
*/
// Warning: 'descram' set but not used.
// It's used in conditional debug code below.
// descram =
descramble (demod_data, &(D->slicer[slice].lfsr));
hdlc_rec_bit (chan, subchan, slice, demod_data, 1, D->slicer[slice].lfsr);
hdlc_rec_bit (chan, subchan, slice, demod_out_f > 0, 1, D->slicer[slice].lfsr);
}
if (demod_data != D->slicer[slice].prev_demod_data) {
/*
* Zero crossing?
*/
if ((D->slicer[slice].prev_demod_out_f < 0 && demod_out_f > 0) ||
(D->slicer[slice].prev_demod_out_f > 0 && demod_out_f < 0)) {
// Note: Test for this demodulator, not overall for channel.
float target = 0;
target = D->pll_step_per_sample * demod_out_f / (demod_out_f - D->slicer[slice].prev_demod_out_f);
if (hdlc_rec_gathering (chan, subchan, slice)) {
D->slicer[slice].data_clock_pll = (int)(D->slicer[slice].data_clock_pll * D->pll_locked_inertia);
D->slicer[slice].data_clock_pll = (int)(D->slicer[slice].data_clock_pll * D->pll_locked_inertia + target * (1.0f - D->pll_locked_inertia) );
}
else {
D->slicer[slice].data_clock_pll = (int)(D->slicer[slice].data_clock_pll * D->pll_searching_inertia);
D->slicer[slice].data_clock_pll = (int)(D->slicer[slice].data_clock_pll * D->pll_searching_inertia + target * (1.0f - D->pll_searching_inertia) );
}
}
@ -506,12 +567,9 @@ static void inline nudge_pll (int chan, int subchan, int slice, int demod_data,
* Remember demodulator output (pre-descrambling) so we can compare next time
* for the DPLL sync.
*/
D->slicer[slice].prev_demod_data = demod_data;
D->slicer[slice].prev_demod_out_f = demod_out_f;
} /* end nudge_pll */
/* end demod_9600.c */

View File

@ -39,7 +39,7 @@
*
*---------------------------------------------------------------*/
#include "direwolf.h"
#include <stdlib.h>
#include <stdio.h>
@ -50,9 +50,7 @@
#include <assert.h>
#include <ctype.h>
#include "direwolf.h"
#include "audio.h"
#include "tune.h"
#include "fsk_demod_state.h"
#include "fsk_gen_filter.h"
@ -105,7 +103,7 @@ static inline float convolve (const float *__restrict__ data, const float *__res
int j;
#pragma GCC ivdep // ignored until gcc 4.9
//#pragma GCC ivdep // ignored until gcc 4.9
for (j=0; j<filter_size; j++) {
sum += filter[j] * data[j];
}

View File

@ -94,7 +94,7 @@
*
*---------------------------------------------------------------*/
#include "direwolf.h"
#include <stdlib.h>
#include <stdio.h>
@ -105,9 +105,8 @@
#include <assert.h>
#include <ctype.h>
#include "direwolf.h"
#include "audio.h"
#include "audio.h"
#include "tune.h"
#include "fsk_demod_state.h"
#include "fsk_gen_filter.h"
@ -694,14 +693,14 @@ void demod_psk_process_sample (int chan, int subchan, int sam, struct demodulato
#endif
}
else {
float a, delta;
int id;
float a;
int idelta;
a = my_atan2f(I,Q);
id = ((int)((a / (2.f * M_PI) + 1.f) * 256.f)) & 0xff;
idelta = ((int)((a / (2.f * M_PI) + 1.f) * 256.f)) & 0xff;
// 32 (90 degrees) compensates for 1800 carrier vs. 1800 baud.
// 16 is to set threshold between constellation points.
demod_phase_shift = ((id - 32 - 16) >> 5) & 0x7;
demod_phase_shift = ((idelta - 32 - 16) >> 5) & 0x7;
}
nudge_pll (chan, subchan, slice, demod_phase_shift, D);

View File

@ -53,6 +53,7 @@
#define DIGIPEATER_C
#include "direwolf.h"
#include <stdlib.h>
#include <string.h>
@ -62,7 +63,6 @@
#include "regex.h"
#include <sys/unistd.h>
#include "direwolf.h"
#include "ax25_pad.h"
#include "digipeater.h"
#include "textcolor.h"
@ -74,8 +74,6 @@
static packet_t digipeat_match (int from_chan, packet_t pp, char *mycall_rec, char *mycall_xmit,
regex_t *uidigi, regex_t *uitrace, int to_chan, enum preempt_e preempt, char *type_filter);
//static int filter_by_type (char *source, char *infop, char *type_filter);
/*
* Keep pointer to configuration options.
@ -87,6 +85,18 @@ static struct audio_s *save_audio_config_p;
static struct digi_config_s *save_digi_config_p;
/*
* Maintain count of packets digipeated for each combination of from/to channel.
*/
static int digi_count[MAX_CHANS][MAX_CHANS];
int digipeater_get_count (int from_chan, int to_chan) {
return (digi_count[from_chan][to_chan]);
}
/*------------------------------------------------------------------------------
*
* Name: digipeater_init
@ -165,6 +175,7 @@ void digipeater (int from_chan, packet_t pp)
if (result != NULL) {
dedupe_remember (pp, to_chan);
tq_append (to_chan, TQ_PRIO_0_HI, result);
digi_count[from_chan][to_chan]++;
}
}
}
@ -190,6 +201,7 @@ void digipeater (int from_chan, packet_t pp)
if (result != NULL) {
dedupe_remember (pp, to_chan);
tq_append (to_chan, TQ_PRIO_1_LO, result);
digi_count[from_chan][to_chan]++;
}
}
}
@ -584,13 +596,11 @@ static int failed;
static enum preempt_e preempt = PREEMPT_OFF;
static char typefilter[20] = "";
static void test (char *in, char *out)
{
packet_t pp, result;
//int should_repeat;
char rec[256];
char xmit[256];
unsigned char *pinfo;
@ -610,6 +620,7 @@ static void test (char *in, char *out)
ax25_format_addrs (pp, rec);
info_len = ax25_get_info (pp, &pinfo);
(void)info_len;
strlcat (rec, (char*)pinfo, sizeof(rec));
if (strcmp(in, rec) != 0) {
@ -863,69 +874,6 @@ int main (int argc, char *argv[])
"");
#if 0 /* changed strategy */
/*
* New in version 1.2.
*/
// no filter.
if (filter_by_type ("CWAPID", ":NWS-TTTTT:DDHHMMz,ADVISETYPE,zcs{seq#", "") != 1)
{ text_color_set(DW_COLOR_ERROR); dw_printf ("filter_by_type case 1\n"); failed++; }
// message should not match psqt
if (filter_by_type ("CWAPID", ":NWS-TTTTT:DDHHMMz,ADVISETYPE,zcs{seq#", "pqst") != 0)
{ text_color_set(DW_COLOR_ERROR); dw_printf ("filter_by_type case 2\n"); failed++; }
// This should match position
if (filter_by_type ("N3LEE-7", "`cHDl <0x1c>[/\"5j}", "qstp") != 1)
{ text_color_set(DW_COLOR_ERROR); dw_printf ("filter_by_type case 3\n"); failed++; }
// This should match nws
if (filter_by_type ("CWAPID", ":NWS-TTTTT:DDHHMMz,ADVISETYPE,zcs{seq#", "n") != 1)
{ text_color_set(DW_COLOR_ERROR); dw_printf ("filter_by_type case 4\n"); failed++; }
// But not this.
if (filter_by_type ("CWAPID", ":zzz-TTTTT:DDHHMMz,ADVISETYPE,zcs{seq#", "n") != 0)
{ text_color_set(DW_COLOR_ERROR); dw_printf ("filter_by_type case 5\n"); failed++; }
// This should match nws
if (filter_by_type ("CWAPID", ";CWAttttz *DDHHMMzLATLONICONADVISETYPE{seq#", "n") != 1)
{ text_color_set(DW_COLOR_ERROR); dw_printf ("filter_by_type case 6\n"); failed++; }
// But not this due do addressee prefix mismatch
if (filter_by_type ("CWAPID", ";NWSttttz *DDHHMMzLATLONICONADVISETYPE{seq#", "n") != 0)
{ text_color_set(DW_COLOR_ERROR); dw_printf ("filter_by_type case 7\n"); failed++; }
/*
* Filtering integrated with rest of process...
*/
strlcpy (typefilter, "w", sizeof(typefilter));
test ( "N8VIM>APN391,WIDE2-1:$ULTW00000000010E097D2884FFF389DC000102430002033400000000",
"N8VIM>APN391,WB2OSZ-9*:$ULTW00000000010E097D2884FFF389DC000102430002033400000000");
test ( "AB1OC-10>APWW10,WIDE1-1,WIDE2-1:>FN42er/# Hollis, NH iGate Operational",
"");
strlcpy (typefilter, "s", sizeof(typefilter));
test ( "AB1OC-10>APWW10,WIDE1-1,WIDE2-1:>FN42er/# Hollis, NH iGate Operational",
"AB1OC-10>APWW10,WB2OSZ-9*,WIDE2-1:>FN42er/# Hollis, NH iGate Operational");
test ( "K1ABC-9>TR4R8R,WIDE1-1:`c6LlIb>/`\"4K}_%",
"");
strlcpy (typefilter, "up", sizeof(typefilter));
test ( "K1ABC-9>TR4R8R,WIDE1-1:`c6LlIb>/`\"4K}_%",
"K1ABC-9>TR4R8R,WB2OSZ-9*:`c6LlIb>/`\"4K}_%");
strlcpy (typefilter, "", sizeof(typefilter));
#endif
/*
* Did I miss any cases?
*/

View File

@ -65,6 +65,11 @@ extern void digipeater (int from_chan, packet_t pp);
void digi_regen (int from_chan, packet_t pp);
/* Make statistics available. */
int digipeater_get_count (int from_chan, int to_chan);
#endif
/* end digipeater.h */

View File

@ -35,6 +35,13 @@
*
*---------------------------------------------------------------*/
#define DIREWOLF_C 1
#include "direwolf.h"
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
@ -72,9 +79,7 @@
#endif
#define DIREWOLF_C 1
#include "direwolf.h"
#include "version.h"
#include "audio.h"
#include "config.h"
@ -96,7 +101,6 @@
#include "xmit.h"
#include "ptt.h"
#include "beacon.h"
#include "redecode.h"
#include "dtmf.h"
#include "aprs_tt.h"
#include "tt_user.h"
@ -107,6 +111,7 @@
#include "log.h"
#include "recv.h"
#include "morse.h"
#include "mheard.h"
//static int idx_decoded = 0;
@ -160,7 +165,7 @@ static int d_u_opt = 0; /* "-d u" command line option to print UTF-8 also in h
static int d_p_opt = 0; /* "-d p" option for dumping packets over radio. */
static int q_h_opt = 0; /* "-q h" Quiet, suppress the "heard" line with audio level. */
static int q_d_opt = 0; /* "-q d" Quiet, suppress the decoding of APRS packets. */
static int q_d_opt = 0; /* "-q d" Quiet, suppress the printing of decoded of APRS packets. */
@ -236,10 +241,13 @@ int main (int argc, char *argv[])
// TODO: control development/beta/release by version.h instead of changing here.
// Print platform. This will provide more information when people send a copy the information displayed.
// Might want to print OS version here. For Windows, see:
// https://msdn.microsoft.com/en-us/library/ms724451(v=VS.85).aspx
text_color_init(t_opt);
text_color_set(DW_COLOR_INFO);
//dw_printf ("Dire Wolf version %d.%d (%s) Beta Test\n", MAJOR_VERSION, MINOR_VERSION, __DATE__);
dw_printf ("Dire Wolf DEVELOPMENT version %d.%d %s (%s)\n", MAJOR_VERSION, MINOR_VERSION, "B", __DATE__);
dw_printf ("Dire Wolf DEVELOPMENT version %d.%d %s (%s)\n", MAJOR_VERSION, MINOR_VERSION, "C", __DATE__);
//dw_printf ("Dire Wolf version %d.%d\n", MAJOR_VERSION, MINOR_VERSION);
#if defined(ENABLE_GPSD) || defined(USE_HAMLIB)
@ -660,7 +668,7 @@ int main (int argc, char *argv[])
* Note: This is not the same as a volume control you would see on the screen.
* It is the range of the digital sound representation.
*/
gen_tone_init (&audio_config, 100);
gen_tone_init (&audio_config, 100, 0);
morse_init (&audio_config, 100);
assert (audio_config.adev[0].bits_per_sample == 8 || audio_config.adev[0].bits_per_sample == 16);
@ -723,11 +731,6 @@ int main (int argc, char *argv[])
waypoint_init (&misc_config);
/*
* Create thread for trying to salvage frames with bad FCS.
*/
redecode_init (&audio_config);
/*
* Enable beaconing.
* Open log file first because "-dttt" (along with -l...) will
@ -735,7 +738,8 @@ int main (int argc, char *argv[])
*/
log_init(misc_config.logdir);
beacon_init (&audio_config, &misc_config);
mheard_init (0); // might add debug option someday.
beacon_init (&audio_config, &misc_config, &igate_config);
/*
@ -916,6 +920,7 @@ void app_process_rec_packet (int chan, int subchan, int slice, packet_t pp, alev
int ns;
ftype = ax25_frame_type (pp, &cr, desc, &pf, &nr, &ns);
(void)ftype;
dw_printf ("(%s)", desc);
}
@ -962,15 +967,20 @@ void app_process_rec_packet (int chan, int subchan, int slice, packet_t pp, alev
/* Decode the contents of APRS frames and display in human-readable form. */
/* Suppress decoding if "-q d" option used. */
if ( ( ! q_d_opt ) && ax25_is_aprs(pp)) {
if (ax25_is_aprs(pp)) {
decode_aprs_t A;
decode_aprs (&A, pp, 0);
//Print it all out in human readable format.
decode_aprs_print (&A);
if ( ! q_d_opt ) {
// Print it all out in human readable format unless "-q d" option used.
decode_aprs_print (&A);
}
/*
* Perform validity check on each address.
@ -982,6 +992,11 @@ void app_process_rec_packet (int chan, int subchan, int slice, packet_t pp, alev
log_write (chan, &A, pp, alevel, retries);
// Add to list of stations heard.
mheard_save (chan, &A, pp, alevel, retries);
// Convert to NMEA waypoint sentence if we have a location.
if (A.g_lat != G_UNKNOWN && A.g_lon != G_UNKNOWN) {
@ -994,7 +1009,7 @@ void app_process_rec_packet (int chan, int subchan, int slice, packet_t pp, alev
/* Send to another application if connected. */
// TODO1.3: Put a wrapper around this so we only call one function to send by all methods.
// TODO: Put a wrapper around this so we only call one function to send by all methods.
int flen;
unsigned char fbuf[AX25_MAX_PACKET_LEN];
@ -1119,6 +1134,7 @@ static void usage (char **argv)
dw_printf (" u u = Display non-ASCII text in hexadecimal.\n");
dw_printf (" p p = dump Packets in hexadecimal.\n");
dw_printf (" g g = GPS interface.\n");
dw_printf (" w w = Waypoints for Position or Object Reports.\n");
dw_printf (" t t = Tracker beacon.\n");
dw_printf (" o o = output controls such as PTT and DCD.\n");
dw_printf (" i i = IGate.\n");

View File

@ -1,7 +1,37 @@
/* direwolf.h - Common stuff used many places. */
// TODO: include this file first before anything else in each .c file.
#ifndef DIREWOLF_H
#define DIREWOLF_H 1
/*
* Support Windows XP and later.
*
* We need this before "#include <ws2tcpip.h>".
*
* Don't know what other impact it might have on others.
*/
#if __WIN32__
#ifdef _WIN32_WINNT
#error Include "direwolf.h" before any windows system files.
#endif
#ifdef WINVER
#error Include "direwolf.h" before any windows system files.
#endif
#define _WIN32_WINNT 0x0501 /* Minimum OS version is XP. */
#define WINVER 0x0501 /* Minimum OS version is XP. */
#include <windows.h>
#endif
/*
* Previously, we could handle only a single audio device.
@ -9,6 +39,8 @@
* In version 1.2, we relax this restriction and allow more audio devices.
* Three is probably adequate for standard version.
* Larger reasonable numbers should also be fine.
*
* For example, if you wanted to use 4 audio devices at once, change this to 4.
*/
#define MAX_ADEVS 3
@ -69,7 +101,6 @@
#if __WIN32__
#include <windows.h>
#define SLEEP_SEC(n) Sleep((n)*1000)
#define SLEEP_MS(n) Sleep(n)
#else
@ -191,9 +222,8 @@ char *strsep(char **stringp, const char *delim);
char *strtok_r(char *str, const char *delim, char **saveptr);
#endif
//#if __WIN32__
// Don't recall why for everyone.
char *strcasestr(const char *S, const char *FIND);
//#endif
#if defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__APPLE__)

3
dlq.c
View File

@ -37,6 +37,8 @@
*
*---------------------------------------------------------------*/
#include "direwolf.h"
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
@ -47,7 +49,6 @@
#include <errno.h>
#endif
#include "direwolf.h"
#include "ax25_pad.h"
#include "textcolor.h"
#include "audio.h"

Binary file not shown.

Binary file not shown.

5
dsp.c
View File

@ -26,6 +26,8 @@
*
*----------------------------------------------------------------*/
#include "direwolf.h"
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
@ -34,7 +36,6 @@
#include <ctype.h>
#include <assert.h>
#include "direwolf.h"
#include "audio.h"
#include "fsk_demod_state.h"
#include "fsk_gen_filter.h"
@ -51,7 +52,7 @@
// Don't remove this. It serves as a reminder that an experiment is underway.
#if defined(TUNE_MS_FILTER_SIZE) || defined(TUNE_AGC_FAST) || defined(TUNE_LPF_BAUD) || defined(TUNE_PLL_LOCKED) || defined(TUNE_PROFILE)
#define DEBUG1 1
#define DEBUG1 1 // Don't remove this.
#endif

4
dtmf.c
View File

@ -34,13 +34,13 @@
*
*---------------------------------------------------------------*/
#include "direwolf.h"
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <assert.h>
#include "direwolf.h"
#include "dtmf.h"
#include "hdlc_rec.h" // for dcd_change
@ -48,7 +48,7 @@
#if DTMF_TEST
#define TIMEOUT_SEC 1 /* short for unit test below. */
#define DEBUG 1
#define DEBUG 1 // Don't remove this. We want more output for test.
#else
#define TIMEOUT_SEC 5 /* for normal operation. */
#endif

View File

@ -48,13 +48,14 @@
*
*---------------------------------------------------------------*/
#include "direwolf.h"
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "direwolf.h"
#include "textcolor.h"
#include "dwgps.h"
#include "dwgpsnmea.h"

View File

@ -34,6 +34,9 @@
*---------------------------------------------------------------*/
#include "direwolf.h"
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
@ -60,7 +63,6 @@
#endif
#include "direwolf.h"
#include "textcolor.h"
#include "dwgps.h"
#include "dwgpsd.h"

View File

@ -29,6 +29,9 @@
*---------------------------------------------------------------*/
#include "direwolf.h"
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
@ -38,7 +41,6 @@
#include <time.h>
#include "direwolf.h"
#include "textcolor.h"
#include "dwgps.h"
#include "dwgpsnmea.h"

View File

@ -33,6 +33,8 @@
*
*---------------------------------------------------------------*/
#include "direwolf.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
@ -42,7 +44,6 @@
#include <math.h>
#include <assert.h>
#include "direwolf.h"
#include "encode_aprs.h"
#include "latlong.h"
#include "textcolor.h"
@ -692,7 +693,7 @@ int encode_object (char *name, int compressed, time_t thyme, double lat, double
#define XMIT_UTC 1
#if XMIT_UTC
gmtime_r (&thyme, &tm);
(void)gmtime_r (&thyme, &tm);
#else
/* Using local time, for this application, would make more sense to me. */
/* On Windows, localtime_r produces UTC. */

View File

@ -18,6 +18,8 @@
//
#include "direwolf.h"
#include <stdio.h>
/*

View File

@ -234,6 +234,7 @@ struct demodulator_state_s
int prev_demod_data; // Previous data bit detected.
// Used to look for transitions.
float prev_demod_out_f;
/* This is used only for "9600" baud data. */

View File

@ -60,7 +60,7 @@
*------------------------------------------------------------------*/
#include "direwolf.h"
#include <stdio.h>
#include <stdlib.h>
@ -463,7 +463,7 @@ int main(int argc, char **argv)
amplitude = 100;
}
gen_tone_init (&modem, amplitude/2);
gen_tone_init (&modem, amplitude/2, 1);
morse_init (&modem, amplitude/2);
@ -635,6 +635,8 @@ int main(int argc, char **argv)
else {
/* e.g. 9600 */
g_noise_level = 0.33 * (amplitude / 200.0) * ((float)i / packet_count);
// temp test
//g_noise_level = 0.20 * (amplitude / 200.0) * ((float)i / packet_count);
}
snprintf (stemp, sizeof(stemp), "WB2OSZ-15>TEST:,The quick brown fox jumps over the lazy dog! %04d of %04d", i, packet_count);
@ -677,8 +679,8 @@ static void usage (char **argv)
dw_printf (" -r <number> Audio sample Rate. Default is %d.\n", DEFAULT_SAMPLES_PER_SEC);
dw_printf (" -n <number> Generate specified number of frames with increasing noise.\n");
dw_printf (" -o <file> Send output to .wav file.\n");
// dw_printf (" -8 8 bit audio rather than 16.\n");
// dw_printf (" -2 2 channels of audio rather than 1.\n");
dw_printf (" -8 8 bit audio rather than 16.\n");
dw_printf (" -2 2 channels (stereo) audio rather than one channel.\n");
// dw_printf (" -z <number> Number of leading zero bits before frame.\n");
// dw_printf (" Default is 12 which is .01 seconds at 1200 bits/sec.\n");

View File

@ -1,3 +1,6 @@
//#define DEBUG 1
//#define DEBUG2 1
//
// This file is part of Dire Wolf, an amateur radio packet TNC.
//
@ -28,6 +31,9 @@
*
*---------------------------------------------------------------*/
#include "direwolf.h"
#include <stdio.h>
#include <math.h>
#include <unistd.h>
@ -35,7 +41,7 @@
#include <stdlib.h>
#include <assert.h>
#include "direwolf.h"
#include "audio.h"
#include "gen_tone.h"
#include "textcolor.h"
@ -47,7 +53,7 @@
// Properties of the digitized sound stream & modem.
static struct audio_s *save_audio_config_p;
static struct audio_s *save_audio_config_p = NULL;
/*
* 8 bit samples are unsigned bytes in range of 0 .. 255.
@ -99,9 +105,6 @@ static int bit_count[MAX_CHANS]; // Counter incremented for each bit transmitted
// three for each symbol.
static int save_bit[MAX_CHANS];
static int prev_symbol[MAX_CHANS]; // Data is conveyed by phase relative to the
// previous symbol. So we need to keep it.
/*
* The K9NG/G3RUH output originally took a very simple and lazy approach.
@ -177,6 +180,9 @@ static int resample[MAX_CHANS];
*
* amp - Signal amplitude on scale of 0 .. 100.
*
* gen_packets - True if being called from "gen_packets" utility
* rather than the "direwolf" application.
*
* Returns: 0 for success.
* -1 for failure.
*
@ -188,11 +194,17 @@ static int resample[MAX_CHANS];
static int amp16bit; /* for 9600 baud */
int gen_tone_init (struct audio_s *audio_config_p, int amp)
int gen_tone_init (struct audio_s *audio_config_p, int amp, int gen_packets)
{
int j;
int chan = 0;
#if DEBUG
text_color_set(DW_COLOR_DEBUG);
dw_printf ("gen_tone_init ( audio_config_p=%p, amp=%d, gen_packets=%d )\n",
audio_config_p, amp, gen_packets);
#endif
/*
* Save away modem parameters for later use.
*/
@ -209,6 +221,15 @@ int gen_tone_init (struct audio_s *audio_config_p, int amp)
int a = ACHAN2ADEV(chan);
#if DEBUG
text_color_set(DW_COLOR_DEBUG);
dw_printf ("gen_tone_init: chan=%d, modem_type=%d, bps=%d, samples_per_sec=%d\n",
chan,
save_audio_config_p->achan[chan].modem_type,
audio_config_p->achan[chan].baud,
audio_config_p->adev[a].samples_per_sec);
#endif
tone_phase[chan] = 0;
bit_len_acc[chan] = 0;
lfsr[chan] = 0;
@ -302,6 +323,20 @@ int gen_tone_init (struct audio_s *audio_config_p, int amp)
float fc; /* Cutoff frequency as fraction of sampling frequency. */
/*
* Normally, we want to generate the same thing whether sending over the air
* or putting it into a file for other testing.
* (There is an important exception. gen_packets can introduce random noise.)
* In this case, we want more aggressive low pass filtering so it looks more like
* what we see coming out of a receiver.
* Specifically, single bits of the same state have considerably reduced amplitude
* below several same values in a row.
*/
if (gen_packets) {
filter_len_bits = 4;
lpf_baud = 0.55; /* Lowpass cutoff freq as fraction of baud rate */
}
samples_per_sec = audio_config_p->adev[a].samples_per_sec * UPSAMPLE;
baud = audio_config_p->achan[chan].baud;
@ -339,7 +374,7 @@ int gen_tone_init (struct audio_s *audio_config_p, int amp)
/*-------------------------------------------------------------------
*
* Name: gen_tone_put_bit
* Name: tone_gen_put_bit
*
* Purpose: Generate tone of proper duration for one data bit.
*
@ -364,6 +399,7 @@ void tone_gen_put_bit (int chan, int dat)
{
int a = ACHAN2ADEV(chan); /* device for channel. */
assert (save_audio_config_p != NULL);
assert (save_audio_config_p->achan[chan].valid);
@ -385,26 +421,15 @@ void tone_gen_put_bit (int chan, int dat)
bit_count[chan]++;
return;
}
#define REV2 1
#if REV2
#else
tone_phase[chan] = PHASE_SHIFT_45;
if (bit_count[chan] & 2) {
tone_phase[chan] += (unsigned)PHASE_SHIFT_180;
}
#endif
// All zero bits should give us steady 1800 Hz.
// All one bits should flip phase by 180 degrees each time.
dibit = (save_bit[chan] << 1) | dat;
#if REV2
symbol = gray2phase_v26[dibit];
tone_phase[chan] += symbol * PHASE_SHIFT_90;
#else
symbol = (prev_symbol[chan] + gray2phase_v26[dibit]) & 0x3;
tone_phase[chan] += symbol * PHASE_SHIFT_90;
prev_symbol[chan] = symbol;
#endif
bit_count[chan]++;
}
@ -425,14 +450,10 @@ void tone_gen_put_bit (int chan, int dat)
// All one bits should flip phase by 180 degrees each time.
tribit = (save_bit[chan] << 1) | dat;
#if 1
symbol = gray2phase_v27[tribit];
tone_phase[chan] += symbol * PHASE_SHIFT_45;
#else
symbol = (prev_symbol[chan] + gray2phase_v27[tribit]) & 0x7;
tone_phase[chan] = symbol * PHASE_SHIFT_45;
prev_symbol[chan] = symbol;
#endif
save_bit[chan] = 0;
bit_count[chan] = 0;
}
@ -445,39 +466,63 @@ void tone_gen_put_bit (int chan, int dat)
dat = x;
}
do {
do { /* until enough audio samples for this symbol. */
if (save_audio_config_p->achan[chan].modem_type == MODEM_AFSK) {
int sam;
int sam;
float fsam;
tone_phase[chan] += dat ? f2_change_per_sample[chan] : f1_change_per_sample[chan];
sam = sine_table[(tone_phase[chan] >> 24) & 0xff];
gen_tone_put_sample (chan, a, sam);
}
else if (save_audio_config_p->achan[chan].modem_type == MODEM_QPSK ||
save_audio_config_p->achan[chan].modem_type == MODEM_8PSK) {
int sam;
switch (save_audio_config_p->achan[chan].modem_type) {
tone_phase[chan] += f1_change_per_sample[chan];
sam = sine_table[(tone_phase[chan] >> 24) & 0xff];
gen_tone_put_sample (chan, a, sam);
}
else {
case MODEM_AFSK:
float fsam = dat ? amp16bit : (-amp16bit);
/* version 1.2 - added a low pass filter instead of square wave out. */
push_sample (fsam, raw[chan], lp_filter_size[chan]);
resample[chan]++;
if (resample[chan] >= UPSAMPLE) {
int sam;
sam = (int) convolve (raw[chan], lp_filter[chan], lp_filter_size[chan]);
resample[chan] = 0;
#if DEBUG2
text_color_set(DW_COLOR_DEBUG);
dw_printf ("tone_gen_put_bit %d AFSK\n", __LINE__);
#endif
tone_phase[chan] += dat ? f2_change_per_sample[chan] : f1_change_per_sample[chan];
sam = sine_table[(tone_phase[chan] >> 24) & 0xff];
gen_tone_put_sample (chan, a, sam);
}
break;
case MODEM_QPSK:
case MODEM_8PSK:
#if DEBUG2
text_color_set(DW_COLOR_DEBUG);
dw_printf ("tone_gen_put_bit %d PSK\n", __LINE__);
#endif
tone_phase[chan] += f1_change_per_sample[chan];
sam = sine_table[(tone_phase[chan] >> 24) & 0xff];
gen_tone_put_sample (chan, a, sam);
break;
case MODEM_BASEBAND:
case MODEM_SCRAMBLE:
#if DEBUG2
text_color_set(DW_COLOR_DEBUG);
dw_printf ("tone_gen_put_bit %d SCR\n", __LINE__);
#endif
fsam = dat ? amp16bit : (-amp16bit);
/* version 1.2 - added a low pass filter instead of square wave out. */
push_sample (fsam, raw[chan], lp_filter_size[chan]);
resample[chan]++;
if (resample[chan] >= UPSAMPLE) {
sam = (int) convolve (raw[chan], lp_filter[chan], lp_filter_size[chan]);
resample[chan] = 0;
gen_tone_put_sample (chan, a, sam);
}
break;
default:
text_color_set(DW_COLOR_ERROR);
dw_printf ("INTERNAL ERROR: %s %d achan[%d].modem_type = %d\n",
__FILE__, __LINE__, chan, save_audio_config_p->achan[chan].modem_type);
exit (EXIT_FAILURE);
}
/* Enough for the bit time? */
@ -493,12 +538,14 @@ void tone_gen_put_bit (int chan, int dat)
void gen_tone_put_sample (int chan, int a, int sam) {
/* Ship out an audio sample. */
/* 16 bit is signed, little endian, range -32768 .. +32767 */
/* 8 bit is unsigned, range 0 .. 255 */
assert (save_audio_config_p != NULL);
assert (save_audio_config_p->adev[a].num_channels == 1 || save_audio_config_p->adev[a].num_channels == 2);
/* Generalize to allow 8 bits someday? */
assert (save_audio_config_p->adev[a].bits_per_sample == 16);
assert (save_audio_config_p->adev[a].bits_per_sample == 16 || save_audio_config_p->adev[a].bits_per_sample == 8);
// TODO: Should print message telling user to reduce output level.
@ -509,8 +556,13 @@ void gen_tone_put_sample (int chan, int a, int sam) {
/* Mono */
audio_put (a, sam & 0xff);
audio_put (a, (sam >> 8) & 0xff);
if (save_audio_config_p->adev[a].bits_per_sample == 8) {
audio_put (a, ((sam+32768) >> 8) & 0xff);
}
else {
audio_put (a, sam & 0xff);
audio_put (a, (sam >> 8) & 0xff);
}
}
else {
@ -518,21 +570,33 @@ void gen_tone_put_sample (int chan, int a, int sam) {
/* Stereo, left channel. */
audio_put (a, sam & 0xff);
audio_put (a, (sam >> 8) & 0xff);
if (save_audio_config_p->adev[a].bits_per_sample == 8) {
audio_put (a, ((sam+32768) >> 8) & 0xff);
audio_put (a, 0);
}
else {
audio_put (a, sam & 0xff);
audio_put (a, (sam >> 8) & 0xff);
audio_put (a, 0);
audio_put (a, 0);
audio_put (a, 0);
audio_put (a, 0);
}
}
else {
/* Stereo, right channel. */
audio_put (a, 0);
audio_put (a, 0);
if (save_audio_config_p->adev[a].bits_per_sample == 8) {
audio_put (a, 0);
audio_put (a, ((sam+32768) >> 8) & 0xff);
}
else {
audio_put (a, 0);
audio_put (a, 0);
audio_put (a, sam & 0xff);
audio_put (a, (sam >> 8) & 0xff);
audio_put (a, sam & 0xff);
audio_put (a, (sam >> 8) & 0xff);
}
}
}
}

View File

@ -3,7 +3,7 @@
*/
int gen_tone_init (struct audio_s *pp, int amp);
int gen_tone_init (struct audio_s *pp, int amp, int gen_packets);
//int gen_tone_open (int nchan, int sample_rate, int bit_rate, int f1, int f2, int amp, char *fname);

View File

@ -27,11 +27,12 @@
*
*******************************************************************************/
#include "direwolf.h"
#include <stdio.h>
#include <assert.h>
#include <string.h>
#include "direwolf.h"
#include "demod.h"
#include "hdlc_rec.h"
#include "hdlc_rec2.h"
@ -46,6 +47,7 @@
//#define TEST 1 /* Define for unit testing. */
//#define DEBUG3 1 /* monitor the data detect signal. */
@ -278,6 +280,7 @@ void hdlc_rec_bit (int chan, int subchan, int slice, int raw, int is_scrambled,
* when listening to live signals. Let's try 3 and see how that works out.
*/
//if (H->flag4_det == 0x7e7e7e7e) {
if ((H->flag4_det & 0xffffff00) == 0x7e7e7e00) {
//if ((H->flag4_det & 0xffff0000) == 0x7e7e0000) {

View File

@ -84,13 +84,15 @@
*
*******************************************************************************/
#include "direwolf.h"
#include <stdio.h>
#include <assert.h>
#include <ctype.h>
#include <string.h>
//Optimize processing by accessing directly to decoded bits
#define RRBB_C 1
#include "direwolf.h"
#include "hdlc_rec2.h"
#include "fcs_calc.h"
#include "textcolor.h"
@ -242,6 +244,8 @@ void hdlc_rec2_block (rrbb_t block)
/* Create an empty retry configuration */
retry_conf_t retry_cfg;
memset (&retry_cfg, 0, sizeof(retry_cfg));
/*
* For our first attempt we don't try to alter any bits.
* Still let it thru if passall AND no retries are desired.
@ -327,7 +331,7 @@ void hdlc_rec2_block (rrbb_t block)
static int try_to_fix_quick_now (rrbb_t block, int chan, int subchan, int slice, alevel_t alevel)
{
int ok;
int len, i,j;
int len, i;
retry_t fix_bits = save_audio_config_p->achan[chan].fix_bits;
//int passall = save_audio_config_p->achan[chan].passall;
@ -335,6 +339,9 @@ static int try_to_fix_quick_now (rrbb_t block, int chan, int subchan, int slice,
len = rrbb_get_len(block);
/* Prepare the retry configuration */
retry_conf_t retry_cfg;
memset (&retry_cfg, 0, sizeof(retry_cfg));
/* Will modify only contiguous bits*/
retry_cfg.mode = RETRY_MODE_CONTIGUOUS;
/*
@ -464,14 +471,17 @@ static int try_to_fix_quick_now (rrbb_t block, int chan, int subchan, int slice,
int hdlc_rec2_try_to_fix_later (rrbb_t block, int chan, int subchan, int slice, alevel_t alevel)
{
int ok;
int len, i, j;
retry_t fix_bits = save_audio_config_p->achan[chan].fix_bits;
//int len;
//retry_t fix_bits = save_audio_config_p->achan[chan].fix_bits;
int passall = save_audio_config_p->achan[chan].passall;
#if DEBUG_LATER
double tstart, tend;
#endif
retry_conf_t retry_cfg;
len = rrbb_get_len(block);
memset (&retry_cfg, 0, sizeof(retry_cfg));
//len = rrbb_get_len(block);
/*

View File

@ -1,3 +1,4 @@
//
// This file is part of Dire Wolf, an amateur radio packet TNC.
//
@ -17,10 +18,10 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
#include "direwolf.h"
#include <stdio.h>
#include "direwolf.h"
#include "hdlc_send.h"
#include "audio.h"
#include "gen_tone.h"
@ -33,7 +34,9 @@ static void send_bit (int, int);
static int number_of_bits_sent[MAX_CHANS];
static int number_of_bits_sent[MAX_CHANS]; // Count number of bits sent by "hdlc_send_frame" or "hdlc_send_flags"
@ -162,7 +165,10 @@ int hdlc_send_flags (int chan, int nflags, int finish)
static int stuff = 0;
static int stuff[MAX_CHANS]; // Count number of "1" bits to keep track of when we
// need to break up a long run by "bit stuffing."
// Needs to be array because we could be transmitting
// on multiple channels at the same time.
static void send_control (int chan, int x)
{
@ -173,7 +179,7 @@ static void send_control (int chan, int x)
x >>= 1;
}
stuff = 0;
stuff[chan] = 0;
}
static void send_data (int chan, int x)
@ -183,13 +189,13 @@ static void send_data (int chan, int x)
for (i=0; i<8; i++) {
send_bit (chan, x & 1);
if (x & 1) {
stuff++;
if (stuff == 5) {
stuff[chan]++;
if (stuff[chan] == 5) {
send_bit (chan, 0);
stuff = 0;
stuff[chan] = 0;
}
} else {
stuff = 0;
stuff[chan] = 0;
}
x >>= 1;
}
@ -203,13 +209,13 @@ static void send_data (int chan, int x)
static void send_bit (int chan, int b)
{
static int output;
static int output[MAX_CHANS];
if (b == 0) {
output = ! output;
output[chan] = ! output[chan];
}
tone_gen_put_bit (chan, output);
tone_gen_put_bit (chan, output[chan]);
number_of_bits_sent[chan]++;
}

148
igate.c
View File

@ -63,18 +63,15 @@
* Cygwin: Can use either one.
*/
#include "direwolf.h" // Sets _WIN32_WINNT for XP API level needed by ws2tcpip.h
#if __WIN32__
/* The goal is to support Windows XP and later. */
#include <winsock2.h>
// default is 0x0400
#undef _WIN32_WINNT
#define _WIN32_WINNT 0x0501 /* Minimum OS version is XP. */
//#define _WIN32_WINNT 0x0502 /* Minimum OS version is XP with SP2. */
//#define _WIN32_WINNT 0x0600 /* Minimum OS version is Vista. */
#include <ws2tcpip.h>
#include <ws2tcpip.h> // _WIN32_WINNT must be set to 0x0501 before including this
#else
#include <stdlib.h>
#include <netdb.h>
@ -293,8 +290,10 @@ static int s_debug;
/*
* Statistics.
* TODO: need print function.
* Statistics for IGate function.
* Note that the RF related counters are just a subset of what is happening on radio channels.
*
* TODO: should have debug option to print these occasionally.
*/
static int stats_failed_connect; /* Number of times we tried to connect to */
@ -312,8 +311,10 @@ static time_t stats_connect_at; /* Most recent time connection was established.
/* can be used to determine elapsed connect time. */
static int stats_rf_recv_packets; /* Number of candidate packets from the radio. */
/* This is not the total number of AX.25 frames received */
/* over the radio; only APRS packets get this far. */
static int stats_rx_igate_packets; /* Number of packets passed along to the IGate */
static int stats_uplink_packets; /* Number of packets passed along to the IGate */
/* server after filtering. */
static int stats_uplink_bytes; /* Total number of bytes sent to IGate server */
@ -322,40 +323,44 @@ static int stats_uplink_bytes; /* Total number of bytes sent to IGate server */
static int stats_downlink_bytes; /* Total number of bytes from IGate server including */
/* packets, heartbeats, other messages. */
static int stats_tx_igate_packets; /* Number of packets from IGate server. */
static int stats_downlink_packets; /* Number of packets from IGate server for possible transmission. */
/* Fewer might be transmitted due to filtering or rate limiting. */
static int stats_rf_xmit_packets; /* Number of packets passed along to radio */
/* after rate limiting or other restrictions. */
static int stats_rf_xmit_packets; /* Number of packets passed along to radio, for the IGate function, */
/* after filtering, rate limiting, or other restrictions. */
/* Number of packets transmitted for beacons, digipeating, */
/* or client applications are not included here. */
/* We have some statistics. What do we do with them?
static int stats_msg_cnt; /* Number of "messages" transmitted. Subset of above. */
/* A "message" has the data type indicator of ":" and it is */
/* not the special case of telemetry metadata. */
IGate stations often send packets like this:
/*
* Make some of these available for IGate statistics beacon like
*
* WB2OSZ>APDW14,WIDE1-1:<IGATE,MSG_CNT=2,PKT_CNT=0,DIR_CNT=10,LOC_CNT=35,RF_CNT=45
*
* MSG_CNT is only "messages." From original spec.
* PKT_CNT is other (non-message) packets. Followed precedent of APRSISCE32.
*/
<IGATE MSG_CNT=1238 LOC_CNT=0 FILL_CNT=0
<IGATE,MSG_CNT=1,LOC_CNT=25
<IGATE,MSG_CNT=0,LOC_CNT=46,DIR_CNT=13,RF_CNT=49,RFPORT_ID=0
int igate_get_msg_cnt (void) {
return (stats_msg_cnt);
}
What does it all mean?
Why do some have spaces instead of commas between the capabilities?
int igate_get_pkt_cnt (void) {
return (stats_rf_xmit_packets - stats_msg_cnt);
}
The APRS Protocol Reference ( http://www.aprs.org/doc/APRS101.PDF ),
section 15, briefly discusses station capabilities and gives the example
IGATE,MSG_CNT=n,LOC_CNT=n
int igate_get_upl_cnt (void) {
return (stats_uplink_packets);
}
IGate Design ( http://www.aprs-is.net/IGating.aspx ) barely mentions
<IGATE,MSG_CNT=n,LOC_CNT=n
int igate_get_dnl_cnt (void) {
return (stats_downlink_packets);
}
This leaves many questions. Does "number of messages transmitted" mean only
the APRS "Message" (data type indicator ":") or does it mean any type of
APRS packet? What are "local" stations? Those we hear directly without
going thru a digipeater?
What are DIR_CNT, RF_CNT, and so on?
Are the counts since the system started up or are they for some interval?
*/
/*-------------------------------------------------------------------
@ -424,11 +429,12 @@ void igate_init (struct audio_s *p_audio_config, struct igate_config_s *p_igate_
stats_connects = 0;
stats_connect_at = 0;
stats_rf_recv_packets = 0;
stats_rx_igate_packets = 0;
stats_uplink_packets = 0;
stats_uplink_bytes = 0;
stats_downlink_bytes = 0;
stats_tx_igate_packets = 0;
stats_downlink_packets = 0;
stats_rf_xmit_packets = 0;
stats_msg_cnt = 0;
rx_to_ig_init ();
ig_to_tx_init ();
@ -867,6 +873,10 @@ void igate_send_rec_packet (int chan, packet_t recv_pp)
return; /* Login not complete. */
}
/* Gather statistics. */
stats_rf_recv_packets++;
/*
* Check for filtering from specified channel to the IGate server.
*/
@ -875,18 +885,18 @@ void igate_send_rec_packet (int chan, packet_t recv_pp)
if (pfilter(chan, MAX_CHANS, save_digi_config_p->filter_str[chan][MAX_CHANS], recv_pp) != 1) {
text_color_set(DW_COLOR_INFO);
dw_printf ("Packet from channel %d to IGate was rejected by filter: %s\n", chan, save_digi_config_p->filter_str[chan][MAX_CHANS]);
// Is this useful troubleshooting information or just distracting noise?
// Originally this was always printed but there was a request to add a "quiet" option to suppress this.
// version 1.4: Instead, make the default off and activate it only with the debug igate option.
if (s_debug >= 1) {
text_color_set(DW_COLOR_INFO);
dw_printf ("Packet from channel %d to IGate was rejected by filter: %s\n", chan, save_digi_config_p->filter_str[chan][MAX_CHANS]);
}
return;
}
}
/* Gather statistics. */
stats_rf_recv_packets++;
/*
* First make a copy of it because it might be modified in place.
*/
@ -1080,7 +1090,7 @@ static void send_packet_to_server (packet_t pp, int chan)
strlcat (msg, (char*)pinfo, sizeof(msg));
send_msg_to_server (msg);
stats_rx_igate_packets++;
stats_uplink_packets++;
/*
* Remember what was sent to avoid duplicates in near future.
@ -1329,6 +1339,8 @@ static void * igate_recv_thread (void *arg)
ax25_safe_print ((char *)message, len, 0);
dw_printf ("\n");
stats_downlink_packets++;
int to_chan = save_igate_config_p->tx_chan;
if (to_chan >= 0) {
@ -1532,8 +1544,13 @@ static void xmit_packet (char *message, int to_chan)
if (pfilter(MAX_CHANS, to_chan, save_digi_config_p->filter_str[MAX_CHANS][to_chan], pp3) != 1) {
text_color_set(DW_COLOR_INFO);
dw_printf ("Packet from IGate to channel %d was rejected by filter: %s\n", to_chan, save_digi_config_p->filter_str[MAX_CHANS][to_chan]);
// Originally this was always printed but it's probably too much noise.
// Version 1.4, print only if debug option is specified.
if (s_debug >= 1) {
text_color_set(DW_COLOR_INFO);
dw_printf ("Packet from IGate to channel %d was rejected by filter: %s\n", to_chan, save_digi_config_p->filter_str[MAX_CHANS][to_chan]);
}
ax25_delete (pp3);
return;
@ -1599,8 +1616,6 @@ static void xmit_packet (char *message, int to_chan)
if (pradio != NULL) {
stats_tx_igate_packets++;
#if ITEST
text_color_set(DW_COLOR_XMIT);
dw_printf ("Xmit: %s\n", radio);
@ -1609,7 +1624,12 @@ static void xmit_packet (char *message, int to_chan)
/* This consumes packet so don't reference it again! */
tq_append (to_chan, TQ_PRIO_1_LO, pradio);
#endif
stats_rf_xmit_packets++;
stats_rf_xmit_packets++; // Any type of packet.
if (*pinfo == ':' && ! is_telem_metadata(pinfo)) {
stats_msg_cnt++; // "message" be sure to exclude telemetry metadata.
}
ig_to_tx_remember (pp3, save_igate_config_p->tx_chan, 0); // correct. version before encapsulating it.
}
else {
@ -1701,6 +1721,7 @@ static void rx_to_ig_remember (packet_t pp)
ax25_get_addr_with_ssid(pp, AX25_SOURCE, src);
ax25_get_addr_with_ssid(pp, AX25_DESTINATION, dest);
info_len = ax25_get_info (pp, &pinfo);
(void)info_len;
text_color_set(DW_COLOR_DEBUG);
dw_printf ("rx_to_ig_remember [%d] = %d %d \"%s>%s:%s\"\n",
@ -1731,6 +1752,7 @@ static int rx_to_ig_allow (packet_t pp)
ax25_get_addr_with_ssid(pp, AX25_SOURCE, src);
ax25_get_addr_with_ssid(pp, AX25_DESTINATION, dest);
info_len = ax25_get_info (pp, &pinfo);
(void)info_len;
text_color_set(DW_COLOR_DEBUG);
dw_printf ("rx_to_ig_allow? %d \"%s>%s:%s\"\n", crc, src, dest, pinfo);
@ -1986,6 +2008,7 @@ void ig_to_tx_remember (packet_t pp, int chan, int bydigi)
ax25_get_addr_with_ssid(pp, AX25_SOURCE, src);
ax25_get_addr_with_ssid(pp, AX25_DESTINATION, dest);
info_len = ax25_get_info (pp, &pinfo);
(void)info_len;
text_color_set(DW_COLOR_DEBUG);
dw_printf ("ig_to_tx_remember [%d] = ch%d d%d %d %d \"%s>%s:%s\"\n",
@ -2012,16 +2035,20 @@ static int ig_to_tx_allow (packet_t pp, int chan)
time_t now = time(NULL);
int j;
int count_1, count_5;
int increase_limit;
unsigned char *pinfo;
int info_len;
info_len = ax25_get_info (pp, &pinfo);
(void)info_len;
if (s_debug >= 2) {
char src[AX25_MAX_ADDR_LEN];
char dest[AX25_MAX_ADDR_LEN];
unsigned char *pinfo;
int info_len;
ax25_get_addr_with_ssid(pp, AX25_SOURCE, src);
ax25_get_addr_with_ssid(pp, AX25_DESTINATION, dest);
info_len = ax25_get_info (pp, &pinfo);
text_color_set(DW_COLOR_DEBUG);
dw_printf ("ig_to_tx_allow? ch%d %d \"%s>%s:%s\"\n", chan, crc, src, dest, pinfo);
@ -2053,12 +2080,25 @@ static int ig_to_tx_allow (packet_t pp, int chan)
}
}
if (count_1 >= save_igate_config_p->tx_limit_1) {
/* "Messages" (special APRS data type ":") are intentional and more */
/* important than all of the other mostly repetitive useless junk */
/* flowing thru here. */
/* It would be unfortunate to discard a message because we already */
/* hit our limit. I don't want to completely eliminate limiting for */
/* messages, in case something goes terribly wrong, but we can triple */
/* the normal limit for them. */
increase_limit = 1;
if (*pinfo == ':' && ! is_telem_metadata((char*)pinfo)) {
increase_limit = 3;
}
if (count_1 >= save_igate_config_p->tx_limit_1 * increase_limit) {
text_color_set(DW_COLOR_ERROR);
dw_printf ("Tx IGate: Already transmitted maximum of %d packets in 1 minute.\n", save_igate_config_p->tx_limit_1);
return 0;
}
if (count_5 >= save_igate_config_p->tx_limit_5) {
if (count_5 >= save_igate_config_p->tx_limit_5 * increase_limit) {
text_color_set(DW_COLOR_ERROR);
dw_printf ("Tx IGate: Already transmitted maximum of %d packets in 5 minutes.\n", save_igate_config_p->tx_limit_5);
return 0;

19
igate.h
View File

@ -51,6 +51,11 @@ struct igate_config_s {
/* Must start with "," if not empty so it can */
/* simply be inserted after the destination address. */
int max_digi_hops; /* Maximum number of digipeater hops possible for via path. */
/* e.g. "WIDE1-1,WDIE2-2" would be 3. */
/* This is useful to know so we can determine how many */
/* stations we might be able to reach. */
int tx_limit_1; /* Max. packets to transmit in 1 minute. */
int tx_limit_5; /* Max. packets to transmit in 5 minutes. */
@ -84,4 +89,18 @@ void igate_send_rec_packet (int chan, packet_t recv_pp);
void ig_to_tx_remember (packet_t pp, int chan, int bydigi);
/* Get statistics for IGATE status beacon. */
int igate_get_msg_cnt (void);
int igate_get_pkt_cnt (void);
int igate_get_upl_cnt (void);
int igate_get_dnl_cnt (void);
#endif

15
kiss.c
View File

@ -112,12 +112,13 @@
*
*---------------------------------------------------------------*/
#include "direwolf.h"
#include <stdio.h>
#include <unistd.h>
#if __WIN32__
#include <stdlib.h>
#include <windows.h>
#else
#define __USE_XOPEN2KXSI 1
#define __USE_XOPEN 1
@ -138,7 +139,7 @@
#include <assert.h>
#include <string.h>
#include "direwolf.h"
#include "tq.h"
#include "ax25_pad.h"
#include "textcolor.h"
@ -241,17 +242,22 @@ void hex_dump (unsigned char *p, int len);
*
*--------------------------------------------------------------------*/
static MYFDTYPE kiss_open_pt (void);
#if __WIN32__
static MYFDTYPE kiss_open_nullmodem (char *device);
#else
static MYFDTYPE kiss_open_pt (void);
#endif
void kiss_init (struct misc_config_s *mc)
{
int e;
#if __WIN32__
HANDLE kiss_nullmodem_listen_th;
#else
pthread_t kiss_pterm_listen_tid;
pthread_t kiss_nullmodem_listen_tid;
int e;
#endif
memset (&kf, 0, sizeof(kf));
@ -635,7 +641,6 @@ void kiss_send_rec_packet (int chan, unsigned char *fbuf, int flen)
{
unsigned char kiss_buff[2 * AX25_MAX_PACKET_LEN + 2];
int kiss_len;
int j;
int err;
#if ! __WIN32__

View File

@ -68,6 +68,8 @@
*
*---------------------------------------------------------------*/
#include "direwolf.h"
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
@ -75,7 +77,6 @@
#include <assert.h>
#include <string.h>
#include "direwolf.h"
#include "ax25_pad.h"
#include "textcolor.h"
#include "kiss_frame.h"
@ -86,7 +87,7 @@
void hex_dump (unsigned char *p, int len);
static void kiss_process_msg (unsigned char *kiss_msg, int kiss_len, int debug);
#if KISSTEST
@ -98,6 +99,10 @@ void text_color_set (dw_color_t c)
return;
}
#else
static void kiss_process_msg (unsigned char *kiss_msg, int kiss_len, int debug);
#endif
@ -561,9 +566,15 @@ static void kiss_process_msg (unsigned char *kiss_msg, int kiss_len, int debug)
break;
default:
text_color_set(DW_COLOR_DEBUG);
text_color_set(DW_COLOR_ERROR);
dw_printf ("KISS Invalid command %d\n", cmd);
kiss_debug_print (FROM_CLIENT, NULL, kiss_msg, kiss_len);
text_color_set(DW_COLOR_INFO);
dw_printf ("Troubleshooting tip:\n");
dw_printf ("Use \"-d kn\" option on direwolf command line to observe\n");
dw_printf ("all communication with the client application.\n");
break;
}
@ -630,7 +641,7 @@ void kiss_debug_print (fromto_t fromto, char *special, unsigned char *pmsg, int
#if KISSTEST
main ()
int main ()
{
unsigned char din[512];
unsigned char kissed[520];

View File

@ -95,10 +95,12 @@
*/
#include "direwolf.h" // Sets _WIN32_WINNT for XP API level needed by ws2tcpip.h
#if __WIN32__
#include <winsock2.h>
#define _WIN32_WINNT 0x0501
#include <ws2tcpip.h>
#include <ws2tcpip.h> // _WIN32_WINNT must be set to 0x0501 before including this
#else
#include <stdlib.h>
#include <sys/types.h>
@ -115,11 +117,9 @@
#include <unistd.h>
#include <stdio.h>
#include <assert.h>
#include <string.h>
#include "direwolf.h"
#include "tq.h"
#include "ax25_pad.h"
#include "textcolor.h"
@ -128,6 +128,8 @@
#include "kiss_frame.h"
#include "xmit.h"
void hex_dump (unsigned char *p, int len); // This should be in a .h file.
static kiss_frame_t kf; /* Accumulated KISS frame and state of decoder. */
// TODO: multiple instances if multiple KISS network clients!
@ -139,8 +141,15 @@ static int client_sock; /* File descriptor for socket for */
/* (Don't use SOCKET type because it is unsigned.) */
static void * connect_listen_thread (void *arg);
static void * kissnet_listen_thread (void *arg);
// TODO: define in one place, use everywhere.
#if __WIN32__
#define THREAD_F unsigned __stdcall
#else
#define THREAD_F void *
#endif
static THREAD_F connect_listen_thread (void *arg);
static THREAD_F kissnet_listen_thread (void *arg);
@ -184,8 +193,8 @@ void kissnet_init (struct misc_config_s *mc)
#else
pthread_t connect_listen_tid;
pthread_t cmd_listen_tid;
#endif
int e;
#endif
int kiss_port = mc->kiss_port;
@ -208,7 +217,7 @@ void kissnet_init (struct misc_config_s *mc)
* This waits for a client to connect and sets client_sock.
*/
#if __WIN32__
connect_listen_th = _beginthreadex (NULL, 0, connect_listen_thread, (void *)kiss_port, 0, NULL);
connect_listen_th = (HANDLE)_beginthreadex (NULL, 0, connect_listen_thread, (void *)kiss_port, 0, NULL);
if (connect_listen_th == NULL) {
text_color_set(DW_COLOR_ERROR);
dw_printf ("Could not create KISS socket connect listening thread\n");
@ -227,7 +236,7 @@ void kissnet_init (struct misc_config_s *mc)
* This reads messages from client when client_sock is valid.
*/
#if __WIN32__
cmd_listen_th = _beginthreadex (NULL, 0, kissnet_listen_thread, NULL, 0, NULL);
cmd_listen_th = (HANDLE)_beginthreadex (NULL, 0, kissnet_listen_thread, NULL, 0, NULL);
if (cmd_listen_th == NULL) {
text_color_set(DW_COLOR_ERROR);
dw_printf ("Could not create KISS socket command listening thread\n");
@ -263,7 +272,7 @@ void kissnet_init (struct misc_config_s *mc)
*
*--------------------------------------------------------------------*/
static void * connect_listen_thread (void *arg)
static THREAD_F connect_listen_thread (void *arg)
{
#if __WIN32__
@ -284,7 +293,7 @@ static void * connect_listen_thread (void *arg)
if (err != 0) {
text_color_set(DW_COLOR_ERROR);
dw_printf("WSAStartup failed: %d\n", err);
return (NULL);
return (0);
}
if (LOBYTE(wsadata.wVersion) != 2 || HIBYTE(wsadata.wVersion) != 2) {
@ -292,7 +301,7 @@ static void * connect_listen_thread (void *arg)
dw_printf("Could not find a usable version of Winsock.dll\n");
WSACleanup();
//sleep (1);
return (NULL);
return (0);
}
memset (&hints, 0, sizeof(hints));
@ -307,14 +316,14 @@ static void * connect_listen_thread (void *arg)
dw_printf("getaddrinfo failed: %d\n", err);
//sleep (1);
WSACleanup();
return (NULL);
return (0);
}
listen_sock= socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
if (listen_sock == INVALID_SOCKET) {
text_color_set(DW_COLOR_ERROR);
dw_printf ("connect_listen_thread: Socket creation failed, err=%d", WSAGetLastError());
return (NULL);
return (0);
}
#if DEBUG
@ -331,7 +340,7 @@ static void * connect_listen_thread (void *arg)
freeaddrinfo(ai);
closesocket(listen_sock);
WSACleanup();
return (NULL);
return (0);
}
freeaddrinfo(ai);
@ -353,7 +362,7 @@ static void * connect_listen_thread (void *arg)
{
text_color_set(DW_COLOR_ERROR);
dw_printf("Listen failed with error: %d\n", WSAGetLastError());
return (NULL);
return (0);
}
text_color_set(DW_COLOR_INFO);
@ -366,7 +375,7 @@ static void * connect_listen_thread (void *arg)
dw_printf("Accept failed with error: %d\n", WSAGetLastError());
closesocket(listen_sock);
WSACleanup();
return (NULL);
return (0);
}
text_color_set(DW_COLOR_INFO);
@ -481,7 +490,6 @@ void kissnet_send_rec_packet (int chan, unsigned char *fbuf, int flen)
{
unsigned char kiss_buff[2 * AX25_MAX_PACKET_LEN];
int kiss_len;
int j;
int err;
@ -580,6 +588,7 @@ static int read_from_socket (int fd, char *ptr, int len)
#if __WIN32__
//TODO: any flags for send/recv?
//TODO: Would be useful to have more detailed explanation from the error code.
n = recv (fd, ptr + got_bytes, len - got_bytes, 0);
#else
@ -659,7 +668,7 @@ static int kiss_get (void)
}
text_color_set(DW_COLOR_ERROR);
dw_printf ("\nError reading KISS byte from clent application. Closing connection.\n\n");
dw_printf ("\nError reading KISS byte from client application. Closing connection.\n\n");
#if __WIN32__
closesocket (client_sock);
#else
@ -671,7 +680,7 @@ static int kiss_get (void)
static void * kissnet_listen_thread (void *arg)
static THREAD_F kissnet_listen_thread (void *arg)
{
unsigned char ch;
@ -685,7 +694,11 @@ static void * kissnet_listen_thread (void *arg)
kiss_rec_byte (&kf, ch, kiss_debug, kissnet_send_rec_packet);
}
return (NULL); /* to suppress compiler warning. */
#if __WIN32__
return(0);
#else
return (THREAD_F) 0; /* Unreachable but avoids compiler warning. */
#endif
} /* end kissnet_listen_thread */

View File

@ -30,6 +30,7 @@
*
*---------------------------------------------------------------*/
#include "direwolf.h"
#include <stdlib.h>
#include <string.h>
@ -40,7 +41,6 @@
#include <math.h>
#include <assert.h>
#include "direwolf.h"
#include "latlong.h"
#include "textcolor.h"

View File

@ -1,5 +1,7 @@
/* Latitude / Longitude to UTM conversion */
#include "direwolf.h"
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

4
log.c
View File

@ -31,6 +31,8 @@
*
*------------------------------------------------------------------*/
#include "direwolf.h"
#include <stdio.h>
#include <time.h>
#include <assert.h>
@ -42,8 +44,6 @@
#include <unistd.h>
#include <errno.h>
#include "direwolf.h"
#include "ax25_pad.h"
#include "textcolor.h"
#include "decode_aprs.h"

View File

@ -18,17 +18,12 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
#include "direwolf.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#if __WIN32__
char *strsep(char **stringp, const char *delim);
#endif
#include "direwolf.h"
/*
* Information we gather for each thing.

331
mheard.c Normal file
View File

@ -0,0 +1,331 @@
//
// This file is part of Dire Wolf, an amateur radio packet TNC.
//
// Copyright (C) 2016 John Langner, WB2OSZ
//
// 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, see <http://www.gnu.org/licenses/>.
//
/*------------------------------------------------------------------
*
* File: mheard.c
*
* Purpose: Maintain a list of all stations heard.
*
* Description: This was added for IGate statistics but would also be
* useful for the AGW network protocol 'H' request.
*
* This application has no GUI and is not interactive so
* I'm not sure what else we might do with the information.
*
* Future Ideas: Someone suggested using SQLite to store the information
* so other applications could access it.
*
*------------------------------------------------------------------*/
#include "direwolf.h"
#include <stdio.h>
#include <time.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "textcolor.h"
#include "decode_aprs.h"
#include "ax25_pad.h"
#include "hdlc_rec2.h" // for retry_t
#include "mheard.h"
// I think we can get away without a critical region if we follow certain rules.
//
// (1) All updates are from a single thread. Although there are multiple receive
// threads, all received packets go into a single queue for serial processing.
// (2) When adding a new node, make sure it is complete, including next ptr,
// before adding it to the list.
// (3) Nothing gets deleted.
//
// It shouldn't be a problem if the data readers are from other threads.
/*
* Information for each station heard over the radio.
*/
typedef struct mheard_s {
struct mheard_s *pnext; // Pointer to next in list.
char callsign[AX25_MAX_ADDR_LEN]; // Callsign from the AX.25 source field.
int num_digi_hops; // Number of digipeater hops before we heard it.
// Zero when heard directly.
time_t last_heard; // Timestamp when last heard.
// What else would be useful?
// The AGW protocol is by channel and returns
// first heard in addition to last heard.
} mheard_t;
/*
* The list could be quite long and we hit this a lot so use a hash table.
*/
#define MHEARD_HASH_SIZE 73 // Best if prime number.
static mheard_t *mheard_hash[MHEARD_HASH_SIZE];
static inline int hash_index(char *callsign) {
int n = 0;
char *p = callsign;
while (*p != '\0') {
n += *p++;
}
return (n % MHEARD_HASH_SIZE);
}
static mheard_t *mheard_ptr(char *callsign) {
int n = hash_index(callsign);
mheard_t *p = mheard_hash[n];
while (p != NULL) {
if (strcmp(callsign,p->callsign) == 0) return (p);
p = p->pnext;
}
return (NULL);
}
static int mheard_debug;
/*------------------------------------------------------------------
*
* Function: mheard_init
*
* Purpose: Initialization at start of application.
*
* Inputs: debug - Debug level.
*
* Description: Clear pointer table.
* Save debug level for later use.
*
*------------------------------------------------------------------*/
void mheard_init (int debug)
{
int i;
mheard_debug = debug;
for (i = 0; i < MHEARD_HASH_SIZE; i++) {
mheard_hash[i] = NULL;
}
} /* end mheard_init */
/*------------------------------------------------------------------
*
* Function: mheard_save
*
* Purpose: Save information about station heard.
*
* Inputs: chan - Radio channel where heard.
*
* A - Exploded information from APRS packet.
*
* pp - Received packet object.
*
* alevel - audio level.
*
* retries - Amount of effort to get a good CRC.
*
* Description: Calling sequence was copied from "log_write."
* It has a lot more than what we currently keep but the
* hooks are there so it will be easy to capture additional
* information when the need arises.
*
*------------------------------------------------------------------*/
void mheard_save (int chan, decode_aprs_t *A, packet_t pp, alevel_t alevel, retry_t retries)
{
time_t now = time(NULL);
char source[AX25_MAX_ADDR_LEN];
int hops;
mheard_t *mptr;
ax25_get_addr_with_ssid (pp, AX25_SOURCE, source);
/*
* How many digipeaters has it gone thru before we hear it?
* We can count the number of digi addresses that are marked as "has been used."
* This is not always accurate because there is inconsistency in digipeater behavior.
* The base AX.25 spec seems clear in this regard. The used digipeaters should
* should accurately reflict the path taken by the packet. Sometimes we see excess
* stuff in there. Even when you understand what is going on, it is still an ambiguous
* situation. Look for my rant in the User Guide.
*/
hops = ax25_get_heard(pp) - AX25_SOURCE;
mptr = mheard_ptr(source);
if (mptr == NULL) {
int i;
/*
* Not heard before. Add it.
*/
if (mheard_debug) {
text_color_set(DW_COLOR_DEBUG);
dw_printf ("mheard_save: %s %d - added new\n", source, hops);
}
mptr = calloc(sizeof(mheard_t),1);
strlcpy (mptr->callsign, source, sizeof(mptr->callsign));
mptr->num_digi_hops = hops;
mptr->last_heard = now;
i = hash_index(source);
mptr->pnext = mheard_hash[i]; // before inserting into list.
mheard_hash[i] = mptr;
}
else {
/*
* Update existing entry.
* The only tricky part here is that we might hear the same transmission
* several times. First direct, then thru various digipeater paths.
* We are interested in the shortest path if heard very recently.
*/
if (hops > mptr->num_digi_hops && (int)(now - mptr->last_heard) < 15) {
if (mheard_debug) {
text_color_set(DW_COLOR_DEBUG);
dw_printf ("mheard_save: %s %d - skip because hops was %d %d seconds ago.\n", source, hops, mptr->num_digi_hops, (int)(now - mptr->last_heard) );
}
}
else {
if (mheard_debug) {
text_color_set(DW_COLOR_DEBUG);
dw_printf ("mheard_save: %s %d - update time, was %d hops %d seconds ago.\n", source, hops, mptr->num_digi_hops, (int)(now - mptr->last_heard));
}
mptr->num_digi_hops = hops;
mptr->last_heard = now;
}
}
if (mheard_debug >= 2) {
int limit = 10; // normally 30 or 60
text_color_set(DW_COLOR_DEBUG);
dw_printf ("mheard debug, %d min, DIR_CNT=%d,LOC_CNT=%d,RF_CNT=%d\n", limit, mheard_count(0,limit), mheard_count(2,limit), mheard_count(8,limit));
}
} /* end mheard_save */
/*------------------------------------------------------------------
*
* Function: mheard_count
*
* Purpose: Count local stations for IGate statistics report like this:
*
* <IGATE,MSG_CNT=1,LOC_CNT=25
*
* Inputs: max_hops - Include only stations heard with this number of
* digipeater hops or less. For reporting, we might use:
*
* 0 for DIR_CNT (heard directly)
* IGate transmit path for LOC_CNT.
* e.g. 3 for WIDE1-1,WIDE2-2
* 8 for RF_CNT.
*
* time_limit - Include only stations heard within this many minutes.
* Typically 30 or 60.
*
* Returns: Number to be used in the statistics report.
*
* Description: Look for discussion here: http://www.tapr.org/pipermail/aprssig/2016-June/045837.html
*
* Lynn KJ4ERJ:
*
* For APRSISCE/32, "Local" is defined as those stations to which messages
* would be gated if any are received from the APRS-IS. This currently
* means unique stations heard within the past 30 minutes with at most two
* used path hops.
*
* I added DIR_CNT and RF_CNT with comma delimiters to APRSISCE/32's IGate
* status. DIR_CNT is the count of unique stations received on RF in the
* past 30 minutes with no used hops. RF_CNT is the total count of unique
* stations received on RF in the past 30 minutes.
*
* Steve K4HG:
*
* The number of hops defining local should match the number of hops of the
* outgoing packets from the IGate. So if the path is only WIDE, then local
* should only be stations heard direct or through one hop. From the beginning
* I was very much against on a standardization of the outgoing IGate path,
* hams should be free to manage their local RF network in a way that works
* for them. Busy areas one hop may be best, I lived in an area where three was
* a much better choice. I avoided as much as possible prescribing anything
* that might change between locations.
*
* The intent was how many stations are there for which messages could be IGated.
* IGate software keeps an internal list of the 'local' stations so it knows
* when to IGate a message, and this number should be the length of that list.
* Some IGates have a parameter for local timeout, 1 hour was the original default,
* so if in an hour the IGate has not heard another local packet the station is
* dropped from the local list. Messages will no longer be IGated to that station
* and the station count would drop by one. The number should not just continue to rise.
*
*
*------------------------------------------------------------------*/
int mheard_count (int max_hops, int time_limit)
{
time_t since = time(NULL) - time_limit * 60;
int count = 0;
int i;
mheard_t *p;
for (i = 0; i < MHEARD_HASH_SIZE; i++) {
for (p = mheard_hash[i]; p != NULL; p = p->pnext) {
if (p->last_heard >= since && p->num_digi_hops <= max_hops) {
count++;
}
}
}
if (mheard_debug == 1) {
text_color_set(DW_COLOR_DEBUG);
dw_printf ("mheard_count(<= %d digi hops, last %d minutes) returns %d\n", max_hops, time_limit, count);
}
return (count);
} /* end mheard_count */
/* end mheard.c */

9
mheard.h Normal file
View File

@ -0,0 +1,9 @@
/* mheard.h */
void mheard_init (int debug);
void mheard_save (int chan, decode_aprs_t *A, packet_t pp, alevel_t alevel, retry_t retries);
int mheard_count (int max_hops, int time_limit);

View File

@ -30,6 +30,8 @@
*
*---------------------------------------------------------------*/
#include "direwolf.h"
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
@ -39,8 +41,6 @@
#include <time.h>
#include <math.h>
#include "direwolf.h"
#include "textcolor.h"
#include "audio.h"
#include "ptt.h"

View File

@ -74,6 +74,7 @@
//#define DEBUG 1
#define DIGIPEATER_C
#include "direwolf.h"
#include <stdlib.h>
#include <string.h>
@ -81,7 +82,6 @@
#include <stdio.h>
#include <sys/unistd.h>
#include "direwolf.h"
#include "ax25_pad.h"
#include "textcolor.h"
#include "multi_modem.h"

View File

@ -37,6 +37,7 @@
*
*---------------------------------------------------------------*/
#include "direwolf.h"
#include <unistd.h>
#include <assert.h>
@ -45,11 +46,6 @@
#include <stdio.h>
#include <ctype.h>
#if __WIN32__
char *strsep(char **stringp, const char *delim);
#endif
#include "direwolf.h"
#include "ax25_pad.h"
#include "textcolor.h"
#include "decode_aprs.h"
@ -622,7 +618,7 @@ static int filt_bodgu (pfstate_t *pf, char *arg)
/* Telemetry metadata is a special case of message. */
/* We want to categorize it as telemetry rather than message. */
static int is_telem_metadata (char *infop)
int is_telem_metadata (char *infop)
{
if (*infop != ':') return (0);
if (strlen(infop) < 16) return (0);

View File

@ -2,3 +2,5 @@
/* pfilter.h */
int pfilter (int from_chan, int to_chan, char *filter, packet_t pp);
int is_telem_metadata (char *infop);

5
ptt.c
View File

@ -94,6 +94,9 @@
Maybe even for Windows. ;-)
*/
#include "direwolf.h" // should be first. This includes windows.h.
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
@ -102,7 +105,6 @@
#include <time.h>
#if __WIN32__
#include <windows.h>
#else
#include <sys/termios.h>
#include <sys/ioctl.h>
@ -122,7 +124,6 @@ typedef int HANDLE;
#endif
#include "direwolf.h"
#include "textcolor.h"
#include "audio.h"
#include "ptt.h"

3
rdq.c
View File

@ -29,13 +29,14 @@
*
*---------------------------------------------------------------*/
#include "direwolf.h"
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include "direwolf.h"
#include "ax25_pad.h"
#include "textcolor.h"
#include "audio.h"

2
recv.c
View File

@ -82,6 +82,7 @@
//#define DEBUG 1
#include "direwolf.h"
#include <stdio.h>
#include <unistd.h>
@ -97,7 +98,6 @@
#include <errno.h>
#endif
#include "direwolf.h"
#include "audio.h"
#include "demod.h"
#include "multi_modem.h"

View File

@ -1,255 +0,0 @@
//
// This file is part of Dire Wolf, an amateur radio packet TNC.
//
// Copyright (C) 2011, 2012, 2013, 2015 John Langner, WB2OSZ
//
// 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, see <http://www.gnu.org/licenses/>.
//
/*------------------------------------------------------------------
*
* Module: redecode.c
*
* Purpose: Retry decoding frames that have a bad FCS.
*
* Description:
*
*
* Usage: (1) The main application calls redecode_init.
*
* This will initialize the retry decoding queue
* and create a thread to work on contents of the queue.
*
* (2) The application queues up frames by calling rdq_append.
*
*
* (3) redecode_thread removes raw frames from the queue and
* tries to recover from errors.
*
*---------------------------------------------------------------*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include <time.h>
#if __WIN32__
#include <windows.h>
#endif
#include "direwolf.h"
#include "ax25_pad.h"
#include "textcolor.h"
#include "audio.h"
#include "rdq.h"
#include "redecode.h"
#include "hdlc_send.h"
#include "hdlc_rec2.h"
#include "ptt.h"
/* Audio configuration for the fix_bits / passall optiions. */
static struct audio_s *save_audio_config_p;
#if __WIN32__
static unsigned redecode_thread (void *arg);
#else
static void * redecode_thread (void *arg);
#endif
/*-------------------------------------------------------------------
*
* Name: redecode_init
*
* Purpose: Initialize the process to try fixing bits in frames with bad FCS.
*
* Inputs: none.
*
* Outputs: none.
*
* Description: Initialize the queue to be empty and set up other
* mechanisms for sharing it between different threads.
*
* Start up redecode_thread to actually process the
* raw frames from the queue.
*
*--------------------------------------------------------------------*/
void redecode_init (struct audio_s *p_audio_config)
{
#if 0
#if __WIN32__
HANDLE redecode_th;
#else
pthread_t redecode_tid;
int e;
#endif
#if DEBUG
text_color_set(DW_COLOR_DEBUG);
dw_printf ("redecode_init ( ... )\n");
#endif
save_audio_config_p = p_audio_config;
#if DEBUG
text_color_set(DW_COLOR_DEBUG);
dw_printf ("redecode_init: about to call rdq_init \n");
#endif
rdq_init ();
#if DEBUG
text_color_set(DW_COLOR_DEBUG);
dw_printf ("redecode_init: about to create thread \n");
#endif
#if __WIN32__
redecode_th = _beginthreadex (NULL, 0, redecode_thread, NULL, 0, NULL);
if (redecode_th == NULL) {
text_color_set(DW_COLOR_ERROR);
dw_printf ("Could not create redecode thread\n");
return;
}
#else
//TODO: Give thread lower priority.
e = pthread_create (&redecode_tid, NULL, redecode_thread, (void *)0);
if (e != 0) {
text_color_set(DW_COLOR_ERROR);
perror("Could not create redecode thread");
return;
}
#endif
#if DEBUG
text_color_set(DW_COLOR_DEBUG);
dw_printf ("redecode_init: finished \n");
#endif
#endif
} /* end redecode_init */
/*-------------------------------------------------------------------
*
* Name: redecode_thread
*
* Purpose: Try to decode frames with a bad FCS.
*
* Inputs: None.
*
* Outputs:
*
* Description: Initialize the queue to be empty and set up other
* mechanisms for sharing it between different threads.
*
*
*--------------------------------------------------------------------*/
#if 0
#if __WIN32__
static unsigned redecode_thread (void *arg)
#else
static void * redecode_thread (void *arg)
#endif
{
#if __WIN32__
HANDLE tid = GetCurrentThread();
//int tp;
//tp = GetThreadPriority (tid);
//text_color_set(DW_COLOR_DEBUG);
//dw_printf ("Starting redecode thread priority=%d\n", tp);
SetThreadPriority (tid, THREAD_PRIORITY_LOWEST);
//tp = GetThreadPriority (tid);
//dw_printf ("New redecode thread priority=%d\n", tp);
#endif
while (1) {
rrbb_t block;
rdq_wait_while_empty ();
#if DEBUG
text_color_set(DW_COLOR_DEBUG);
dw_printf ("redecode_thread: woke up\n");
#endif
block = rdq_remove ();
#if DEBUG
text_color_set(DW_COLOR_DEBUG);
dw_printf ("redecode_thread: rdq_remove() returned %p\n", block);
#endif
/* Don't expect null ever but be safe. */
if (block != NULL) {
int chan = rrbb_get_chan(block);
int subchan = rrbb_get_subchan(block);
int blen = rrbb_get_len(block);
alevel_t alevel = rrbb_get_audio_level(block);
//retry_t fix_bits = save_audio_config_p->achan[chan].fix_bits;
//int passall = save_audio_config_p->achan[chan].passall;
int ok;
#if DEBUG
text_color_set(DW_COLOR_DEBUG);
dw_printf ("redecode_thread: begin processing %p, from channel %d, blen=%d\n", block, chan, blen);
#endif
ok = hdlc_rec2_try_to_fix_later (block, chan, subchan, alevel);
#if DEBUG
text_color_set(DW_COLOR_DEBUG);
dw_printf ("redecode_thread: finished processing %p\n", block);
#endif
rrbb_delete (block);
}
}
return 0;
} /* end redecode_thread */
#endif
/* end redecode.c */

3
rrbb.c
View File

@ -35,12 +35,13 @@
#define RRBB_C
#include "direwolf.h"
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include "direwolf.h"
#include "textcolor.h"
#include "ax25_pad.h"
#include "rrbb.h"

View File

@ -34,12 +34,13 @@
*
*---------------------------------------------------------------*/
#include "direwolf.h" // should be first
#include <stdio.h>
#if __WIN32__
#include <stdlib.h>
#include <windows.h>
#else
@ -58,7 +59,7 @@
#include <assert.h>
#include <string.h>
#include "direwolf.h"
#include "textcolor.h"
#include "serial_port.h"

View File

@ -8,7 +8,6 @@
#if __WIN32__
#include <stdlib.h>
#include <windows.h>
typedef HANDLE MYFDTYPE;
#define MYFDERROR INVALID_HANDLE_VALUE

View File

@ -121,11 +121,11 @@
* Cygwin: Can use either one.
*/
#include "direwolf.h" // Sets _WIN32_WINNT for XP API level needed by ws2tcpip.h
#if __WIN32__
#include <winsock2.h>
#define _WIN32_WINNT 0x0501
#include <ws2tcpip.h>
#include <ws2tcpip.h> // _WIN32_WINNT must be set to 0x0501 before including this
#else
#include <stdlib.h>
#include <sys/types.h>
@ -146,7 +146,6 @@
#include <time.h>
#include <ctype.h>
#include "direwolf.h"
#include "tq.h"
#include "ax25_pad.h"
#include "textcolor.h"
@ -861,6 +860,7 @@ void server_send_rec_packet (int chan, packet_t pp, unsigned char *fbuf, int fl
time_t clock;
struct tm *tm;
int num_digi;
clock = time(NULL);
tm = localtime(&clock); // TODO: should use localtime_r
@ -885,13 +885,46 @@ void server_send_rec_packet (int chan, packet_t pp, unsigned char *fbuf, int fl
/* The documentation example includes these 3 extra in the Len= value */
/* but actual observed data uses only the packet info length. */
snprintf (agwpe_msg.data, sizeof(agwpe_msg.data), " %d:Fm %s To %s <UI pid=%02X Len=%d >[%02d:%02d:%02d]\r%s\r\r",
// Documentation doesn't mention anything about including the via path.
// In version 1.4, we add that to match observed behaviour.
// This inconsistency was reported:
// Direwolf:
// [AGWE-IN] 1:Fm ZL4FOX-8 To Q7P2U2 [08:25:07]`I1*l V>/"9<}[:Barts Tracker 3.83V X
// AGWPE:
// [AGWE-IN] 1:Fm ZL4FOX-8 To Q7P2U2 Via WIDE3-3 [08:32:14]`I0*l V>/"98}[:Barts Tracker 3.83V X
num_digi = ax25_get_num_repeaters(pp);
if (num_digi > 0) {
char via[AX25_MAX_REPEATERS*(AX25_MAX_ADDR_LEN+1)];
char stemp[AX25_MAX_ADDR_LEN+1];
int j;
ax25_get_addr_with_ssid (pp, AX25_REPEATER_1, via);
for (j = 1; j < num_digi; j++) {
ax25_get_addr_with_ssid (pp, AX25_REPEATER_1 + j, stemp);
strlcat (via, ",", sizeof(via));
strlcat (via, stemp, sizeof(via));
}
snprintf (agwpe_msg.data, sizeof(agwpe_msg.data), " %d:Fm %s To %s Via %s <UI pid=%02X Len=%d >[%02d:%02d:%02d]\r%s\r\r",
chan+1, agwpe_msg.hdr.call_from, agwpe_msg.hdr.call_to, via,
ax25_get_pid(pp), info_len,
tm->tm_hour, tm->tm_min, tm->tm_sec,
pinfo);
}
else {
snprintf (agwpe_msg.data, sizeof(agwpe_msg.data), " %d:Fm %s To %s <UI pid=%02X Len=%d >[%02d:%02d:%02d]\r%s\r\r",
chan+1, agwpe_msg.hdr.call_from, agwpe_msg.hdr.call_to,
ax25_get_pid(pp), info_len,
tm->tm_hour, tm->tm_min, tm->tm_sec,
pinfo);
}
agwpe_msg.hdr.data_len_NETLE = host2netle(strlen(agwpe_msg.data) + 1) /* include null */ ;
agwpe_msg.hdr.data_len_NETLE = host2netle(strlen(agwpe_msg.data) + 1) /* +1 to include terminating null */ ;
if (debug_client) {
debug_print (TO_CLIENT, client, &agwpe_msg.hdr, sizeof(agwpe_msg.hdr) + netle2host(agwpe_msg.hdr.data_len_NETLE));
@ -1383,10 +1416,14 @@ static THREAD_F cmd_listen_thread (void *arg)
break;
case 'H': /* Ask about recently heard stations. */
case 'H': /* Ask about recently heard stations on given port. */
/* This should send back 20 'H' frames for the most recently heard stations. */
/* If there are less available, empty frames are sent to make a total of 20. */
/* Each contains the first and last heard times. */
{
#if 0 /* This information is not being collected. */
#if 0 /* Currently, this information is not being collected. */
struct {
struct agwpe_s hdr;
char info[100];
@ -1400,7 +1437,8 @@ static THREAD_F cmd_listen_thread (void *arg)
reply.hdr.portx = cmd.hdr.portx
strlcpy (reply.hdr.call_from, "WB2OSZ-15", sizeof(reply.hdr.call_from));
strlcpy (reply.hdr.call_from, "WB2OSZ-15 Mon,01Jan2000 01:02:03 Tue,31Dec2099 23:45:56", sizeof(reply.hdr.call_from));
// or 00:00:00 00:00:00
strlcpy (agwpe_msg.data, ..., sizeof(agwpe_msg.data));
@ -1640,6 +1678,7 @@ static THREAD_F cmd_listen_thread (void *arg)
#if NEW14
dlq_connect_request (callsigns, num_calls, cmd.hdr.portx, client, pid);
#else
(void)pid; // suppress unused variable message.
text_color_set(DW_COLOR_ERROR);
dw_printf ("\n");
dw_printf ("Can't process command '%c' from AGW client app %d.\n", cmd.hdr.datakind, client);
@ -1660,6 +1699,7 @@ static THREAD_F cmd_listen_thread (void *arg)
#if NEW14
dlq_xmit_data_request (callsigns, num_calls, cmd.hdr.portx, client, cmd.hdr.pid, cmd.data, netle2host(cmd.hdr.data_len_NETLE));
#else
(void)num_calls; // suppress unused variable warning.
text_color_set(DW_COLOR_ERROR);
dw_printf ("\n");
dw_printf ("Can't process command '%c' from AGW client app %d.\n", cmd.hdr.datakind, client);
@ -1679,6 +1719,7 @@ static THREAD_F cmd_listen_thread (void *arg)
#if NEW14
dlq_disconnect_request (callsigns, num_calls, cmd.hdr.portx, client);
#else
(void)num_calls; // suppress unused variable warning.
text_color_set(DW_COLOR_ERROR);
dw_printf ("\n");
dw_printf ("Can't process command '%c' from AGW client app %d.\n", cmd.hdr.datakind, client);

View File

@ -1,4 +1,4 @@
APRS SYMBOL OVERLAY and EXTENSION TABLES in APRS 1.2 29 Oct 2015
APRS SYMBOL OVERLAY and EXTENSION TABLES in APRS 1.2 22 Mar 2016
---------------------------------------------------------------------
BACKGROUND: This file addresses new additions proposals (OVERLAYS)
@ -7,7 +7,11 @@ document remains on the www.aprs.org/symbols/symbolsX.txt page, but
only has one line per symbol character. Since each of the symbols
can have up to 36 overlays, this gives us thousands of symbols codes.
22 Mar 2016: Added A0 overlay circle for ALSTAR nodes
and V0 for VOIP combined echolink and IRLP
and P& for PSKmail node
and W& for Wirese-X as opposed to W0 for WiresII
and Ya for Yaesu C4FM repeaters
Update 29 Oct 2015: Reorgainized list to Alphabetical Order.
+ Added many new Balloons (due to lost DoD radar Blimp yesterday)
+ Confirmed D^ for Drones was already in there since 2014
@ -164,6 +168,7 @@ Ga = RSGB Radio Society of Great Brittan
Ra = RACES
Sa = SATERN Salvation Army
Wa = WinLink
Ya = C4FM Yaesu repeaters
BALLOONS and lighter than air #O (All new Oct 2015)
/O = Original Balloon (think Ham balloon)
@ -240,7 +245,9 @@ GATEWAYS: #&
/& = HF Gateway <= the original primary table definition
I& = Igate Generic (please use more specific overlay)
R& = Receive only IGate (do not send msgs back to RF)
P& = PSKmail node
T& = TX igate with path set to 1 hop only)
W& = WIRES-X as opposed to W0 for WiresII
2& = TX igate with path set to 2 hops (not generally good idea)
GPS devices: #\
@ -287,9 +294,11 @@ P' = Pileup
T' = Truck wreck
NUMBERED CIRCLES: #0
A0 = Allstar Node (A0)
E0 = Echolink Node (E0)
I0 = IRLP repeater (I0)
S0 = Staging Area (S0)
V0 = Echolink and IRLP (VOIP)
W0 = WIRES (Yaesu VOIP)
NETWORK NODES: #8

View File

@ -26,22 +26,19 @@
*
*------------------------------------------------------------------*/
#include "direwolf.h"
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "direwolf.h"
#include "textcolor.h"
#include "symbols.h"
#include "tt_text.h"
//#if __WIN32__
char *strcasestr(const char *S, const char *FIND);
//#endif
/*
* APRS symbol tables.
*

View File

@ -25,10 +25,10 @@
#if TEST
#define DEBUG1 1
#define DEBUG2 1
#define DEBUG3 1
#define DEBUG4 1
#define DEBUG1 1 // Activate debug out when testing.
#define DEBUG2 1 //
#define DEBUG3 1 //
#define DEBUG4 1 //
#endif
@ -49,6 +49,8 @@
*
*---------------------------------------------------------------*/
#include "direwolf.h"
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
@ -57,7 +59,6 @@
#include <math.h>
#include <ctype.h>
#include "direwolf.h"
#include "ax25_pad.h" // for packet_t, AX25_MAX_ADDR_LEN
#include "decode_aprs.h" // for decode_aprs_t, G_UNKNOWN
#include "textcolor.h"

View File

@ -74,6 +74,8 @@
*--------------------------------------------------------------------*/
#include "direwolf.h" // Should be first. includes windows.h
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
@ -81,8 +83,6 @@
#if __WIN32__
#include <windows.h>
#define BACKGROUND_WHITE (BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_INTENSITY)

View File

@ -1,6 +1,8 @@
APRS TO-CALL VERSION NUMBERS 21 Jan 2016
APRS TO-CALL VERSION NUMBERS 29 Apr 2016
-------------------------------------------------------------------
WB4APR
29 Apr 16 added APFPRS for FreeDV by Jeroen PE1RXQ
25 Feb 16 Added APCDS0 for Leon Lessing ZS6LMG's cell tracker
21 Jan 16 added APDNOx for APRSduino by DO3SWW
18 Nov 15 Added APSTPO for N0AGI
03 Nov 15 Updated APAND1 and APDRxx for androids
@ -76,6 +78,7 @@ a TOCALL number series:
APF APFxxx Firenet
APFGxx Flood Gage (KP4DJT)
APFIxx for APRS.FI OH7LZB, Hessu
APFPRS for FreeDV by Jeroen PE1RXQ
APG APGxxx Gates, etc
APGOxx for AA3NJ PDA application
APH APHKxx for LA1BR tracker/digipeater

3
tq.c
View File

@ -35,13 +35,14 @@
*
*---------------------------------------------------------------*/
#include "direwolf.h"
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include "direwolf.h"
#include "ax25_pad.h"
#include "textcolor.h"
#include "audio.h"

View File

@ -154,6 +154,7 @@ static const char grid[10][10][3] =
{ "PH", "QH", "OG", "PG", "QG", "OF", "PF", "QF", "RF", "RE" }, // 8 - Aus / NZ
{ "IL", "IK", "IJ", "JJ", "JI", "JH", "JG", "KG", "JF", "KF" } }; // 9 - Africa
#include "direwolf.h"
#include <stdlib.h>
#include <stdio.h>
@ -162,7 +163,6 @@ static const char grid[10][10][3] =
#include <assert.h>
#include <stdarg.h>
#include "direwolf.h"
#include "textcolor.h"
#include "tt_text.h"

View File

@ -34,6 +34,8 @@
*
*---------------------------------------------------------------*/
#include "direwolf.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
@ -42,7 +44,6 @@
#include <time.h>
#include <assert.h>
#include "direwolf.h"
#include "version.h"
#include "ax25_pad.h"
#include "textcolor.h"

View File

@ -45,12 +45,12 @@
*---------------------------------------------------------------*/
#include "direwolf.h" // Sets _WIN32_WINNT for XP API level needed by ws2tcpip.h
#if __WIN32__
#include <winsock2.h>
#undef _WIN32_WINNT
#define _WIN32_WINNT 0x0501 /* Minimum OS version is XP. */
#include <ws2tcpip.h>
#include <ws2tcpip.h> // _WIN32_WINNT must be set to 0x0501 before including this
#else
#include <stdlib.h>
#include <netdb.h>

View File

@ -1,5 +1,6 @@
/* UTM to Latitude / Longitude conversion */
#include "direwolf.h"
#include <stdio.h>
#include <stdlib.h>
@ -7,7 +8,6 @@
#include <string.h>
#include <ctype.h>
#include "direwolf.h"
#include "utm.h"
#include "mgrs.h"
#include "usng.h"

View File

@ -30,6 +30,8 @@
*
*---------------------------------------------------------------*/
#include "direwolf.h"
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
@ -37,7 +39,6 @@
#include <string.h>
#include <math.h>
#include "direwolf.h"
#include "config.h"
#include "ax25_pad.h"
#include "textcolor.h"

View File

@ -29,12 +29,15 @@
*
*---------------------------------------------------------------*/
#include "direwolf.h" // should be first
#include <stdio.h>
#include <unistd.h>
#if __WIN32__
#include <stdlib.h>
#include <windows.h>
#else
#define __USE_XOPEN2KXSI 1
#define __USE_XOPEN 1
@ -48,7 +51,7 @@
#include <string.h>
#include <time.h>
#include "direwolf.h"
#include "config.h"
#include "textcolor.h"
#include "latlong.h"
@ -443,7 +446,7 @@ void waypoint_send_sentence (char *name_in, double dlat, double dlong, char symt
* GPS Status A = active, V = void.
* It looks like this might be modeled after the GPS status values
* we see in $GPRMC. i.e. Does the transceiver know its location?
* I dont see how that information would be relevant in this context.
* I don't see how that information would be relevant in this context.
* I've observed this under various conditions (No GPS, GPS with/without
* fix) and it has always been "V."
* (There is some information out there indicating this field
@ -524,7 +527,7 @@ void waypoint_send_sentence (char *name_in, double dlat, double dlong, char symt
char ken_sym; /* APRS symbol with , or * substituted. */
now = time(NULL);
gmtime_r (&now, &tm);
(void)gmtime_r (&now, &tm);
strftime (stime, sizeof(stime), "%H%M%S", &tm);
strftime (sdate, sizeof(sdate), "%d%m%y", &tm);

2
xid.c
View File

@ -44,12 +44,12 @@
*
*---------------------------------------------------------------*/
#include "direwolf.h"
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "direwolf.h"
#include "textcolor.h"
//#include "xid.h"

7
xmit.c
View File

@ -51,6 +51,8 @@
*
*---------------------------------------------------------------*/
#include "direwolf.h"
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
@ -615,6 +617,7 @@ static void xmit_ax25_frames (int c, int p, packet_t pp)
int ns;
ftype = ax25_frame_type (pp, &cr, desc, &pf, &nr, &ns);
(void)ftype;
dw_printf ("(%s)", desc);
}
@ -821,6 +824,8 @@ static void xmit_speech (int c, packet_t pp)
*/
info_len = ax25_get_info (pp, &pinfo);
(void)info_len;
text_color_set(DW_COLOR_XMIT);
dw_printf ("[%d.speech] \"%s\"\n", c, pinfo);
@ -891,6 +896,7 @@ int xmit_speak_it (char *script, int c, char *orig_msg)
dw_printf ("Failed to run text-to-speech script, %s\n", script);
ignore = getcwd (cwd, sizeof(cwd));
(void)ignore;
strlcpy (path, getenv("PATH"), sizeof(path));
dw_printf ("CWD = %s\n", cwd);
@ -933,6 +939,7 @@ static void xmit_morse (int c, packet_t pp, int wpm)
info_len = ax25_get_info (pp, &pinfo);
(void)info_len;
text_color_set(DW_COLOR_XMIT);
dw_printf ("[%d.morse] \"%s\"\n", c, pinfo);