diff --git a/CHANGES.md b/CHANGES.md index 65279ef..e1a7bdc 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -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: ### diff --git a/Makefile.linux b/Makefile.linux index e32be77..40498e3 100644 --- a/Makefile.linux +++ b/Makefile.linux @@ -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 diff --git a/Makefile.macosx b/Makefile.macosx index ced3b20..c77c9cf 100644 --- a/Makefile.macosx +++ b/Makefile.macosx @@ -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 diff --git a/Makefile.win b/Makefile.win index 5007702..24fa6ff 100644 --- a/Makefile.win +++ b/Makefile.win @@ -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. diff --git a/README.md b/README.md index 451b043..dc70652 100644 --- a/README.md +++ b/README.md @@ -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. diff --git a/aclients.c b/aclients.c index fe5e93c..1561e1f 100644 --- a/aclients.c +++ b/aclients.c @@ -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 -// default is 0x0400 -#undef _WIN32_WINNT -#define _WIN32_WINNT 0x0501 /* Minimum OS version is XP. */ -#include +#include // _WIN32_WINNT must be set to 0x0501 before including this + #else //#define __USE_XOPEN2KXSI 1 //#define __USE_XOPEN 1 @@ -83,7 +82,6 @@ #include -#include "direwolf.h" #include "ax25_pad.h" #include "textcolor.h" #include "version.h" diff --git a/aprs_tt.c b/aprs_tt.c index 6642cef..513095f 100644 --- a/aprs_tt.c +++ b/aprs_tt.c @@ -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 #include -#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 /*------------------------------------------------------------------ diff --git a/atest.c b/atest.c index e3d47b6..a97ef22 100644 --- a/atest.c +++ b/atest.c @@ -59,6 +59,7 @@ // #define X 1 +#include "direwolf.h" #include #include @@ -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,12 +505,16 @@ 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); diff --git a/audio.c b/audio.c index 84aa854..667f8b1 100644 --- a/audio.c +++ b/audio.c @@ -60,6 +60,7 @@ * *---------------------------------------------------------------*/ +#include "direwolf.h" #include #include @@ -88,7 +89,6 @@ #endif -#include "direwolf.h" #include "audio.h" #include "audio_stats.h" #include "textcolor.h" diff --git a/audio_portaudio.c b/audio_portaudio.c index ead1ffc..6d53f6a 100644 --- a/audio_portaudio.c +++ b/audio_portaudio.c @@ -37,6 +37,8 @@ #if defined(USE_PORTAUDIO) +#include "direwolf.h" + #include #include #include @@ -54,7 +56,6 @@ #include #include -#include "direwolf.h" #include "audio.h" #include "audio_stats.h" #include "textcolor.h" diff --git a/audio_stats.c b/audio_stats.c index 9c67769..b6549ca 100644 --- a/audio_stats.c +++ b/audio_stats.c @@ -50,6 +50,9 @@ *---------------------------------------------------------------*/ +#include "direwolf.h" + + #include #include #include @@ -57,8 +60,9 @@ #include #include #include +#include + -#include "direwolf.h" #include "audio_stats.h" #include "textcolor.h" #include "dtime_now.h" diff --git a/audio_win.c b/audio_win.c index f431363..432f554 100644 --- a/audio_win.c +++ b/audio_win.c @@ -39,6 +39,10 @@ *---------------------------------------------------------------*/ +#include "direwolf.h" // Sets _WIN32_WINNT for XP API level needed by ws2tcpip.h + // Also includes windows.h. + + #include #include #include @@ -48,7 +52,6 @@ #include #include -#include #include #ifndef WAVE_FORMAT_96M16 @@ -57,11 +60,9 @@ #endif #include -#define _WIN32_WINNT 0x0501 -#include +#include // _WIN32_WINNT must be set to 0x0501 before including this -#include "direwolf.h" #include "audio.h" #include "audio_stats.h" #include "textcolor.h" diff --git a/ax25_pad.c b/ax25_pad.c index 90fba0b..2b15428 100644 --- a/ax25_pad.c +++ b/ax25_pad.c @@ -146,6 +146,7 @@ #define AX25_PAD_C /* this will affect behavior of ax25_pad.h */ +#include "direwolf.h" #include #include @@ -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" diff --git a/ax25_pad.h b/ax25_pad.h index a579a83..2426e56 100644 --- a/ax25_pad.h +++ b/ax25_pad.h @@ -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; diff --git a/ax25_pad2.c b/ax25_pad2.c index 60e0f1b..43e2d83 100644 --- a/ax25_pad2.c +++ b/ax25_pad2.c @@ -136,6 +136,8 @@ #define AX25_PAD_C /* this will affect behavior of ax25_pad.h */ +#include "direwolf.h" + #include #include #include @@ -143,9 +145,7 @@ #include -#include "direwolf.h" #include "textcolor.h" - #include "ax25_pad.h" #include "ax25_pad2.h" diff --git a/beacon.c b/beacon.c index 9837676..1d0ca49 100644 --- a/beacon.c +++ b/beacon.c @@ -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 #include @@ -40,7 +42,6 @@ #include -#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), "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; diff --git a/beacon.h b/beacon.h index 1dce32b..f7d2a56 100644 --- a/beacon.h +++ b/beacon.h @@ -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); diff --git a/config.c b/config.c index a1bd076..e358b14 100644 --- a/config.c +++ b/config.c @@ -17,7 +17,7 @@ // along with this program. If not, see . // -#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 #include #include @@ -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); diff --git a/config.h b/config.h index acfb47a..1b3c602 100644 --- a/config.h +++ b/config.h @@ -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 }; diff --git a/decode_aprs.c b/decode_aprs.c index 075fc72..3684234 100644 --- a/decode_aprs.c +++ b/decode_aprs.c @@ -33,6 +33,8 @@ * *------------------------------------------------------------------*/ +#include "direwolf.h" + #include #include #include @@ -48,7 +50,6 @@ #endif #include "regex.h" -#include "direwolf.h" #include "ax25_pad.h" #include "textcolor.h" #include "symbols.h" diff --git a/dedupe.c b/dedupe.c index 66a035f..cb012eb 100644 --- a/dedupe.c +++ b/dedupe.c @@ -96,6 +96,7 @@ #define DEDUPE_C +#include "direwolf.h" #include #include diff --git a/demod.c b/demod.c index bdea694..8daf6d9 100644 --- a/demod.c +++ b/demod.c @@ -31,6 +31,7 @@ * *---------------------------------------------------------------*/ +#include "direwolf.h" #include #include @@ -41,7 +42,6 @@ #include #include -#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) { @@ -919,51 +931,51 @@ void demod_process_sample (int chan, int subchan, int sam) case MODEM_BASEBAND: 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 #include #include @@ -42,7 +44,6 @@ #include #include -#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; jnum_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 @@ -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; slicenum_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 */ diff --git a/demod_afsk.c b/demod_afsk.c index dba8317..96d9e45 100644 --- a/demod_afsk.c +++ b/demod_afsk.c @@ -39,7 +39,7 @@ * *---------------------------------------------------------------*/ - +#include "direwolf.h" #include #include @@ -50,9 +50,7 @@ #include #include -#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 #include @@ -105,9 +105,8 @@ #include #include -#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); diff --git a/digipeater.c b/digipeater.c index 7e90d91..817032b 100644 --- a/digipeater.c +++ b/digipeater.c @@ -53,6 +53,7 @@ #define DIGIPEATER_C +#include "direwolf.h" #include #include @@ -62,7 +63,6 @@ #include "regex.h" #include -#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? */ diff --git a/digipeater.h b/digipeater.h index d1b26b8..d1ad3b6 100644 --- a/digipeater.h +++ b/digipeater.h @@ -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 */ diff --git a/direwolf.c b/direwolf.c index 280acba..5be1b58 100644 --- a/direwolf.c +++ b/direwolf.c @@ -35,6 +35,13 @@ * *---------------------------------------------------------------*/ + +#define DIREWOLF_C 1 + +#include "direwolf.h" + + + #include #include #include @@ -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"); diff --git a/direwolf.h b/direwolf.h index 958e093..c584664 100644 --- a/direwolf.h +++ b/direwolf.h @@ -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 ". + * + * 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 + +#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 #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__) diff --git a/dlq.c b/dlq.c index 5f01ff9..3d0a2c9 100644 --- a/dlq.c +++ b/dlq.c @@ -37,6 +37,8 @@ * *---------------------------------------------------------------*/ +#include "direwolf.h" + #include #include #include @@ -47,7 +49,6 @@ #include #endif -#include "direwolf.h" #include "ax25_pad.h" #include "textcolor.h" #include "audio.h" diff --git a/doc/Going-beyond-9600-baud.pdf b/doc/Going-beyond-9600-baud.pdf index b4ecea2..2996aec 100644 Binary files a/doc/Going-beyond-9600-baud.pdf and b/doc/Going-beyond-9600-baud.pdf differ diff --git a/doc/User-Guide.pdf b/doc/User-Guide.pdf index 8f3f765..412c310 100644 Binary files a/doc/User-Guide.pdf and b/doc/User-Guide.pdf differ diff --git a/dsp.c b/dsp.c index f2a4343..fa16305 100644 --- a/dsp.c +++ b/dsp.c @@ -26,6 +26,8 @@ * *----------------------------------------------------------------*/ +#include "direwolf.h" + #include #include #include @@ -34,7 +36,6 @@ #include #include -#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 diff --git a/dtmf.c b/dtmf.c index 3479244..c4270f7 100644 --- a/dtmf.c +++ b/dtmf.c @@ -34,13 +34,13 @@ * *---------------------------------------------------------------*/ +#include "direwolf.h" #include #include #include #include -#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 diff --git a/dwgps.c b/dwgps.c index f8cc37e..83e9244 100644 --- a/dwgps.c +++ b/dwgps.c @@ -48,13 +48,14 @@ * *---------------------------------------------------------------*/ +#include "direwolf.h" + #include #include #include #include #include -#include "direwolf.h" #include "textcolor.h" #include "dwgps.h" #include "dwgpsnmea.h" diff --git a/dwgpsd.c b/dwgpsd.c index 37688ff..900f26e 100644 --- a/dwgpsd.c +++ b/dwgpsd.c @@ -34,6 +34,9 @@ *---------------------------------------------------------------*/ +#include "direwolf.h" + + #include #include #include @@ -60,7 +63,6 @@ #endif -#include "direwolf.h" #include "textcolor.h" #include "dwgps.h" #include "dwgpsd.h" diff --git a/dwgpsnmea.c b/dwgpsnmea.c index 93de1ed..fc53575 100644 --- a/dwgpsnmea.c +++ b/dwgpsnmea.c @@ -29,6 +29,9 @@ *---------------------------------------------------------------*/ +#include "direwolf.h" + + #include #include #include @@ -38,7 +41,6 @@ #include -#include "direwolf.h" #include "textcolor.h" #include "dwgps.h" #include "dwgpsnmea.h" diff --git a/encode_aprs.c b/encode_aprs.c index 67476f4..a2afff6 100644 --- a/encode_aprs.c +++ b/encode_aprs.c @@ -33,6 +33,8 @@ * *---------------------------------------------------------------*/ +#include "direwolf.h" + #include #include #include @@ -42,7 +44,6 @@ #include #include -#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. */ diff --git a/fcs_calc.c b/fcs_calc.c index eff88d3..97e34a5 100644 --- a/fcs_calc.c +++ b/fcs_calc.c @@ -18,6 +18,8 @@ // +#include "direwolf.h" + #include /* diff --git a/fsk_demod_state.h b/fsk_demod_state.h index 85b970a..a37b24d 100644 --- a/fsk_demod_state.h +++ b/fsk_demod_state.h @@ -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. */ diff --git a/gen_packets.c b/gen_packets.c index bee4de8..13ad6e2 100644 --- a/gen_packets.c +++ b/gen_packets.c @@ -60,7 +60,7 @@ *------------------------------------------------------------------*/ - +#include "direwolf.h" #include #include @@ -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 Audio sample Rate. Default is %d.\n", DEFAULT_SAMPLES_PER_SEC); dw_printf (" -n Generate specified number of frames with increasing noise.\n"); dw_printf (" -o 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 of leading zero bits before frame.\n"); // dw_printf (" Default is 12 which is .01 seconds at 1200 bits/sec.\n"); diff --git a/gen_tone.c b/gen_tone.c index d81a669..0d7c255 100644 --- a/gen_tone.c +++ b/gen_tone.c @@ -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 #include #include @@ -35,7 +41,7 @@ #include #include -#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,10 +194,16 @@ 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 { - - float fsam = dat ? amp16bit : (-amp16bit); + case MODEM_AFSK: - /* 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); + } } } } diff --git a/gen_tone.h b/gen_tone.h index 1937c4a..bbe23b5 100644 --- a/gen_tone.h +++ b/gen_tone.h @@ -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); diff --git a/hdlc_rec.c b/hdlc_rec.c index 06d1c4b..975f353 100644 --- a/hdlc_rec.c +++ b/hdlc_rec.c @@ -27,11 +27,12 @@ * *******************************************************************************/ +#include "direwolf.h" + #include #include #include -#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) { diff --git a/hdlc_rec2.c b/hdlc_rec2.c index 374fa98..8b970d3 100644 --- a/hdlc_rec2.c +++ b/hdlc_rec2.c @@ -84,13 +84,15 @@ * *******************************************************************************/ +#include "direwolf.h" + #include #include #include +#include //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); /* diff --git a/hdlc_send.c b/hdlc_send.c index 3511488..fd43c43 100644 --- a/hdlc_send.c +++ b/hdlc_send.c @@ -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 . // +#include "direwolf.h" #include -#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]++; } diff --git a/igate.c b/igate.c index 16041b6..14a54b7 100644 --- a/igate.c +++ b/igate.c @@ -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 -// 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 +#include // _WIN32_WINNT must be set to 0x0501 before including this + #else #include #include @@ -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: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; diff --git a/igate.h b/igate.h index 3e2d003..369d01e 100644 --- a/igate.h +++ b/igate.h @@ -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 diff --git a/kiss.c b/kiss.c index a9e6f60..f0d7434 100644 --- a/kiss.c +++ b/kiss.c @@ -112,12 +112,13 @@ * *---------------------------------------------------------------*/ +#include "direwolf.h" + #include #include #if __WIN32__ #include -#include #else #define __USE_XOPEN2KXSI 1 #define __USE_XOPEN 1 @@ -138,7 +139,7 @@ #include #include -#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__ diff --git a/kiss_frame.c b/kiss_frame.c index f988412..3e9c45a 100644 --- a/kiss_frame.c +++ b/kiss_frame.c @@ -68,6 +68,8 @@ * *---------------------------------------------------------------*/ +#include "direwolf.h" + #include #include #include @@ -75,7 +77,6 @@ #include #include -#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]; diff --git a/kissnet.c b/kissnet.c index e377657..6aeaa71 100644 --- a/kissnet.c +++ b/kissnet.c @@ -95,10 +95,12 @@ */ +#include "direwolf.h" // Sets _WIN32_WINNT for XP API level needed by ws2tcpip.h + + #if __WIN32__ #include -#define _WIN32_WINNT 0x0501 -#include +#include // _WIN32_WINNT must be set to 0x0501 before including this #else #include #include @@ -115,11 +117,9 @@ #include #include #include - #include -#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 */ diff --git a/latlong.c b/latlong.c index c984ef1..8e3a999 100644 --- a/latlong.c +++ b/latlong.c @@ -30,6 +30,7 @@ * *---------------------------------------------------------------*/ +#include "direwolf.h" #include #include @@ -40,7 +41,6 @@ #include #include -#include "direwolf.h" #include "latlong.h" #include "textcolor.h" diff --git a/ll2utm.c b/ll2utm.c index 3ff663d..e06cd56 100644 --- a/ll2utm.c +++ b/ll2utm.c @@ -1,5 +1,7 @@ /* Latitude / Longitude to UTM conversion */ +#include "direwolf.h" + #include #include #include diff --git a/log.c b/log.c index f5448e7..c466677 100644 --- a/log.c +++ b/log.c @@ -31,6 +31,8 @@ * *------------------------------------------------------------------*/ +#include "direwolf.h" + #include #include #include @@ -42,8 +44,6 @@ #include #include - -#include "direwolf.h" #include "ax25_pad.h" #include "textcolor.h" #include "decode_aprs.h" diff --git a/log2gpx.c b/log2gpx.c index c8f47e0..15b9835 100644 --- a/log2gpx.c +++ b/log2gpx.c @@ -18,17 +18,12 @@ // along with this program. If not, see . // +#include "direwolf.h" #include #include #include -#if __WIN32__ -char *strsep(char **stringp, const char *delim); -#endif - -#include "direwolf.h" - /* * Information we gather for each thing. diff --git a/mheard.c b/mheard.c new file mode 100644 index 0000000..2d498d8 --- /dev/null +++ b/mheard.c @@ -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 . +// + + +/*------------------------------------------------------------------ + * + * 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 +#include +#include +#include +#include +#include + +#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: + * + * 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 */ diff --git a/mheard.h b/mheard.h new file mode 100644 index 0000000..e4ab9bf --- /dev/null +++ b/mheard.h @@ -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); \ No newline at end of file diff --git a/morse.c b/morse.c index 8598fcc..1319501 100644 --- a/morse.c +++ b/morse.c @@ -30,6 +30,8 @@ * *---------------------------------------------------------------*/ +#include "direwolf.h" + #include #include #include @@ -39,8 +41,6 @@ #include #include - -#include "direwolf.h" #include "textcolor.h" #include "audio.h" #include "ptt.h" diff --git a/multi_modem.c b/multi_modem.c index e1d9f55..851f6d9 100644 --- a/multi_modem.c +++ b/multi_modem.c @@ -74,6 +74,7 @@ //#define DEBUG 1 #define DIGIPEATER_C +#include "direwolf.h" #include #include @@ -81,7 +82,6 @@ #include #include -#include "direwolf.h" #include "ax25_pad.h" #include "textcolor.h" #include "multi_modem.h" diff --git a/pfilter.c b/pfilter.c index 3305949..761ca5d 100644 --- a/pfilter.c +++ b/pfilter.c @@ -37,6 +37,7 @@ * *---------------------------------------------------------------*/ +#include "direwolf.h" #include #include @@ -45,11 +46,6 @@ #include #include -#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); diff --git a/pfilter.h b/pfilter.h index 1171280..ba4dcee 100644 --- a/pfilter.h +++ b/pfilter.h @@ -1,4 +1,6 @@ /* pfilter.h */ -int pfilter (int from_chan, int to_chan, char *filter, packet_t pp); \ No newline at end of file +int pfilter (int from_chan, int to_chan, char *filter, packet_t pp); + +int is_telem_metadata (char *infop); \ No newline at end of file diff --git a/ptt.c b/ptt.c index 749ada6..6369f31 100644 --- a/ptt.c +++ b/ptt.c @@ -94,6 +94,9 @@ Maybe even for Windows. ;-) */ + +#include "direwolf.h" // should be first. This includes windows.h. + #include #include #include @@ -102,7 +105,6 @@ #include #if __WIN32__ -#include #else #include #include @@ -122,7 +124,6 @@ typedef int HANDLE; #endif -#include "direwolf.h" #include "textcolor.h" #include "audio.h" #include "ptt.h" diff --git a/rdq.c b/rdq.c index cbfc2cf..565fee6 100644 --- a/rdq.c +++ b/rdq.c @@ -29,13 +29,14 @@ * *---------------------------------------------------------------*/ +#include "direwolf.h" + #include #include #include #include #include -#include "direwolf.h" #include "ax25_pad.h" #include "textcolor.h" #include "audio.h" diff --git a/recv.c b/recv.c index 05c90b7..85bf147 100644 --- a/recv.c +++ b/recv.c @@ -82,6 +82,7 @@ //#define DEBUG 1 +#include "direwolf.h" #include #include @@ -97,7 +98,6 @@ #include #endif -#include "direwolf.h" #include "audio.h" #include "demod.h" #include "multi_modem.h" diff --git a/redecode.c b/redecode.c deleted file mode 100644 index 7c779ad..0000000 --- a/redecode.c +++ /dev/null @@ -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 . -// - - -/*------------------------------------------------------------------ - * - * 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 -#include -#include -#include -#include - -#include - -#if __WIN32__ -#include -#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 */ - - - diff --git a/rrbb.c b/rrbb.c index 5651de7..82d8aae 100644 --- a/rrbb.c +++ b/rrbb.c @@ -35,12 +35,13 @@ #define RRBB_C +#include "direwolf.h" + #include #include #include #include -#include "direwolf.h" #include "textcolor.h" #include "ax25_pad.h" #include "rrbb.h" diff --git a/serial_port.c b/serial_port.c index 2a71010..f125178 100644 --- a/serial_port.c +++ b/serial_port.c @@ -34,12 +34,13 @@ * *---------------------------------------------------------------*/ +#include "direwolf.h" // should be first + #include #if __WIN32__ #include -#include #else @@ -58,7 +59,7 @@ #include #include -#include "direwolf.h" + #include "textcolor.h" #include "serial_port.h" diff --git a/serial_port.h b/serial_port.h index 05ee072..8a65a0b 100644 --- a/serial_port.h +++ b/serial_port.h @@ -8,7 +8,6 @@ #if __WIN32__ #include -#include typedef HANDLE MYFDTYPE; #define MYFDERROR INVALID_HANDLE_VALUE diff --git a/server.c b/server.c index f4cf5d7..59df2a9 100644 --- a/server.c +++ b/server.c @@ -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 -#define _WIN32_WINNT 0x0501 -#include +#include // _WIN32_WINNT must be set to 0x0501 before including this #else #include #include @@ -146,7 +146,6 @@ #include #include -#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 [%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 [%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 [%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); diff --git a/symbols-new.txt b/symbols-new.txt index d9f50b4..57646a3 100644 --- a/symbols-new.txt +++ b/symbols-new.txt @@ -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 diff --git a/symbols.c b/symbols.c index e4d51af..a0592f1 100644 --- a/symbols.c +++ b/symbols.c @@ -26,22 +26,19 @@ * *------------------------------------------------------------------*/ +#include "direwolf.h" + #include #include #include #include #include -#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. * diff --git a/telemetry.c b/telemetry.c index 68cd585..711f3d1 100644 --- a/telemetry.c +++ b/telemetry.c @@ -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 #include #include @@ -57,7 +59,6 @@ #include #include -#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" diff --git a/textcolor.c b/textcolor.c index 90b55e3..e0d2f31 100644 --- a/textcolor.c +++ b/textcolor.c @@ -74,6 +74,8 @@ *--------------------------------------------------------------------*/ +#include "direwolf.h" // Should be first. includes windows.h + #include #include #include @@ -81,8 +83,6 @@ #if __WIN32__ -#include - #define BACKGROUND_WHITE (BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_INTENSITY) diff --git a/tocalls.txt b/tocalls.txt index ac44dfd..2e3e12d 100644 --- a/tocalls.txt +++ b/tocalls.txt @@ -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 diff --git a/tq.c b/tq.c index 88ad59e..f98518b 100644 --- a/tq.c +++ b/tq.c @@ -35,13 +35,14 @@ * *---------------------------------------------------------------*/ +#include "direwolf.h" + #include #include #include #include #include -#include "direwolf.h" #include "ax25_pad.h" #include "textcolor.h" #include "audio.h" diff --git a/tt_text.c b/tt_text.c index f2803f2..8cd7ba8 100644 --- a/tt_text.c +++ b/tt_text.c @@ -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 #include @@ -162,7 +163,6 @@ static const char grid[10][10][3] = #include #include -#include "direwolf.h" #include "textcolor.h" #include "tt_text.h" diff --git a/tt_user.c b/tt_user.c index 46aff3c..f6ce167 100644 --- a/tt_user.c +++ b/tt_user.c @@ -34,6 +34,8 @@ * *---------------------------------------------------------------*/ +#include "direwolf.h" + #include #include #include @@ -42,7 +44,6 @@ #include #include -#include "direwolf.h" #include "version.h" #include "ax25_pad.h" #include "textcolor.h" diff --git a/ttcalc.c b/ttcalc.c index 17538e3..e5303f5 100644 --- a/ttcalc.c +++ b/ttcalc.c @@ -45,12 +45,12 @@ *---------------------------------------------------------------*/ +#include "direwolf.h" // Sets _WIN32_WINNT for XP API level needed by ws2tcpip.h + #if __WIN32__ #include -#undef _WIN32_WINNT -#define _WIN32_WINNT 0x0501 /* Minimum OS version is XP. */ -#include +#include // _WIN32_WINNT must be set to 0x0501 before including this #else #include #include diff --git a/utm2ll.c b/utm2ll.c index e1d793c..89dc55e 100644 --- a/utm2ll.c +++ b/utm2ll.c @@ -1,5 +1,6 @@ /* UTM to Latitude / Longitude conversion */ +#include "direwolf.h" #include #include @@ -7,7 +8,6 @@ #include #include -#include "direwolf.h" #include "utm.h" #include "mgrs.h" #include "usng.h" diff --git a/walk96.c b/walk96.c index ef1c34c..dfad612 100644 --- a/walk96.c +++ b/walk96.c @@ -30,6 +30,8 @@ * *---------------------------------------------------------------*/ +#include "direwolf.h" + #include #include #include @@ -37,7 +39,6 @@ #include #include -#include "direwolf.h" #include "config.h" #include "ax25_pad.h" #include "textcolor.h" diff --git a/waypoint.c b/waypoint.c index 4025b9c..96123f7 100644 --- a/waypoint.c +++ b/waypoint.c @@ -29,12 +29,15 @@ * *---------------------------------------------------------------*/ + +#include "direwolf.h" // should be first + + #include #include #if __WIN32__ #include -#include #else #define __USE_XOPEN2KXSI 1 #define __USE_XOPEN 1 @@ -48,7 +51,7 @@ #include #include -#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 don’t 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); diff --git a/xid.c b/xid.c index 9db66f8..b0b1ca8 100644 --- a/xid.c +++ b/xid.c @@ -44,12 +44,12 @@ * *---------------------------------------------------------------*/ +#include "direwolf.h" #include #include #include -#include "direwolf.h" #include "textcolor.h" //#include "xid.h" diff --git a/xmit.c b/xmit.c index b80d844..6419ade 100644 --- a/xmit.c +++ b/xmit.c @@ -51,6 +51,8 @@ * *---------------------------------------------------------------*/ +#include "direwolf.h" + #include #include #include @@ -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);