From c491655edb68615ca49ec87b2ed06abec7ba9a7b Mon Sep 17 00:00:00 2001 From: "David E. Tiller" <3858971+dtiller@users.noreply.github.com> Date: Fri, 18 Mar 2022 20:33:59 -0400 Subject: [PATCH] More framework. --- src/CMakeLists.txt | 2 ++ src/eotd.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++ src/eotd.h | 1 + src/hdlc_rec.c | 62 +++++++++++++++++++++++++++++++++++++++-- src/multi_modem.c | 8 ++++++ 5 files changed, 140 insertions(+), 2 deletions(-) create mode 100644 src/eotd.c create mode 100644 src/eotd.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 46d3ac7..7afa21e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -85,6 +85,7 @@ list(APPEND direwolf_SOURCES dwgpsnmea.c dwgpsd.c mheard.c + eotd.c ) if(LINUX) @@ -317,6 +318,7 @@ list(APPEND atest_SOURCES symbols.c tt_text.c textcolor.c + eotd.c ) if(WIN32 OR CYGWIN) diff --git a/src/eotd.c b/src/eotd.c new file mode 100644 index 0000000..91f0110 --- /dev/null +++ b/src/eotd.c @@ -0,0 +1,69 @@ + +// This file is part of Dire Wolf, an amateur radio packet TNC. +// +// Copyright (C) 2022 David Tiller, K4DET +// +// 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: eotd.c + * + * Purpose: Functions for processing received EOTD transmissions and + * converting to NMEA sentence representation. + * + * References: AIVDM/AIVDO protocol decoding by Eric S. Raymond + * https://gpsd.gitlab.io/gpsd/AIVDM.html + * + * Sample recording with about 100 messages. Test with "atest -B AIS xxx.wav" + * https://github.com/freerange/ais-on-sdr/wiki/example-data/long-beach-160-messages.wav + * + * Useful on-line decoder for AIS NMEA sentences. + * https://www.aggsoft.com/ais-decoder.htm + * + * Future? Add an interface to feed AIS data into aprs.fi. + * https://aprs.fi/page/ais_feeding + * + *******************************************************************************/ + +#include "direwolf.h" + +#include +#include +#include +#include +#include + +#include "textcolor.h" +#include "eotd.h" + +/*------------------------------------------------------------------- + * + * Convert EOTD binary block (from HDLC frame) to NMEA sentence. + * + * In: Pointer to EOTD binary block and number of bytes. + * Out: NMEA sentence. Provide size to avoid string overflow. + * + *--------------------------------------------------------------------*/ + +void eotd_to_nmea (unsigned char *eotd, int eotd_len, char *nmea, int nmea_size) +{ + for (int i = 0; i < eotd_len; i++) { + char temp[32]; + snprintf(temp, sizeof(temp), "%d=%02x ", i, eotd[i]); + strlcpy(nmea, temp, nmea_size); + } +} diff --git a/src/eotd.h b/src/eotd.h new file mode 100644 index 0000000..64dba3a --- /dev/null +++ b/src/eotd.h @@ -0,0 +1 @@ +void eotd_to_nmea (unsigned char *ais, int ais_len, char *nema, int nema_size); diff --git a/src/hdlc_rec.c b/src/hdlc_rec.c index 6db809c..85879e1 100644 --- a/src/hdlc_rec.c +++ b/src/hdlc_rec.c @@ -1,5 +1,5 @@ -// -// This file is part of Dire Wolf, an amateur radio packet TNC. +//// +//// This file is part of Dire Wolf, an amateur radio packet TNC. // // Copyright (C) 2011, 2012, 2013, 2014, 2015 John Langner, WB2OSZ // @@ -111,6 +111,10 @@ struct hdlc_state_s { int eas_plus_found; /* "+" seen, indicating end of geographical area list. */ int eas_fields_after_plus; /* Number of "-" characters after the "+". */ + + uint32_t eotd_acc; /* Accumulate last recent 32 bits for EOTD. */ + + int eotd_gathering; /* Decoding in progress - valid frame. */ }; static struct hdlc_state_s hdlc_state[MAX_CHANS][MAX_SUBCHANS][MAX_SLICERS]; @@ -423,6 +427,8 @@ a good modem here and providing a result when it is received. * ***********************************************************************************/ +#define PREAMBLE_AND_BARKER_CODE 0x55555712 +#define EOTD_MAX_LEN 8 static void eotd_rec_bit (int chan, int subchan, int slice, int raw, int future_use) { @@ -432,7 +438,59 @@ static void eotd_rec_bit (int chan, int subchan, int slice, int raw, int future_ * Different state information for each channel / subchannel / slice. */ H = &hdlc_state[chan][subchan][slice]; + fprintf(stderr, "chan=%d subchan=%d slice=%d raw=%d\n", chan, subchan, slice, raw); + //dw_printf ("slice %d = %d\n", slice, raw); + +// Accumulate most recent 32 bits in MSB-first order. + + H->eotd_acc <<= 1; + H->eotd_acc |= raw; + + int done = 0; + + if (!H->eotd_gathering && H->eotd_acc == PREAMBLE_AND_BARKER_CODE) { + dw_printf ("Barker Code Found\n"); + H->olen = 0; + H->eotd_gathering = 1; + H->frame_len = 0; + } + else if (H->eotd_gathering) { + H->olen++; + + /* Hack to skip 'dummy' 64th bit */ + if (H->olen == 7 && H->frame_len == 7) { +fprintf(stderr, "Special case!\n"); + H->eotd_acc <<= 1; + H->olen++; + } + + if (H->olen == 8) { + H->olen = 0; + char ch = H->eotd_acc & 0xff; + H->frame_buf[H->frame_len++] = ch; + H->frame_buf[H->frame_len] = '\0'; + //dw_printf ("frame_buf = %s\n", H->frame_buf); + + if (H->frame_len == EOTD_MAX_LEN) { // FIXME: look for other places with max length + done = 1; +for (int ii=0; ii < EOTD_MAX_LEN; ii++) {fprintf(stderr, "%02x ", H->frame_buf[ii]); } fprintf(stderr, "\n"); + } + } + } + + if (done) { +#ifdef DEBUG_E + dw_printf ("frame_buf %d = %s\n", slice, H->frame_buf); +#endif + alevel_t alevel = demod_get_audio_level (chan, subchan); + multi_modem_process_rec_frame (chan, subchan, slice, H->frame_buf, H->frame_len, alevel, 0, 0); + + H->eotd_acc = 0; + H->eotd_gathering = 0; + H->olen = 0; + H->frame_len = 0; + } return; } // end eotd_rec_bit diff --git a/src/multi_modem.c b/src/multi_modem.c index c59af07..86a59a7 100644 --- a/src/multi_modem.c +++ b/src/multi_modem.c @@ -103,6 +103,7 @@ #include "fx25.h" #include "version.h" #include "ais.h" +#include "eotd.h" @@ -342,6 +343,13 @@ void multi_modem_process_rec_frame (int chan, int subchan, int slice, unsigned c // alevel gets in there somehow making me question why it is passed thru here. } + else if (save_audio_config_p->achan[chan].modem_type == MODEM_EOTD) { + char nmea[300]; + eotd_to_nmea (fbuf, flen, nmea, sizeof(nmea)); + char monfmt[276]; + snprintf (monfmt, sizeof(monfmt), "EOTD>%s%1d%1d:{%c%c%s", APP_TOCALL, MAJOR_VERSION, MINOR_VERSION, USER_DEF_USER_ID, USER_DEF_TYPE_AIS, nmea); + pp = ax25_from_text (monfmt, 1); + } else { pp = ax25_from_frame (fbuf, flen, alevel); }