Add FEC type to station heard line.

This commit is contained in:
wb2osz 2023-09-11 00:07:36 +01:00
parent 7a8e4320ac
commit a08d0939b5
10 changed files with 80 additions and 59 deletions

View File

@ -757,7 +757,7 @@ int audio_get (int a)
* This is called when we have a good frame. * This is called when we have a good frame.
*/ */
void dlq_rec_frame (int chan, int subchan, int slice, packet_t pp, alevel_t alevel, int is_fx25, retry_t retries, char *spectrum) void dlq_rec_frame (int chan, int subchan, int slice, packet_t pp, alevel_t alevel, fec_type_t fec_type, retry_t retries, char *spectrum)
{ {
char stemp[500]; char stemp[500];
@ -826,29 +826,31 @@ void dlq_rec_frame (int chan, int subchan, int slice, packet_t pp, alevel_t alev
strlcat (heard, ")", sizeof(heard)); strlcat (heard, ")", sizeof(heard));
} }
switch (fec_type) {
case fec_type_fx25:
dw_printf ("%s audio level = %s FX.25 %s\n", heard, alevel_text, spectrum);
break;
case fec_type_il2p:
dw_printf ("%s audio level = %s IL2P %s\n", heard, alevel_text, spectrum);
break;
case fec_type_none:
default:
if (my_audio_config.achan[chan].fix_bits == RETRY_NONE && my_audio_config.achan[chan].passall == 0) { if (my_audio_config.achan[chan].fix_bits == RETRY_NONE && my_audio_config.achan[chan].passall == 0) {
dw_printf ("%s audio level = %s %s\n", heard, alevel_text, spectrum); // No fix_bits or passall specified.
}
else if (is_fx25) {
dw_printf ("%s audio level = %s %s\n", heard, alevel_text, spectrum); dw_printf ("%s audio level = %s %s\n", heard, alevel_text, spectrum);
} }
else { else {
assert (retries >= RETRY_NONE && retries <= RETRY_MAX); assert (retries >= RETRY_NONE && retries <= RETRY_MAX); // validate array index.
dw_printf ("%s audio level = %s [%s] %s\n", heard, alevel_text, retry_text[(int)retries], spectrum); dw_printf ("%s audio level = %s [%s] %s\n", heard, alevel_text, retry_text[(int)retries], spectrum);
} }
break;
}
#endif #endif
//#if defined(EXPERIMENT_G) || defined(EXPERIMENT_H)
// int j;
//
// for (j=0; j<MAX_SUBCHANS; j++) {
// if (spectrum[j] == '|') {
// count[j]++;
// }
// }
//#endif
// Display non-APRS packets in a different color. // Display non-APRS packets in a different color.

View File

@ -128,6 +128,7 @@
#include "il2p.h" #include "il2p.h"
#include "dwsock.h" #include "dwsock.h"
#include "dns_sd_dw.h" #include "dns_sd_dw.h"
#include "dlq.h" // for fec_type_t definition.
//static int idx_decoded = 0; //static int idx_decoded = 0;
@ -300,7 +301,7 @@ int main (int argc, char *argv[])
text_color_init(t_opt); text_color_init(t_opt);
text_color_set(DW_COLOR_INFO); text_color_set(DW_COLOR_INFO);
dw_printf ("Dire Wolf version %d.%d (%s) BETA TEST 5\n", MAJOR_VERSION, MINOR_VERSION, __DATE__); dw_printf ("Dire Wolf version %d.%d (%s) BETA TEST 7\n", MAJOR_VERSION, MINOR_VERSION, __DATE__);
//dw_printf ("Dire Wolf DEVELOPMENT version %d.%d %s (%s)\n", MAJOR_VERSION, MINOR_VERSION, "G", __DATE__); //dw_printf ("Dire Wolf DEVELOPMENT version %d.%d %s (%s)\n", MAJOR_VERSION, MINOR_VERSION, "G", __DATE__);
//dw_printf ("Dire Wolf version %d.%d\n", MAJOR_VERSION, MINOR_VERSION); //dw_printf ("Dire Wolf version %d.%d\n", MAJOR_VERSION, MINOR_VERSION);
@ -1179,7 +1180,7 @@ int main (int argc, char *argv[])
// TODO: Use only one printf per line so output doesn't get jumbled up with stuff from other threads. // TODO: Use only one printf per line so output doesn't get jumbled up with stuff from other threads.
void app_process_rec_packet (int chan, int subchan, int slice, packet_t pp, alevel_t alevel, int is_fx25, retry_t retries, char *spectrum) void app_process_rec_packet (int chan, int subchan, int slice, packet_t pp, alevel_t alevel, fec_type_t fec_type, retry_t retries, char *spectrum)
{ {
char stemp[500]; char stemp[500];
@ -1188,7 +1189,8 @@ void app_process_rec_packet (int chan, int subchan, int slice, packet_t pp, alev
char heard[AX25_MAX_ADDR_LEN]; char heard[AX25_MAX_ADDR_LEN];
//int j; //int j;
int h; int h;
char display_retries[32]; char display_retries[32]; // Extra stuff before slice indicators.
// Can indicate FX.25/IL2P or fix_bits.
assert (chan >= 0 && chan < MAX_TOTAL_CHANS); // TOTAL for virtual channels assert (chan >= 0 && chan < MAX_TOTAL_CHANS); // TOTAL for virtual channels
assert (subchan >= -2 && subchan < MAX_SUBCHANS); assert (subchan >= -2 && subchan < MAX_SUBCHANS);
@ -1197,13 +1199,22 @@ void app_process_rec_packet (int chan, int subchan, int slice, packet_t pp, alev
strlcpy (display_retries, "", sizeof(display_retries)); strlcpy (display_retries, "", sizeof(display_retries));
if (is_fx25) { switch (fec_type) {
; case fec_type_fx25:
} strlcpy (display_retries, " FX.25 ", sizeof(display_retries));
else if (audio_config.achan[chan].fix_bits != RETRY_NONE || audio_config.achan[chan].passall) { break;
case fec_type_il2p:
strlcpy (display_retries, " IL2P ", sizeof(display_retries));
break;
case fec_type_none:
default:
// Possible fix_bits indication.
if (audio_config.achan[chan].fix_bits != RETRY_NONE || audio_config.achan[chan].passall) {
assert (retries >= RETRY_NONE && retries <= RETRY_MAX); assert (retries >= RETRY_NONE && retries <= RETRY_MAX);
snprintf (display_retries, sizeof(display_retries), " [%s] ", retry_text[(int)retries]); snprintf (display_retries, sizeof(display_retries), " [%s] ", retry_text[(int)retries]);
} }
break;
}
ax25_format_addrs (pp, stemp); ax25_format_addrs (pp, stemp);
@ -1567,7 +1578,7 @@ void app_process_rec_packet (int chan, int subchan, int slice, packet_t pp, alev
* However, if it used FEC mode (FX.25. IL2P), we have much higher level of * However, if it used FEC mode (FX.25. IL2P), we have much higher level of
* confidence that it is correct. * confidence that it is correct.
*/ */
if (ax25_is_aprs(pp) && ( retries == RETRY_NONE || is_fx25) ) { if (ax25_is_aprs(pp) && ( retries == RETRY_NONE || fec_type == fec_type_fx25 || fec_type == fec_type_il2p) ) {
igate_send_rec_packet (chan, pp); igate_send_rec_packet (chan, pp);
} }
@ -1588,7 +1599,7 @@ void app_process_rec_packet (int chan, int subchan, int slice, packet_t pp, alev
* However, if it used FEC mode (FX.25. IL2P), we have much higher level of * However, if it used FEC mode (FX.25. IL2P), we have much higher level of
* confidence that it is correct. * confidence that it is correct.
*/ */
if (ax25_is_aprs(pp) && ( retries == RETRY_NONE || is_fx25) ) { if (ax25_is_aprs(pp) && ( retries == RETRY_NONE || fec_type == fec_type_fx25 || fec_type == fec_type_il2p) ) {
digipeater (chan, pp); digipeater (chan, pp);
} }
@ -1598,7 +1609,7 @@ void app_process_rec_packet (int chan, int subchan, int slice, packet_t pp, alev
* Use only those with correct CRC (or using FEC.) * Use only those with correct CRC (or using FEC.)
*/ */
if (retries == RETRY_NONE || is_fx25) { if (retries == RETRY_NONE || fec_type == fec_type_fx25 || fec_type == fec_type_il2p) {
cdigipeater (chan, pp); cdigipeater (chan, pp);
} }

View File

@ -215,10 +215,10 @@ void dlq_init (void)
* display of audio level line. * display of audio level line.
* Use -2 to indicate DTMF message.) * Use -2 to indicate DTMF message.)
* *
* is_fx25 - Was it from FX.25? Need to know because * fec_type - Was it from FX.25 or IL2P? Need to know because
* meaning of retries is different. * meaning of retries is different.
* *
* retries - Level of bit correction used. * retries - Level of correction used.
* *
* spectrum - Display of how well multiple decoders did. * spectrum - Display of how well multiple decoders did.
* *
@ -228,7 +228,7 @@ void dlq_init (void)
* *
*--------------------------------------------------------------------*/ *--------------------------------------------------------------------*/
void dlq_rec_frame (int chan, int subchan, int slice, packet_t pp, alevel_t alevel, int is_fx25, retry_t retries, char *spectrum) void dlq_rec_frame (int chan, int subchan, int slice, packet_t pp, alevel_t alevel, fec_type_t fec_type, retry_t retries, char *spectrum)
{ {
struct dlq_item_s *pnew; struct dlq_item_s *pnew;
@ -278,7 +278,7 @@ void dlq_rec_frame (int chan, int subchan, int slice, packet_t pp, alevel_t alev
pnew->subchan = subchan; pnew->subchan = subchan;
pnew->pp = pp; pnew->pp = pp;
pnew->alevel = alevel; pnew->alevel = alevel;
pnew->is_fx25 = is_fx25; pnew->fec_type = fec_type;
pnew->retries = retries; pnew->retries = retries;
if (spectrum == NULL) if (spectrum == NULL)
strlcpy(pnew->spectrum, "", sizeof(pnew->spectrum)); strlcpy(pnew->spectrum, "", sizeof(pnew->spectrum));

View File

@ -33,10 +33,13 @@ typedef struct cdata_s {
/* Types of things that can be in queue. */ /* Types of things that can be in queue. */
typedef enum dlq_type_e {DLQ_REC_FRAME, DLQ_CONNECT_REQUEST, DLQ_DISCONNECT_REQUEST, DLQ_XMIT_DATA_REQUEST, DLQ_REGISTER_CALLSIGN, DLQ_UNREGISTER_CALLSIGN, DLQ_OUTSTANDING_FRAMES_REQUEST, DLQ_CHANNEL_BUSY, DLQ_SEIZE_CONFIRM, DLQ_CLIENT_CLEANUP} dlq_type_t; typedef enum dlq_type_e {DLQ_REC_FRAME, DLQ_CONNECT_REQUEST, DLQ_DISCONNECT_REQUEST, DLQ_XMIT_DATA_REQUEST, DLQ_REGISTER_CALLSIGN, DLQ_UNREGISTER_CALLSIGN, DLQ_OUTSTANDING_FRAMES_REQUEST, DLQ_CHANNEL_BUSY, DLQ_SEIZE_CONFIRM, DLQ_CLIENT_CLEANUP} dlq_type_t;
typedef enum fec_type_e {fec_type_none=0, fec_type_fx25=1, fec_type_il2p=2} fec_type_t;
/* A queue item. */ /* A queue item. */
@ -68,7 +71,7 @@ typedef struct dlq_item_s {
alevel_t alevel; /* Audio level. */ alevel_t alevel; /* Audio level. */
int is_fx25; /* Was it from FX.25? */ fec_type_t fec_type; // Type of FEC for received signal: none, FX.25, or IL2P.
retry_t retries; /* Effort expended to get a valid CRC. */ retry_t retries; /* Effort expended to get a valid CRC. */
/* Bits changed for regular AX.25. */ /* Bits changed for regular AX.25. */
@ -106,7 +109,7 @@ void dlq_init (void);
void dlq_rec_frame (int chan, int subchan, int slice, packet_t pp, alevel_t alevel, int is_fx25, retry_t retries, char *spectrum); void dlq_rec_frame (int chan, int subchan, int slice, packet_t pp, alevel_t alevel, fec_type_t fec_type, retry_t retries, char *spectrum);
void dlq_connect_request (char addrs[AX25_MAX_ADDRS][AX25_MAX_ADDR_LEN], int num_addr, int chan, int client, int pid); void dlq_connect_request (char addrs[AX25_MAX_ADDRS][AX25_MAX_ADDR_LEN], int num_addr, int chan, int client, int pid);

View File

@ -6,6 +6,7 @@
#include "ax25_pad.h" /* for packet_t, alevel_t */ #include "ax25_pad.h" /* for packet_t, alevel_t */
#include "rrbb.h" #include "rrbb.h"
#include "audio.h" /* for struct audio_s */ #include "audio.h" /* for struct audio_s */
#include "dlq.h" // for fec_type_t definition.
@ -62,6 +63,6 @@ int hdlc_rec2_try_to_fix_later (rrbb_t block, int chan, int subchan, int slice,
/* Provided by the top level application to process a complete frame. */ /* Provided by the top level application to process a complete frame. */
void app_process_rec_packet (int chan, int subchan, int slice, packet_t pp, alevel_t level, int is_fx25, retry_t retries, char *spectrum); void app_process_rec_packet (int chan, int subchan, int slice, packet_t pp, alevel_t level, fec_type_t fec_type, retry_t retries, char *spectrum);
#endif #endif

View File

@ -1564,9 +1564,9 @@ static void * igate_recv_thread (void *arg)
// See what happens with -2 and follow up on this. // See what happens with -2 and follow up on this.
// Do we need something else here? // Do we need something else here?
int slice = 0; int slice = 0;
int is_fx25 = 0; fec_type_t fec_type = fec_type_none;
char spectrum[] = "APRS-IS"; char spectrum[] = "APRS-IS";
dlq_rec_frame (ichan, subchan, slice, pp3, alevel, is_fx25, RETRY_NONE, spectrum); dlq_rec_frame (ichan, subchan, slice, pp3, alevel, fec_type, RETRY_NONE, spectrum);
} }
else { else {
text_color_set(DW_COLOR_ERROR); text_color_set(DW_COLOR_ERROR);

View File

@ -943,7 +943,7 @@ void tone_gen_put_bit (int chan, int data)
// This is called when a complete frame has been deserialized. // This is called when a complete frame has been deserialized.
void multi_modem_process_rec_packet (int chan, int subchan, int slice, packet_t pp, alevel_t alevel, retry_t retries, int is_fx25) void multi_modem_process_rec_packet (int chan, int subchan, int slice, packet_t pp, alevel_t alevel, retry_t retries, fec_type_t fec_type)
{ {
if (rec_count < 0) return; // Skip check before serdes test. if (rec_count < 0) return; // Skip check before serdes test.

View File

@ -116,7 +116,8 @@ static struct audio_s *save_audio_config_p;
static struct { static struct {
packet_t packet_p; packet_t packet_p;
alevel_t alevel; alevel_t alevel;
int is_fx25; // 1 for FX.25, 0 for regular AX.25. float speed_error;
fec_type_t fec_type; // Type of FEC: none(0), fx25, il2p
retry_t retries; // For the old "fix bits" strategy, this is the retry_t retries; // For the old "fix bits" strategy, this is the
// number of bits that were modified to get a good CRC. // number of bits that were modified to get a good CRC.
// It would be 0 to something around 4. // It would be 0 to something around 4.
@ -306,14 +307,14 @@ void multi_modem_process_sample (int chan, int audio_sample)
* display of audio level line. * display of audio level line.
* Use -2 to indicate DTMF message.) * Use -2 to indicate DTMF message.)
* retries - Level of correction used. * retries - Level of correction used.
* is_fx25 - 1 for FX.25, 0 for normal AX.25. * fec_type - none(0), fx25, il2p
* *
* Description: Add to list of candidates. Best one will be picked later. * Description: Add to list of candidates. Best one will be picked later.
* *
*--------------------------------------------------------------------*/ *--------------------------------------------------------------------*/
void multi_modem_process_rec_frame (int chan, int subchan, int slice, unsigned char *fbuf, int flen, alevel_t alevel, retry_t retries, int is_fx25) void multi_modem_process_rec_frame (int chan, int subchan, int slice, unsigned char *fbuf, int flen, alevel_t alevel, retry_t retries, fec_type_t fec_type)
{ {
packet_t pp; packet_t pp;
@ -346,12 +347,12 @@ void multi_modem_process_rec_frame (int chan, int subchan, int slice, unsigned c
pp = ax25_from_frame (fbuf, flen, alevel); pp = ax25_from_frame (fbuf, flen, alevel);
} }
multi_modem_process_rec_packet (chan, subchan, slice, pp, alevel, retries, is_fx25); multi_modem_process_rec_packet (chan, subchan, slice, pp, alevel, retries, fec_type);
} }
// TODO: Eliminate function above and move code elsewhere? // TODO: Eliminate function above and move code elsewhere?
void multi_modem_process_rec_packet (int chan, int subchan, int slice, packet_t pp, alevel_t alevel, retry_t retries, int is_fx25) void multi_modem_process_rec_packet (int chan, int subchan, int slice, packet_t pp, alevel_t alevel, retry_t retries, fec_type_t fec_type)
{ {
if (pp == NULL) { if (pp == NULL) {
text_color_set(DW_COLOR_ERROR); text_color_set(DW_COLOR_ERROR);
@ -386,7 +387,7 @@ void multi_modem_process_rec_packet (int chan, int subchan, int slice, packet_t
ax25_delete (pp); ax25_delete (pp);
} }
else { else {
dlq_rec_frame (chan, subchan, slice, pp, alevel, is_fx25, retries, ""); dlq_rec_frame (chan, subchan, slice, pp, alevel, fec_type, retries, "");
} }
return; return;
} }
@ -406,7 +407,7 @@ void multi_modem_process_rec_packet (int chan, int subchan, int slice, packet_t
candidate[chan][subchan][slice].packet_p = pp; candidate[chan][subchan][slice].packet_p = pp;
candidate[chan][subchan][slice].alevel = alevel; candidate[chan][subchan][slice].alevel = alevel;
candidate[chan][subchan][slice].is_fx25 = is_fx25; candidate[chan][subchan][slice].fec_type = fec_type;
candidate[chan][subchan][slice].retries = retries; candidate[chan][subchan][slice].retries = retries;
candidate[chan][subchan][slice].age = 0; candidate[chan][subchan][slice].age = 0;
candidate[chan][subchan][slice].crc = ax25_m_m_crc(pp); candidate[chan][subchan][slice].crc = ax25_m_m_crc(pp);
@ -443,6 +444,9 @@ static void pick_best_candidate (int chan)
int best_n, best_score; int best_n, best_score;
char spectrum[MAX_SUBCHANS*MAX_SLICERS+1]; char spectrum[MAX_SUBCHANS*MAX_SLICERS+1];
int n, j, k; int n, j, k;
if (save_audio_config_p->achan[chan].num_slicers < 1) {
save_audio_config_p->achan[chan].num_slicers = 1;
}
int num_bars = save_audio_config_p->achan[chan].num_slicers * save_audio_config_p->achan[chan].num_subchan; int num_bars = save_audio_config_p->achan[chan].num_slicers * save_audio_config_p->achan[chan].num_subchan;
memset (spectrum, 0, sizeof(spectrum)); memset (spectrum, 0, sizeof(spectrum));
@ -456,7 +460,7 @@ static void pick_best_candidate (int chan)
if (candidate[chan][j][k].packet_p == NULL) { if (candidate[chan][j][k].packet_p == NULL) {
spectrum[n] = '_'; spectrum[n] = '_';
} }
else if (candidate[chan][j][k].is_fx25) { else if (candidate[chan][j][k].fec_type != fec_type_none) { // FX.25 or IL2P
// FIXME: using retries both as an enum and later int too. // FIXME: using retries both as an enum and later int too.
if ((int)(candidate[chan][j][k].retries) <= 9) { if ((int)(candidate[chan][j][k].retries) <= 9) {
spectrum[n] = '0' + candidate[chan][j][k].retries; spectrum[n] = '0' + candidate[chan][j][k].retries;
@ -464,7 +468,7 @@ static void pick_best_candidate (int chan)
else { else {
spectrum[n] = '+'; spectrum[n] = '+';
} }
} } // AX.25 below
else if (candidate[chan][j][k].retries == RETRY_NONE) { else if (candidate[chan][j][k].retries == RETRY_NONE) {
spectrum[n] = '|'; spectrum[n] = '|';
} }
@ -481,8 +485,8 @@ static void pick_best_candidate (int chan)
candidate[chan][j][k].score = 0; candidate[chan][j][k].score = 0;
} }
else { else {
if (candidate[chan][j][k].is_fx25) { if (candidate[chan][j][k].fec_type != fec_type_none) {
candidate[chan][j][k].score = 9000 - 100 * candidate[chan][j][k].retries; candidate[chan][j][k].score = 9000 - 100 * candidate[chan][j][k].retries; // has FEC
} }
else { else {
/* Originally, this produced 0 for the PASSALL case. */ /* Originally, this produced 0 for the PASSALL case. */
@ -550,9 +554,9 @@ static void pick_best_candidate (int chan)
candidate[chan][j][k].packet_p); candidate[chan][j][k].packet_p);
} }
else { else {
dw_printf ("%d.%d.%d: ptr=%p, is_fx25=%d, retry=%d, age=%3d, crc=%04x, score=%d %s\n", chan, j, k, dw_printf ("%d.%d.%d: ptr=%p, fec_type=%d, retry=%d, age=%3d, crc=%04x, score=%d %s\n", chan, j, k,
candidate[chan][j][k].packet_p, candidate[chan][j][k].packet_p,
candidate[chan][j][k].is_fx25, (int)(candidate[chan][j][k].fec_type),
(int)(candidate[chan][j][k].retries), (int)(candidate[chan][j][k].retries),
candidate[chan][j][k].age, candidate[chan][j][k].age,
candidate[chan][j][k].crc, candidate[chan][j][k].crc,
@ -611,7 +615,7 @@ static void pick_best_candidate (int chan)
dlq_rec_frame (chan, j, k, dlq_rec_frame (chan, j, k,
candidate[chan][j][k].packet_p, candidate[chan][j][k].packet_p,
candidate[chan][j][k].alevel, candidate[chan][j][k].alevel,
candidate[chan][j][k].is_fx25, candidate[chan][j][k].fec_type,
(int)(candidate[chan][j][k].retries), (int)(candidate[chan][j][k].retries),
spectrum); spectrum);

View File

@ -17,8 +17,8 @@ void multi_modem_process_sample (int c, int audio_sample);
int multi_modem_get_dc_average (int chan); int multi_modem_get_dc_average (int chan);
// Deprecated. Replace with ...packet // Deprecated. Replace with ...packet
void multi_modem_process_rec_frame (int chan, int subchan, int slice, unsigned char *fbuf, int flen, alevel_t alevel, retry_t retries, int is_fx25); void multi_modem_process_rec_frame (int chan, int subchan, int slice, unsigned char *fbuf, int flen, alevel_t alevel, retry_t retries, fec_type_t fec_type);
void multi_modem_process_rec_packet (int chan, int subchan, int slice, packet_t pp, alevel_t alevel, retry_t retries, int is_fx25); void multi_modem_process_rec_packet (int chan, int subchan, int slice, packet_t pp, alevel_t alevel, retry_t retries, fec_type_t fec_type);
#endif #endif

View File

@ -339,7 +339,7 @@ void recv_process (void)
* - Digipeater. * - Digipeater.
*/ */
app_process_rec_packet (pitem->chan, pitem->subchan, pitem->slice, pitem->pp, pitem->alevel, pitem->is_fx25, pitem->retries, pitem->spectrum); app_process_rec_packet (pitem->chan, pitem->subchan, pitem->slice, pitem->pp, pitem->alevel, pitem->fec_type, pitem->retries, pitem->spectrum);
/* /*