mirror of https://github.com/wb2osz/direwolf.git
New NCHANNEL feature.
This commit is contained in:
parent
c05669a82b
commit
ae888b0a8d
|
@ -6,6 +6,9 @@
|
|||
|
||||
### New Features: ###
|
||||
|
||||
|
||||
- New NCHANNEL feature to map a channel number to an external network TCP KISS TNC. See xxx for example of a bridge to LoRa APRS. See [APRS-LoRa-VHF-APRS-Bridge.pdf](https://github.com/wb2osz/direwolf-doc/blob/main/APRS-LoRa-VHF-APRS-Bridge.pdf) for explanation.
|
||||
|
||||
- [http://www.aprs.org/aprs11/tocalls.txt](http://www.aprs.org/aprs11/tocalls.txt) has been abandoned since the end of 2021. [https://github.com/aprsorg/aprs-deviceid](https://github.com/aprsorg/aprs-deviceid) is now considered to be the authoritative source of truth for the vendor/model encoding.
|
||||
|
||||
## Version 1.7 -- October 2023 ##
|
||||
|
|
|
@ -274,7 +274,7 @@
|
|||
%C%#DTMF
|
||||
%C%
|
||||
%C%# Push to Talk (PTT) can be confusing because there are so many different cases.
|
||||
%C%# Radio-Interface-Guide.pdf in https://github.com/wb2osz/direwolf-doc
|
||||
%C%# https://github.com/wb2osz/direwolf-doc/blob/main/Radio-Interface-Guide.pdf
|
||||
%C%# goes into detail about the various options.
|
||||
%C%
|
||||
%L%# If using a C-Media CM108/CM119 or similar USB Audio Adapter,
|
||||
|
|
|
@ -79,6 +79,7 @@ list(APPEND direwolf_SOURCES
|
|||
morse.c
|
||||
multi_modem.c
|
||||
waypoint.c
|
||||
nettnc.c
|
||||
serial_port.c
|
||||
pfilter.c
|
||||
ptt.c
|
||||
|
|
|
@ -357,7 +357,7 @@ static void * tnc_listen_thread (void *arg)
|
|||
/*
|
||||
* Take some precautions to guard against bad data which could cause problems later.
|
||||
*/
|
||||
if (cmd.hdr.portx < 0 || cmd.hdr.portx >= MAX_CHANS) {
|
||||
if (cmd.hdr.portx < 0 || cmd.hdr.portx >= MAX_TOTAL_CHANS) {
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf ("Invalid channel number, %d, in command '%c', from network TNC.\n",
|
||||
cmd.hdr.portx, cmd.hdr.datakind);
|
||||
|
|
|
@ -597,7 +597,7 @@ void agw_cb_G_port_information (int num_chan_avail, char *chan_descriptions[])
|
|||
if (strncasecmp(p, "Port", 4) == 0 && isdigit(p[4])) {
|
||||
|
||||
int chan = atoi(p+4) - 1; // "Port1" is our channel 0.
|
||||
if (chan >= 0 && chan < MAX_CHANS) {
|
||||
if (chan >= 0 && chan < MAX_TOTAL_CHANS) {
|
||||
|
||||
char *desc = p + 4;
|
||||
while (*desc != '\0' && (*desc == ' ' || isdigit(*desc))) {
|
||||
|
|
|
@ -95,8 +95,8 @@
|
|||
|
||||
#define MAX_MSG_LEN 100
|
||||
|
||||
static char msg_str[MAX_CHANS][MAX_MSG_LEN+1];
|
||||
static int msg_len[MAX_CHANS];
|
||||
static char msg_str[MAX_RADIO_CHANS][MAX_MSG_LEN+1];
|
||||
static int msg_len[MAX_RADIO_CHANS];
|
||||
|
||||
static int parse_fields (char *msg);
|
||||
static int parse_callsign (char *e);
|
||||
|
@ -185,7 +185,7 @@ void aprs_tt_init (struct tt_config_s *p, int debug)
|
|||
// TODO: Keep ptr instead of making a copy.
|
||||
memcpy (&tt_config, p, sizeof(struct tt_config_s));
|
||||
#endif
|
||||
for (c=0; c<MAX_CHANS; c++) {
|
||||
for (c=0; c<MAX_RADIO_CHANS; c++) {
|
||||
msg_len[c] = 0;
|
||||
msg_str[c][0] = '\0';
|
||||
}
|
||||
|
@ -226,7 +226,7 @@ void aprs_tt_button (int chan, char button)
|
|||
{
|
||||
static int poll_period = 0;
|
||||
|
||||
assert (chan >= 0 && chan < MAX_CHANS);
|
||||
assert (chan >= 0 && chan < MAX_RADIO_CHANS);
|
||||
|
||||
|
||||
//if (button != '.') {
|
||||
|
|
11
src/atest.c
11
src/atest.c
|
@ -231,7 +231,7 @@ int main (int argc, char *argv[])
|
|||
my_audio_config.adev[0].bits_per_sample = DEFAULT_BITS_PER_SAMPLE;
|
||||
|
||||
|
||||
for (channel=0; channel<MAX_CHANS; channel++) {
|
||||
for (channel=0; channel<MAX_RADIO_CHANS; channel++) {
|
||||
|
||||
my_audio_config.achan[channel].modem_type = MODEM_AFSK;
|
||||
|
||||
|
@ -628,9 +628,10 @@ int main (int argc, char *argv[])
|
|||
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);
|
||||
(int)(my_audio_config.adev[0].num_channels));
|
||||
// nnum_channels is known to be 1 or 2.
|
||||
one_filetime = (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);
|
||||
((my_audio_config.adev[0].bits_per_sample / 8) * (int)(my_audio_config.adev[0].num_channels) * my_audio_config.adev[0].samples_per_sec);
|
||||
total_filetime += one_filetime;
|
||||
|
||||
dw_printf ("%d audio bytes in file. Duration = %.1f seconds.\n",
|
||||
|
@ -654,7 +655,7 @@ int main (int argc, char *argv[])
|
|||
int audio_sample;
|
||||
int c;
|
||||
|
||||
for (c=0; c<my_audio_config.adev[0].num_channels; c++)
|
||||
for (c=0; c<(int)(my_audio_config.adev[0].num_channels); c++)
|
||||
{
|
||||
|
||||
/* This reads either 1 or 2 bytes depending on */
|
||||
|
@ -921,7 +922,7 @@ void dlq_rec_frame (int chan, int subchan, int slice, packet_t pp, alevel_t alev
|
|||
void ptt_set (int ot, int chan, int ptt_signal)
|
||||
{
|
||||
// Should only get here for DCD output control.
|
||||
static double dcd_start_time[MAX_CHANS];
|
||||
static double dcd_start_time[MAX_RADIO_CHANS];
|
||||
|
||||
if (d_o_opt) {
|
||||
double t = (double)sample_number / my_audio_config.adev[0].samples_per_sec;
|
||||
|
|
|
@ -257,7 +257,7 @@ int audio_open (struct audio_s *pa)
|
|||
if (pa->adev[a].bits_per_sample == 0)
|
||||
pa->adev[a].bits_per_sample = DEFAULT_BITS_PER_SAMPLE;
|
||||
|
||||
for (chan=0; chan<MAX_CHANS; chan++) {
|
||||
for (chan=0; chan<MAX_RADIO_CHANS; chan++) {
|
||||
if (pa->achan[chan].mark_freq == 0)
|
||||
pa->achan[chan].mark_freq = DEFAULT_MARK_FREQ;
|
||||
|
||||
|
|
27
src/audio.h
27
src/audio.h
|
@ -16,7 +16,7 @@
|
|||
#include <hamlib/rig.h>
|
||||
#endif
|
||||
|
||||
#include "direwolf.h" /* for MAX_CHANS used throughout the application. */
|
||||
#include "direwolf.h" /* for MAX_RADIO_CHANS and MAX_TOTAL_CHANS used throughout the application. */
|
||||
#include "ax25_pad.h" /* for AX25_MAX_ADDR_LEN */
|
||||
#include "version.h"
|
||||
|
||||
|
@ -59,7 +59,7 @@ typedef enum retry_e {
|
|||
enum medium_e { MEDIUM_NONE = 0, // Channel is not valid for use.
|
||||
MEDIUM_RADIO, // Internal modem for radio.
|
||||
MEDIUM_IGATE, // Access IGate as ordinary channel.
|
||||
MEDIUM_NETTNC }; // Remote network TNC. (possible future)
|
||||
MEDIUM_NETTNC }; // Remote network TNC. (new in 1.8)
|
||||
|
||||
|
||||
typedef enum sanity_e { SANITY_APRS, SANITY_AX25, SANITY_NONE } sanity_t;
|
||||
|
@ -139,10 +139,19 @@ struct audio_s {
|
|||
/* originally a "channel" was always connected to an internal modem. */
|
||||
/* In version 1.6, this is generalized so that a channel (as seen by client application) */
|
||||
/* can be connected to something else. Initially, this will allow application */
|
||||
/* access to the IGate. Later we might have network TNCs or other internal functions. */
|
||||
/* access to the IGate. In version 1.8 we add network KISS TNC. */
|
||||
|
||||
// Watch out for maximum number of channels.
|
||||
// MAX_CHANS - Originally, this was 6 for internal modem adio channels. Has been phased out.
|
||||
// After adding virtual channels (IGate, network TNC), this is split into two different numbers:
|
||||
// MAX_RADIO_CHANNELS - For internal modems.
|
||||
// MAX_TOTAL_CHANNELS - limited by KISS channels/ports. Needed for digipeating, filtering, etc.
|
||||
|
||||
// Properties for all channels.
|
||||
|
||||
char mycall[MAX_TOTAL_CHANS][AX25_MAX_ADDR_LEN]; /* Call associated with this radio channel. */
|
||||
/* Could all be the same or different. */
|
||||
|
||||
enum medium_e chan_medium[MAX_TOTAL_CHANS];
|
||||
// MEDIUM_NONE for invalid.
|
||||
// MEDIUM_RADIO for internal modem. (only possibility earlier)
|
||||
|
@ -154,6 +163,14 @@ struct audio_s {
|
|||
/* Redundant but it makes things quicker and simpler */
|
||||
/* than always searching thru above. */
|
||||
|
||||
// Applies only to network TNC type channels.
|
||||
|
||||
char nettnc_addr[MAX_TOTAL_CHANS][80]; // Network TNC address: hostname or IP addr.
|
||||
|
||||
int nettnc_port[MAX_TOTAL_CHANS]; // Network TNC TCP port.
|
||||
|
||||
|
||||
|
||||
/* Properties for each radio channel, common to receive and transmit. */
|
||||
/* Can be different for each radio channel. */
|
||||
|
||||
|
@ -171,8 +188,6 @@ struct audio_s {
|
|||
// int audio_source; // Default would be [0,1,2,3,4,5]
|
||||
|
||||
// What else should be moved out of structure and enlarged when NETTNC is implemented. ???
|
||||
char mycall[AX25_MAX_ADDR_LEN]; /* Call associated with this radio channel. */
|
||||
/* Could all be the same or different. */
|
||||
|
||||
|
||||
enum modem_t { MODEM_AFSK, MODEM_BASEBAND, MODEM_SCRAMBLE, MODEM_QPSK, MODEM_8PSK, MODEM_OFF, MODEM_16_QAM, MODEM_64_QAM, MODEM_AIS, MODEM_EAS } modem_type;
|
||||
|
@ -381,7 +396,7 @@ struct audio_s {
|
|||
|
||||
int fulldup; /* Full Duplex. */
|
||||
|
||||
} achan[MAX_CHANS];
|
||||
} achan[MAX_RADIO_CHANS];
|
||||
|
||||
#ifdef USE_HAMLIB
|
||||
int rigs; /* Total number of configured rigs */
|
||||
|
|
|
@ -578,7 +578,7 @@ int audio_open (struct audio_s *pa)
|
|||
if (pa->adev[a].bits_per_sample == 0)
|
||||
pa->adev[a].bits_per_sample = DEFAULT_BITS_PER_SAMPLE;
|
||||
|
||||
for (chan = 0; chan < MAX_CHANS; chan++) {
|
||||
for (chan = 0; chan < MAX_RADIO_CHANS; chan++) {
|
||||
if (pa->achan[chan].mark_freq == 0)
|
||||
pa->achan[chan].mark_freq = DEFAULT_MARK_FREQ;
|
||||
|
||||
|
|
|
@ -270,7 +270,7 @@ int audio_open (struct audio_s *pa)
|
|||
|
||||
A->g_audio_in_type = AUDIO_IN_TYPE_SOUNDCARD;
|
||||
|
||||
for (chan=0; chan<MAX_CHANS; chan++) {
|
||||
for (chan=0; chan<MAX_RADIO_CHANS; chan++) {
|
||||
if (pa -> achan[chan].mark_freq == 0)
|
||||
pa -> achan[chan].mark_freq = DEFAULT_MARK_FREQ;
|
||||
|
||||
|
@ -660,7 +660,13 @@ int audio_open (struct audio_s *pa)
|
|||
*/
|
||||
case AUDIO_IN_TYPE_STDIN:
|
||||
|
||||
setmode (STDIN_FILENO, _O_BINARY);
|
||||
// https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/setmode?view=msvc-170
|
||||
|
||||
int err = _setmode (_fileno(stdin), _O_BINARY);
|
||||
if (err == -1) {
|
||||
text_color_set (DW_COLOR_ERROR);
|
||||
dw_printf ("Could not set stdin to binary mode. Unlikely to get desired result.\n");
|
||||
}
|
||||
A->stream_next= 0;
|
||||
A->stream_len = 0;
|
||||
|
||||
|
@ -888,7 +894,7 @@ int audio_get (int a)
|
|||
while (A->stream_next >= A->stream_len) {
|
||||
int res;
|
||||
|
||||
res = read(STDIN_FILENO, A->stream_data, 1024);
|
||||
res = read(STDIN_FILENO, A->stream_data, sizeof(A->stream_data));
|
||||
if (res <= 0) {
|
||||
text_color_set(DW_COLOR_INFO);
|
||||
dw_printf ("\nEnd of file on stdin. Exiting.\n");
|
||||
|
@ -903,9 +909,13 @@ int audio_get (int a)
|
|||
A->stream_len = res;
|
||||
A->stream_next = 0;
|
||||
}
|
||||
return (A->stream_data[A->stream_next++] & 0xff);
|
||||
sample = A->stream_data[A->stream_next] & 0xff;
|
||||
A->stream_next++;
|
||||
return (sample);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
} // end switch audio in type
|
||||
|
||||
return (-1);
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
//
|
||||
// This file is part of Dire Wolf, an amateur radio packet TNC.
|
||||
//
|
||||
// Copyright (C) 2016, 2017, 2018, 2023 John Langner, WB2OSZ
|
||||
// Copyright (C) 2016, 2017, 2018, 2023, 2024 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
|
||||
|
@ -679,11 +679,13 @@ static struct misc_config_s *g_misc_config_p;
|
|||
* Inputs: pconfig - misc. configuration from config file or command line.
|
||||
* Beacon stuff ended up here.
|
||||
*
|
||||
* debug - debug level.
|
||||
*
|
||||
* Outputs: Remember required information for future use. That's all.
|
||||
*
|
||||
*--------------------------------------------------------------------*/
|
||||
|
||||
void ax25_link_init (struct misc_config_s *pconfig)
|
||||
void ax25_link_init (struct misc_config_s *pconfig, int debug)
|
||||
{
|
||||
|
||||
/*
|
||||
|
@ -691,6 +693,31 @@ void ax25_link_init (struct misc_config_s *pconfig)
|
|||
*/
|
||||
g_misc_config_p = pconfig;
|
||||
|
||||
if (debug >= 1) { // Only single level so far.
|
||||
|
||||
s_debug_protocol_errors = 1; // Less serious Protocol errors.
|
||||
|
||||
s_debug_client_app = 1; // Interaction with client application.
|
||||
// dl_connect_request, dl_data_request, dl_data_indication, etc.
|
||||
|
||||
s_debug_radio = 1; // Received frames and channel busy status.
|
||||
// lm_data_indication, lm_channel_busy
|
||||
|
||||
s_debug_variables = 1; // Variables, state changes.
|
||||
|
||||
s_debug_retry = 1; // Related to lost I frames, REJ, SREJ, timeout, resending.
|
||||
|
||||
s_debug_link_handle = 1; // Create data link state machine or pick existing one,
|
||||
// based on my address, peer address, client app index, and radio channel.
|
||||
|
||||
s_debug_stats = 1; // Statistics when connection is closed.
|
||||
|
||||
s_debug_misc = 1; // Anything left over that might be interesting.
|
||||
|
||||
s_debug_timers = 1; // Timer details.
|
||||
}
|
||||
|
||||
|
||||
} /* end ax25_link_init */
|
||||
|
||||
|
||||
|
@ -2013,14 +2040,14 @@ static void dl_data_indication (ax25_dlsm_t *S, int pid, char *data, int len)
|
|||
*
|
||||
*------------------------------------------------------------------------------*/
|
||||
|
||||
static int dcd_status[MAX_CHANS];
|
||||
static int ptt_status[MAX_CHANS];
|
||||
static int dcd_status[MAX_RADIO_CHANS];
|
||||
static int ptt_status[MAX_RADIO_CHANS];
|
||||
|
||||
void lm_channel_busy (dlq_item_t *E)
|
||||
{
|
||||
int busy;
|
||||
|
||||
assert (E->chan >= 0 && E->chan < MAX_CHANS);
|
||||
assert (E->chan >= 0 && E->chan < MAX_RADIO_CHANS);
|
||||
assert (E->activity == OCTYPE_PTT || E->activity == OCTYPE_DCD);
|
||||
assert (E->status == 1 || E->status == 0);
|
||||
|
||||
|
@ -2104,7 +2131,7 @@ void lm_channel_busy (dlq_item_t *E)
|
|||
void lm_seize_confirm (dlq_item_t *E)
|
||||
{
|
||||
|
||||
assert (E->chan >= 0 && E->chan < MAX_CHANS);
|
||||
assert (E->chan >= 0 && E->chan < MAX_RADIO_CHANS);
|
||||
|
||||
ax25_dlsm_t *S;
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@
|
|||
|
||||
// Call once at startup time.
|
||||
|
||||
void ax25_link_init (struct misc_config_s *pconfig);
|
||||
void ax25_link_init (struct misc_config_s *pconfig, int debug);
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
//
|
||||
// This file is part of Dire Wolf, an amateur radio packet TNC.
|
||||
//
|
||||
// Copyright (C) 2011 , 2013, 2014, 2015, 2019 John Langner, WB2OSZ
|
||||
// Copyright (C) 2011 , 2013, 2014, 2015, 2019, 2024 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
|
||||
|
@ -355,12 +355,26 @@ void ax25_delete (packet_t this_p)
|
|||
* The SSID can be 2 alphanumeric characters, not just 1 to 15.
|
||||
*
|
||||
* We can just truncate the name because we will only
|
||||
* end up discarding it. TODO: check on this.
|
||||
* end up discarding it. TODO: check on this. WRONG! FIXME
|
||||
*
|
||||
* Returns: Pointer to new packet object in the current implementation.
|
||||
*
|
||||
* Outputs: Use the "get" functions to retrieve information in different ways.
|
||||
*
|
||||
* Evolution: Originally this was written to handle only valid RF packets.
|
||||
* There are other places where the rules are not as strict.
|
||||
* Using decode_aprs with raw data seen on aprs.fi. e.g.
|
||||
* EL-CA2JOT>RXTLM-1,TCPIP,qAR,CA2JOT::EL-CA2JOT:UNIT....
|
||||
* EA4YR>APBM1S,TCPIP*,qAS,BM2142POS:@162124z...
|
||||
* * Source addr might not comply to RF format.
|
||||
* * The q-construct has lower case.
|
||||
* * Tier-2 server name might not comply to RF format.
|
||||
* We have the same issue with the encapsulated part of a third-party packet.
|
||||
* WB2OSZ-5>APDW17,WIDE1-1,WIDE2-1:}WHO-IS>APJIW4,TCPIP,WB2OSZ-5*::WB2OSZ-7 :ack0
|
||||
*
|
||||
* We need a way to keep and retrieve the original name.
|
||||
* This gets a little messy because the packet object is in the on air frame format.
|
||||
*
|
||||
*------------------------------------------------------------------------------*/
|
||||
|
||||
#if AX25MEMDEBUG
|
||||
|
|
14
src/beacon.c
14
src/beacon.c
|
@ -162,14 +162,14 @@ void beacon_init (struct audio_s *pmodem, struct misc_config_s *pconfig, struct
|
|||
int chan = g_misc_config_p->beacon[j].sendto_chan;
|
||||
|
||||
if (chan < 0) chan = 0; /* For IGate, use channel 0 call. */
|
||||
if (chan >= MAX_CHANS) chan = 0; // For ICHANNEL, use channel 0 call.
|
||||
if (chan >= MAX_TOTAL_CHANS) chan = 0; // For ICHANNEL, use channel 0 call.
|
||||
|
||||
if (g_modem_config_p->chan_medium[chan] == MEDIUM_RADIO ||
|
||||
g_modem_config_p->chan_medium[chan] == MEDIUM_NETTNC) {
|
||||
|
||||
if (strlen(g_modem_config_p->achan[chan].mycall) > 0 &&
|
||||
strcasecmp(g_modem_config_p->achan[chan].mycall, "N0CALL") != 0 &&
|
||||
strcasecmp(g_modem_config_p->achan[chan].mycall, "NOCALL") != 0) {
|
||||
if (strlen(g_modem_config_p->mycall[chan]) > 0 &&
|
||||
strcasecmp(g_modem_config_p->mycall[chan], "N0CALL") != 0 &&
|
||||
strcasecmp(g_modem_config_p->mycall[chan], "NOCALL") != 0) {
|
||||
|
||||
switch (g_misc_config_p->beacon[j].btype) {
|
||||
|
||||
|
@ -809,10 +809,10 @@ static void beacon_send (int j, dwgps_info_t *gpsinfo)
|
|||
|
||||
if (g_modem_config_p->chan_medium[bp->sendto_chan] == MEDIUM_IGATE) { // ICHANNEL uses chan 0 mycall.
|
||||
// TODO: Maybe it should be allowed to have own.
|
||||
strlcpy (mycall, g_modem_config_p->achan[0].mycall, sizeof(mycall));
|
||||
strlcpy (mycall, g_modem_config_p->mycall[0], sizeof(mycall));
|
||||
}
|
||||
else {
|
||||
strlcpy (mycall, g_modem_config_p->achan[bp->sendto_chan].mycall, sizeof(mycall));
|
||||
strlcpy (mycall, g_modem_config_p->mycall[bp->sendto_chan], sizeof(mycall));
|
||||
}
|
||||
|
||||
if (strlen(mycall) == 0 || strcmp(mycall, "NOCALL") == 0) {
|
||||
|
@ -900,7 +900,7 @@ static void beacon_send (int j, dwgps_info_t *gpsinfo)
|
|||
|
||||
case BEACON_OBJECT:
|
||||
|
||||
encode_object (bp->objname, bp->compress, 0, bp->lat, bp->lon, bp->ambiguity,
|
||||
encode_object (bp->objname, bp->compress, 1, bp->lat, bp->lon, bp->ambiguity,
|
||||
bp->symtab, bp->symbol,
|
||||
bp->power, bp->height, bp->gain, bp->dir,
|
||||
G_UNKNOWN, G_UNKNOWN, /* course, speed */
|
||||
|
|
|
@ -76,7 +76,7 @@ static struct cdigi_config_s *save_cdigi_config_p;
|
|||
* Maintain count of packets digipeated for each combination of from/to channel.
|
||||
*/
|
||||
|
||||
static int cdigi_count[MAX_CHANS][MAX_CHANS];
|
||||
static int cdigi_count[MAX_RADIO_CHANS][MAX_RADIO_CHANS];
|
||||
|
||||
int cdigipeater_get_count (int from_chan, int to_chan) {
|
||||
return (cdigi_count[from_chan][to_chan]);
|
||||
|
@ -132,7 +132,9 @@ void cdigipeater (int from_chan, packet_t pp)
|
|||
// Connected mode is allowed only for channels with internal modem.
|
||||
// It probably wouldn't matter for digipeating but let's keep that rule simple and consistent.
|
||||
|
||||
if ( from_chan < 0 || from_chan >= MAX_CHANS || save_audio_config_p->chan_medium[from_chan] != MEDIUM_RADIO) {
|
||||
if ( from_chan < 0 || from_chan >= MAX_RADIO_CHANS ||
|
||||
(save_audio_config_p->chan_medium[from_chan] != MEDIUM_RADIO &&
|
||||
save_audio_config_p->chan_medium[from_chan] != MEDIUM_NETTNC) ) {
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf ("cdigipeater: Did not expect to receive on invalid channel %d.\n", from_chan);
|
||||
return;
|
||||
|
@ -145,13 +147,13 @@ void cdigipeater (int from_chan, packet_t pp)
|
|||
* Might not have a benefit here.
|
||||
*/
|
||||
|
||||
for (to_chan=0; to_chan<MAX_CHANS; to_chan++) {
|
||||
for (to_chan=0; to_chan<MAX_RADIO_CHANS; to_chan++) {
|
||||
if (save_cdigi_config_p->enabled[from_chan][to_chan]) {
|
||||
if (to_chan == from_chan) {
|
||||
packet_t result;
|
||||
|
||||
result = cdigipeat_match (from_chan, pp, save_audio_config_p->achan[from_chan].mycall,
|
||||
save_audio_config_p->achan[to_chan].mycall,
|
||||
result = cdigipeat_match (from_chan, pp, save_audio_config_p->mycall[from_chan],
|
||||
save_audio_config_p->mycall[to_chan],
|
||||
save_cdigi_config_p->has_alias[from_chan][to_chan],
|
||||
&(save_cdigi_config_p->alias[from_chan][to_chan]), to_chan,
|
||||
save_cdigi_config_p->cfilter_str[from_chan][to_chan]);
|
||||
|
@ -168,13 +170,13 @@ void cdigipeater (int from_chan, packet_t pp)
|
|||
* Second pass: Look at packets being digipeated to different channel.
|
||||
*/
|
||||
|
||||
for (to_chan=0; to_chan<MAX_CHANS; to_chan++) {
|
||||
for (to_chan=0; to_chan<MAX_RADIO_CHANS; to_chan++) {
|
||||
if (save_cdigi_config_p->enabled[from_chan][to_chan]) {
|
||||
if (to_chan != from_chan) {
|
||||
packet_t result;
|
||||
|
||||
result = cdigipeat_match (from_chan, pp, save_audio_config_p->achan[from_chan].mycall,
|
||||
save_audio_config_p->achan[to_chan].mycall,
|
||||
result = cdigipeat_match (from_chan, pp, save_audio_config_p->mycall[from_chan],
|
||||
save_audio_config_p->mycall[to_chan],
|
||||
save_cdigi_config_p->has_alias[from_chan][to_chan],
|
||||
&(save_cdigi_config_p->alias[from_chan][to_chan]), to_chan,
|
||||
save_cdigi_config_p->cfilter_str[from_chan][to_chan]);
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
#include "regex.h"
|
||||
|
||||
#include "direwolf.h" /* for MAX_CHANS */
|
||||
#include "direwolf.h" /* for MAX_RADIO_CHANS */
|
||||
#include "ax25_pad.h" /* for packet_t */
|
||||
#include "audio.h" /* for radio channel properties */
|
||||
|
||||
|
@ -23,17 +23,21 @@ struct cdigi_config_s {
|
|||
/*
|
||||
* Rules for each of the [from_chan][to_chan] combinations.
|
||||
*/
|
||||
int enabled[MAX_CHANS][MAX_CHANS]; // Is it enabled for from/to pair?
|
||||
|
||||
int has_alias[MAX_CHANS][MAX_CHANS]; // If there was no alias in the config file,
|
||||
// For APRS digipeater, we use MAX_TOTAL_CHANS because we use external TNCs.
|
||||
// Connected mode packet must use internal modems we we use MAX_RADIO_CHANS.
|
||||
|
||||
int enabled[MAX_RADIO_CHANS][MAX_RADIO_CHANS]; // Is it enabled for from/to pair?
|
||||
|
||||
int has_alias[MAX_RADIO_CHANS][MAX_RADIO_CHANS]; // If there was no alias in the config file,
|
||||
// the structure below will not be set up
|
||||
// properly and an attempt to use it could
|
||||
// result in a crash. (fixed v1.5)
|
||||
// Not needed for [APRS] DIGIPEAT because
|
||||
// the alias is mandatory there.
|
||||
regex_t alias[MAX_CHANS][MAX_CHANS];
|
||||
regex_t alias[MAX_RADIO_CHANS][MAX_RADIO_CHANS];
|
||||
|
||||
char *cfilter_str[MAX_CHANS][MAX_CHANS];
|
||||
char *cfilter_str[MAX_RADIO_CHANS][MAX_RADIO_CHANS];
|
||||
// NULL or optional Packet Filter strings such as "t/m".
|
||||
};
|
||||
|
||||
|
|
206
src/config.c
206
src/config.c
|
@ -763,7 +763,7 @@ void config_init (char *fname, struct audio_s *p_audio_config,
|
|||
|
||||
p_audio_config->adev[0].defined = 2; // 2 means it was done by default and not the user's config file.
|
||||
|
||||
for (channel=0; channel<MAX_CHANS; channel++) {
|
||||
for (channel=0; channel<MAX_TOTAL_CHANS; channel++) {
|
||||
int ot, it;
|
||||
|
||||
p_audio_config->chan_medium[channel] = MEDIUM_NONE; /* One or both channels will be */
|
||||
|
@ -1221,7 +1221,7 @@ void config_init (char *fname, struct audio_s *p_audio_config,
|
|||
*/
|
||||
|
||||
/*
|
||||
* CHANNEL n - Set channel for channel-specific commands.
|
||||
* CHANNEL n - Set channel for channel-specific commands. Only for modem/radio channels.
|
||||
*/
|
||||
|
||||
else if (strcasecmp(t, "CHANNEL") == 0) {
|
||||
|
@ -1233,7 +1233,7 @@ void config_init (char *fname, struct audio_s *p_audio_config,
|
|||
continue;
|
||||
}
|
||||
n = atoi(t);
|
||||
if (n >= 0 && n < MAX_CHANS) {
|
||||
if (n >= 0 && n < MAX_RADIO_CHANS) {
|
||||
|
||||
channel = n;
|
||||
|
||||
|
@ -1253,7 +1253,7 @@ void config_init (char *fname, struct audio_s *p_audio_config,
|
|||
}
|
||||
else {
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf ("Line %d: Channel number must in range of 0 to %d.\n", line, MAX_CHANS-1);
|
||||
dw_printf ("Line %d: Channel number must in range of 0 to %d.\n", line, MAX_RADIO_CHANS-1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1274,7 +1274,7 @@ void config_init (char *fname, struct audio_s *p_audio_config,
|
|||
continue;
|
||||
}
|
||||
int ichan = atoi(t);
|
||||
if (ichan >= MAX_CHANS && ichan < MAX_TOTAL_CHANS) {
|
||||
if (ichan >= MAX_RADIO_CHANS && ichan < MAX_TOTAL_CHANS) {
|
||||
|
||||
if (p_audio_config->chan_medium[ichan] == MEDIUM_NONE) {
|
||||
|
||||
|
@ -1286,15 +1286,73 @@ void config_init (char *fname, struct audio_s *p_audio_config,
|
|||
}
|
||||
else {
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf ("Line %d: ICHANNEL can't use %d because it is already in use.\n", line, ichan);
|
||||
dw_printf ("Line %d: ICHANNEL can't use channel %d because it is already in use.\n", line, ichan);
|
||||
}
|
||||
}
|
||||
else {
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf ("Line %d: ICHANNEL number must in range of %d to %d.\n", line, MAX_CHANS, MAX_TOTAL_CHANS-1);
|
||||
dw_printf ("Line %d: ICHANNEL number must in range of %d to %d.\n", line, MAX_RADIO_CHANS, MAX_TOTAL_CHANS-1);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* NCHANNEL chan addr port - Define Network TNC virtual channel.
|
||||
*
|
||||
* This allows a client application to talk to to an external TNC over TCP KISS
|
||||
* by using a channel number outside the normal range for modems.
|
||||
* This does not change the current channel number used by MODEM, PTT, etc.
|
||||
*
|
||||
* chan = direwolf channel.
|
||||
* addr = hostname or IP address of network TNC.
|
||||
* port = KISS TCP port on network TNC.
|
||||
*
|
||||
* Future: Might allow selection of channel on the network TNC.
|
||||
* For now, ignore incoming and set to 0 for outgoing.
|
||||
*
|
||||
* FIXME: Can't set mycall for nchannel.
|
||||
*/
|
||||
|
||||
else if (strcasecmp(t, "NCHANNEL") == 0) {
|
||||
t = split(NULL,0);
|
||||
if (t == NULL) {
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf ("Line %d: Missing virtual channel number for NCHANNEL command.\n", line);
|
||||
continue;
|
||||
}
|
||||
int nchan = atoi(t);
|
||||
if (nchan >= MAX_RADIO_CHANS && nchan < MAX_TOTAL_CHANS) {
|
||||
|
||||
if (p_audio_config->chan_medium[nchan] == MEDIUM_NONE) {
|
||||
|
||||
p_audio_config->chan_medium[nchan] = MEDIUM_NETTNC;
|
||||
}
|
||||
else {
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf ("Line %d: NCHANNEL can't use channel %d because it is already in use.\n", line, nchan);
|
||||
}
|
||||
}
|
||||
else {
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf ("Line %d: NCHANNEL number must in range of %d to %d.\n", line, MAX_RADIO_CHANS, MAX_TOTAL_CHANS-1);
|
||||
}
|
||||
|
||||
t = split(NULL,0);
|
||||
if (t == NULL) {
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf ("Line %d: Missing network TNC address for NCHANNEL command.\n", line);
|
||||
continue;
|
||||
}
|
||||
strlcpy (p_audio_config->nettnc_addr[nchan], t, sizeof(p_audio_config->nettnc_addr[nchan]));
|
||||
|
||||
t = split(NULL,0);
|
||||
if (t == NULL) {
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf ("Line %d: Missing network TNC TCP port for NCHANNEL command.\n", line);
|
||||
continue;
|
||||
}
|
||||
p_audio_config->nettnc_port[nchan] = atoi(t);
|
||||
}
|
||||
|
||||
/*
|
||||
* MYCALL station
|
||||
*/
|
||||
|
@ -1330,14 +1388,14 @@ void config_init (char *fname, struct audio_s *p_audio_config,
|
|||
|
||||
int c;
|
||||
|
||||
for (c = 0; c < MAX_CHANS; c++) {
|
||||
for (c = 0; c < MAX_TOTAL_CHANS; c++) {
|
||||
|
||||
if (c == channel ||
|
||||
strlen(p_audio_config->achan[c].mycall) == 0 ||
|
||||
strcasecmp(p_audio_config->achan[c].mycall, "NOCALL") == 0 ||
|
||||
strcasecmp(p_audio_config->achan[c].mycall, "N0CALL") == 0) {
|
||||
strlen(p_audio_config->mycall[c]) == 0 ||
|
||||
strcasecmp(p_audio_config->mycall[c], "NOCALL") == 0 ||
|
||||
strcasecmp(p_audio_config->mycall[c], "N0CALL") == 0) {
|
||||
|
||||
strlcpy (p_audio_config->achan[c].mycall, t, sizeof(p_audio_config->achan[c].mycall));
|
||||
strlcpy (p_audio_config->mycall[c], t, sizeof(p_audio_config->mycall[c]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2552,10 +2610,10 @@ void config_init (char *fname, struct audio_s *p_audio_config,
|
|||
continue;
|
||||
}
|
||||
from_chan = atoi(t);
|
||||
if (from_chan < 0 || from_chan >= MAX_CHANS) {
|
||||
if (from_chan < 0 || from_chan >= MAX_TOTAL_CHANS) {
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf ("Config file: FROM-channel must be in range of 0 to %d on line %d.\n",
|
||||
MAX_CHANS-1, line);
|
||||
MAX_TOTAL_CHANS-1, line);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -2582,10 +2640,10 @@ void config_init (char *fname, struct audio_s *p_audio_config,
|
|||
continue;
|
||||
}
|
||||
to_chan = atoi(t);
|
||||
if (to_chan < 0 || to_chan >= MAX_CHANS) {
|
||||
if (to_chan < 0 || to_chan >= MAX_TOTAL_CHANS) {
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf ("Config file: TO-channel must be in range of 0 to %d on line %d.\n",
|
||||
MAX_CHANS-1, line);
|
||||
MAX_TOTAL_CHANS-1, line);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -2713,10 +2771,10 @@ void config_init (char *fname, struct audio_s *p_audio_config,
|
|||
continue;
|
||||
}
|
||||
from_chan = atoi(t);
|
||||
if (from_chan < 0 || from_chan >= MAX_CHANS) {
|
||||
if (from_chan < 0 || from_chan >= MAX_RADIO_CHANS) {
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf ("Config file: FROM-channel must be in range of 0 to %d on line %d.\n",
|
||||
MAX_CHANS-1, line);
|
||||
MAX_RADIO_CHANS-1, line);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -2742,10 +2800,10 @@ void config_init (char *fname, struct audio_s *p_audio_config,
|
|||
continue;
|
||||
}
|
||||
to_chan = atoi(t);
|
||||
if (to_chan < 0 || to_chan >= MAX_CHANS) {
|
||||
if (to_chan < 0 || to_chan >= MAX_RADIO_CHANS) {
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf ("Config file: TO-channel must be in range of 0 to %d on line %d.\n",
|
||||
MAX_CHANS-1, line);
|
||||
MAX_RADIO_CHANS-1, line);
|
||||
continue;
|
||||
}
|
||||
if (p_audio_config->chan_medium[to_chan] != MEDIUM_RADIO) {
|
||||
|
@ -2787,10 +2845,10 @@ void config_init (char *fname, struct audio_s *p_audio_config,
|
|||
continue;
|
||||
}
|
||||
from_chan = atoi(t);
|
||||
if (from_chan < 0 || from_chan >= MAX_CHANS) {
|
||||
if (from_chan < 0 || from_chan >= MAX_RADIO_CHANS) {
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf ("Config file: FROM-channel must be in range of 0 to %d on line %d.\n",
|
||||
MAX_CHANS-1, line);
|
||||
MAX_RADIO_CHANS-1, line);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -2820,10 +2878,10 @@ void config_init (char *fname, struct audio_s *p_audio_config,
|
|||
continue;
|
||||
}
|
||||
to_chan = atoi(t);
|
||||
if (to_chan < 0 || to_chan >= MAX_CHANS) {
|
||||
if (to_chan < 0 || to_chan >= MAX_RADIO_CHANS) {
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf ("Config file: TO-channel must be in range of 0 to %d on line %d.\n",
|
||||
MAX_CHANS-1, line);
|
||||
MAX_RADIO_CHANS-1, line);
|
||||
continue;
|
||||
}
|
||||
if (p_audio_config->chan_medium[to_chan] != MEDIUM_RADIO) {
|
||||
|
@ -2906,7 +2964,7 @@ void config_init (char *fname, struct audio_s *p_audio_config,
|
|||
continue;
|
||||
}
|
||||
if (*t == 'i' || *t == 'I') {
|
||||
from_chan = MAX_CHANS;
|
||||
from_chan = MAX_TOTAL_CHANS;
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf ("Config file: FILTER IG ... on line %d.\n", line);
|
||||
dw_printf ("Warning! Don't mess with IS>RF filtering unless you are an expert and have an unusual situation.\n");
|
||||
|
@ -2916,10 +2974,10 @@ void config_init (char *fname, struct audio_s *p_audio_config,
|
|||
}
|
||||
else {
|
||||
from_chan = isdigit(*t) ? atoi(t) : -999;
|
||||
if (from_chan < 0 || from_chan >= MAX_CHANS) {
|
||||
if (from_chan < 0 || from_chan >= MAX_TOTAL_CHANS) {
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf ("Config file: Filter FROM-channel must be in range of 0 to %d or \"IG\" on line %d.\n",
|
||||
MAX_CHANS-1, line);
|
||||
MAX_TOTAL_CHANS-1, line);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -2945,7 +3003,7 @@ void config_init (char *fname, struct audio_s *p_audio_config,
|
|||
continue;
|
||||
}
|
||||
if (*t == 'i' || *t == 'I') {
|
||||
to_chan = MAX_CHANS;
|
||||
to_chan = MAX_TOTAL_CHANS;
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf ("Config file: FILTER ... IG ... on line %d.\n", line);
|
||||
dw_printf ("Warning! Don't mess with RF>IS filtering unless you are an expert and have an unusual situation.\n");
|
||||
|
@ -2955,10 +3013,10 @@ void config_init (char *fname, struct audio_s *p_audio_config,
|
|||
}
|
||||
else {
|
||||
to_chan = isdigit(*t) ? atoi(t) : -999;
|
||||
if (to_chan < 0 || to_chan >= MAX_CHANS) {
|
||||
if (to_chan < 0 || to_chan >= MAX_TOTAL_CHANS) {
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf ("Config file: Filter TO-channel must be in range of 0 to %d or \"IG\" on line %d.\n",
|
||||
MAX_CHANS-1, line);
|
||||
MAX_TOTAL_CHANS-1, line);
|
||||
continue;
|
||||
}
|
||||
if (p_audio_config->chan_medium[to_chan] != MEDIUM_RADIO &&
|
||||
|
@ -3020,10 +3078,10 @@ void config_init (char *fname, struct audio_s *p_audio_config,
|
|||
}
|
||||
|
||||
from_chan = isdigit(*t) ? atoi(t) : -999;
|
||||
if (from_chan < 0 || from_chan >= MAX_CHANS) {
|
||||
if (from_chan < 0 || from_chan >= MAX_RADIO_CHANS) {
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf ("Config file: Filter FROM-channel must be in range of 0 to %d on line %d.\n",
|
||||
MAX_CHANS-1, line);
|
||||
MAX_RADIO_CHANS-1, line);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -3045,10 +3103,10 @@ void config_init (char *fname, struct audio_s *p_audio_config,
|
|||
}
|
||||
|
||||
to_chan = isdigit(*t) ? atoi(t) : -999;
|
||||
if (to_chan < 0 || to_chan >= MAX_CHANS) {
|
||||
if (to_chan < 0 || to_chan >= MAX_RADIO_CHANS) {
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf ("Config file: Filter TO-channel must be in range of 0 to %d on line %d.\n",
|
||||
MAX_CHANS-1, line);
|
||||
MAX_RADIO_CHANS-1, line);
|
||||
continue;
|
||||
}
|
||||
if (p_audio_config->chan_medium[to_chan] != MEDIUM_RADIO) {
|
||||
|
@ -4205,10 +4263,10 @@ void config_init (char *fname, struct audio_s *p_audio_config,
|
|||
}
|
||||
|
||||
r = atoi(t);
|
||||
if (r < 0 || r > MAX_CHANS-1) {
|
||||
if (r < 0 || r > MAX_RADIO_CHANS-1) {
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf ("Config file: DTMF receive channel must be in range of 0 to %d on line %d.\n",
|
||||
MAX_CHANS-1, line);
|
||||
MAX_RADIO_CHANS-1, line);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -4236,9 +4294,9 @@ void config_init (char *fname, struct audio_s *p_audio_config,
|
|||
|
||||
if (isdigit(*p)) {
|
||||
x = *p - '0';
|
||||
if (x < 0 || x > MAX_CHANS-1) {
|
||||
if (x < 0 || x > MAX_TOTAL_CHANS-1) {
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf ("Config file: Transmit channel must be in range of 0 to %d on line %d.\n", MAX_CHANS-1, line);
|
||||
dw_printf ("Config file: Transmit channel must be in range of 0 to %d on line %d.\n", MAX_TOTAL_CHANS-1, line);
|
||||
x = -1;
|
||||
}
|
||||
else if (p_audio_config->chan_medium[x] != MEDIUM_RADIO &&
|
||||
|
@ -4528,10 +4586,10 @@ void config_init (char *fname, struct audio_s *p_audio_config,
|
|||
}
|
||||
|
||||
n = atoi(t);
|
||||
if (n < 0 || n > MAX_CHANS-1) {
|
||||
if (n < 0 || n > MAX_TOTAL_CHANS-1) {
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf ("Config file: Transmit channel must be in range of 0 to %d on line %d.\n",
|
||||
MAX_CHANS-1, line);
|
||||
MAX_TOTAL_CHANS-1, line);
|
||||
continue;
|
||||
}
|
||||
p_igate_config->tx_chan = n;
|
||||
|
@ -4797,9 +4855,9 @@ void config_init (char *fname, struct audio_s *p_audio_config,
|
|||
t = split(NULL,0);
|
||||
if (t != NULL) {
|
||||
chan = atoi(t);
|
||||
if (chan < 0 || chan >= MAX_CHANS) {
|
||||
if (chan < 0 || chan >= MAX_TOTAL_CHANS) {
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf ("Line %d: Invalid channel %d for KISSPORT command. Must be in range 0 thru %d.\n", line, chan, MAX_CHANS-1);
|
||||
dw_printf ("Line %d: Invalid channel %d for KISSPORT command. Must be in range 0 thru %d.\n", line, chan, MAX_TOTAL_CHANS-1);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
@ -5510,25 +5568,25 @@ void config_init (char *fname, struct audio_s *p_audio_config,
|
|||
*/
|
||||
int i, j, k, b;
|
||||
|
||||
for (i=0; i<MAX_CHANS; i++) {
|
||||
for (j=0; j<MAX_CHANS; j++) {
|
||||
for (i=0; i<MAX_TOTAL_CHANS; i++) {
|
||||
for (j=0; j<MAX_TOTAL_CHANS; j++) {
|
||||
|
||||
/* APRS digipeating. */
|
||||
|
||||
if (p_digi_config->enabled[i][j]) {
|
||||
|
||||
if ( strcmp(p_audio_config->achan[i].mycall, "") == 0 ||
|
||||
strcmp(p_audio_config->achan[i].mycall, "NOCALL") == 0 ||
|
||||
strcmp(p_audio_config->achan[i].mycall, "N0CALL") == 0) {
|
||||
if ( strcmp(p_audio_config->mycall[i], "") == 0 ||
|
||||
strcmp(p_audio_config->mycall[i], "NOCALL") == 0 ||
|
||||
strcmp(p_audio_config->mycall[i], "N0CALL") == 0) {
|
||||
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf ("Config file: MYCALL must be set for receive channel %d before digipeating is allowed.\n", i);
|
||||
p_digi_config->enabled[i][j] = 0;
|
||||
}
|
||||
|
||||
if ( strcmp(p_audio_config->achan[j].mycall, "") == 0 ||
|
||||
strcmp(p_audio_config->achan[j].mycall, "NOCALL") == 0 ||
|
||||
strcmp(p_audio_config->achan[j].mycall, "N0CALL") == 0) {
|
||||
if ( strcmp(p_audio_config->mycall[j], "") == 0 ||
|
||||
strcmp(p_audio_config->mycall[j], "NOCALL") == 0 ||
|
||||
strcmp(p_audio_config->mycall[j], "N0CALL") == 0) {
|
||||
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf ("Config file: MYCALL must be set for transmit channel %d before digipeating is allowed.\n", i);
|
||||
|
@ -5550,20 +5608,20 @@ void config_init (char *fname, struct audio_s *p_audio_config,
|
|||
|
||||
/* Connected mode digipeating. */
|
||||
|
||||
if (p_cdigi_config->enabled[i][j]) {
|
||||
if (i < MAX_RADIO_CHANS && j < MAX_RADIO_CHANS && p_cdigi_config->enabled[i][j]) {
|
||||
|
||||
if ( strcmp(p_audio_config->achan[i].mycall, "") == 0 ||
|
||||
strcmp(p_audio_config->achan[i].mycall, "NOCALL") == 0 ||
|
||||
strcmp(p_audio_config->achan[i].mycall, "N0CALL") == 0) {
|
||||
if ( strcmp(p_audio_config->mycall[i], "") == 0 ||
|
||||
strcmp(p_audio_config->mycall[i], "NOCALL") == 0 ||
|
||||
strcmp(p_audio_config->mycall[i], "N0CALL") == 0) {
|
||||
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf ("Config file: MYCALL must be set for receive channel %d before digipeating is allowed.\n", i);
|
||||
p_cdigi_config->enabled[i][j] = 0;
|
||||
}
|
||||
|
||||
if ( strcmp(p_audio_config->achan[j].mycall, "") == 0 ||
|
||||
strcmp(p_audio_config->achan[j].mycall, "NOCALL") == 0 ||
|
||||
strcmp(p_audio_config->achan[j].mycall, "N0CALL") == 0) {
|
||||
if ( strcmp(p_audio_config->mycall[j], "") == 0 ||
|
||||
strcmp(p_audio_config->mycall[j], "NOCALL") == 0 ||
|
||||
strcmp(p_audio_config->mycall[j], "N0CALL") == 0) {
|
||||
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf ("Config file: MYCALL must be set for transmit channel %d before digipeating is allowed.\n", i);
|
||||
|
@ -5587,7 +5645,7 @@ void config_init (char *fname, struct audio_s *p_audio_config,
|
|||
if (strlen(p_igate_config->t2_login) > 0 &&
|
||||
(p_audio_config->chan_medium[i] == MEDIUM_RADIO || p_audio_config->chan_medium[i] == MEDIUM_NETTNC)) {
|
||||
|
||||
if (strcmp(p_audio_config->achan[i].mycall, "NOCALL") == 0 || strcmp(p_audio_config->achan[i].mycall, "N0CALL") == 0) {
|
||||
if (strcmp(p_audio_config->mycall[i], "NOCALL") == 0 || strcmp(p_audio_config->mycall[i], "N0CALL") == 0) {
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf ("Config file: MYCALL must be set for receive channel %d before Rx IGate is allowed.\n", i);
|
||||
strlcpy (p_igate_config->t2_login, "", sizeof(p_igate_config->t2_login));
|
||||
|
@ -5595,9 +5653,9 @@ void config_init (char *fname, struct audio_s *p_audio_config,
|
|||
// Currently we can have only one transmit channel.
|
||||
// This might be generalized someday to allow more.
|
||||
if (p_igate_config->tx_chan >= 0 &&
|
||||
( strcmp(p_audio_config->achan[p_igate_config->tx_chan].mycall, "") == 0 ||
|
||||
strcmp(p_audio_config->achan[p_igate_config->tx_chan].mycall, "NOCALL") == 0 ||
|
||||
strcmp(p_audio_config->achan[p_igate_config->tx_chan].mycall, "N0CALL") == 0)) {
|
||||
( strcmp(p_audio_config->mycall[p_igate_config->tx_chan], "") == 0 ||
|
||||
strcmp(p_audio_config->mycall[p_igate_config->tx_chan], "NOCALL") == 0 ||
|
||||
strcmp(p_audio_config->mycall[p_igate_config->tx_chan], "N0CALL") == 0)) {
|
||||
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf ("Config file: MYCALL must be set for transmit channel %d before Tx IGate is allowed.\n", i);
|
||||
|
@ -5610,10 +5668,10 @@ void config_init (char *fname, struct audio_s *p_audio_config,
|
|||
// This will handle eventual case of multiple transmit channels.
|
||||
|
||||
if (strlen(p_igate_config->t2_login) > 0) {
|
||||
for (j=0; j<MAX_CHANS; j++) {
|
||||
for (j=0; j<MAX_TOTAL_CHANS; j++) {
|
||||
if (p_audio_config->chan_medium[j] == MEDIUM_RADIO || p_audio_config->chan_medium[j] == MEDIUM_NETTNC) {
|
||||
if (p_digi_config->filter_str[MAX_CHANS][j] == NULL) {
|
||||
p_digi_config->filter_str[MAX_CHANS][j] = strdup("i/180");
|
||||
if (p_digi_config->filter_str[MAX_TOTAL_CHANS][j] == NULL) {
|
||||
p_digi_config->filter_str[MAX_TOTAL_CHANS][j] = strdup("i/180");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5746,7 +5804,7 @@ static int beacon_options(char *cmd, struct beacon_s *b, int line, struct audio_
|
|||
}
|
||||
else if (value[0] == 'r' || value[0] == 'R') {
|
||||
int n = atoi(value+1);
|
||||
if (( n < 0 || n >= MAX_CHANS || p_audio_config->chan_medium[n] == MEDIUM_NONE)
|
||||
if (( n < 0 || n >= MAX_TOTAL_CHANS || p_audio_config->chan_medium[n] == MEDIUM_NONE)
|
||||
&& p_audio_config->chan_medium[n] != MEDIUM_IGATE) {
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf ("Config file, line %d: Simulated receive on channel %d is not valid.\n", line, n);
|
||||
|
@ -5757,7 +5815,7 @@ static int beacon_options(char *cmd, struct beacon_s *b, int line, struct audio_
|
|||
}
|
||||
else if (value[0] == 't' || value[0] == 'T' || value[0] == 'x' || value[0] == 'X') {
|
||||
int n = atoi(value+1);
|
||||
if (( n < 0 || n >= MAX_CHANS || p_audio_config->chan_medium[n] == MEDIUM_NONE)
|
||||
if (( n < 0 || n >= MAX_TOTAL_CHANS || p_audio_config->chan_medium[n] == MEDIUM_NONE)
|
||||
&& p_audio_config->chan_medium[n] != MEDIUM_IGATE) {
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf ("Config file, line %d: Send to channel %d is not valid.\n", line, n);
|
||||
|
@ -5769,7 +5827,7 @@ static int beacon_options(char *cmd, struct beacon_s *b, int line, struct audio_
|
|||
}
|
||||
else {
|
||||
int n = atoi(value);
|
||||
if (( n < 0 || n >= MAX_CHANS || p_audio_config->chan_medium[n] == MEDIUM_NONE)
|
||||
if (( n < 0 || n >= MAX_TOTAL_CHANS || p_audio_config->chan_medium[n] == MEDIUM_NONE)
|
||||
&& p_audio_config->chan_medium[n] != MEDIUM_IGATE) {
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf ("Config file, line %d: Send to channel %d is not valid.\n", line, n);
|
||||
|
@ -6020,7 +6078,7 @@ static int beacon_options(char *cmd, struct beacon_s *b, int line, struct audio_
|
|||
|
||||
if (b->sendto_type == SENDTO_XMIT) {
|
||||
|
||||
if (( b->sendto_chan < 0 || b->sendto_chan >= MAX_CHANS || p_audio_config->chan_medium[b->sendto_chan] == MEDIUM_NONE)
|
||||
if (( b->sendto_chan < 0 || b->sendto_chan >= MAX_TOTAL_CHANS || p_audio_config->chan_medium[b->sendto_chan] == MEDIUM_NONE)
|
||||
&& p_audio_config->chan_medium[b->sendto_chan] != MEDIUM_IGATE) {
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf ("Config file, line %d: Send to channel %d is not valid.\n", line, b->sendto_chan);
|
||||
|
@ -6029,18 +6087,18 @@ static int beacon_options(char *cmd, struct beacon_s *b, int line, struct audio_
|
|||
|
||||
if (p_audio_config->chan_medium[b->sendto_chan] == MEDIUM_IGATE) { // Prevent subscript out of bounds.
|
||||
// Will be using call from chan 0 later.
|
||||
if ( strcmp(p_audio_config->achan[0].mycall, "") == 0 ||
|
||||
strcmp(p_audio_config->achan[0].mycall, "NOCALL") == 0 ||
|
||||
strcmp(p_audio_config->achan[0].mycall, "N0CALL") == 0 ) {
|
||||
if ( strcmp(p_audio_config->mycall[0], "") == 0 ||
|
||||
strcmp(p_audio_config->mycall[0], "NOCALL") == 0 ||
|
||||
strcmp(p_audio_config->mycall[0], "N0CALL") == 0 ) {
|
||||
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf ("Config file: MYCALL must be set for channel %d before beaconing is allowed.\n", 0);
|
||||
return (0);
|
||||
}
|
||||
} else {
|
||||
if ( strcmp(p_audio_config->achan[b->sendto_chan].mycall, "") == 0 ||
|
||||
strcmp(p_audio_config->achan[b->sendto_chan].mycall, "NOCALL") == 0 ||
|
||||
strcmp(p_audio_config->achan[b->sendto_chan].mycall, "N0CALL") == 0 ) {
|
||||
if ( strcmp(p_audio_config->mycall[b->sendto_chan], "") == 0 ||
|
||||
strcmp(p_audio_config->mycall[b->sendto_chan], "NOCALL") == 0 ||
|
||||
strcmp(p_audio_config->mycall[b->sendto_chan], "N0CALL") == 0 ) {
|
||||
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf ("Config file: MYCALL must be set for channel %d before beaconing is allowed.\n", b->sendto_chan);
|
||||
|
|
|
@ -30,7 +30,7 @@ enum sendto_type_e { SENDTO_XMIT, SENDTO_IGATE, SENDTO_RECV };
|
|||
|
||||
|
||||
#define MAX_BEACONS 30
|
||||
#define MAX_KISS_TCP_PORTS (MAX_CHANS+1)
|
||||
#define MAX_KISS_TCP_PORTS (MAX_RADIO_CHANS+1)
|
||||
|
||||
struct misc_config_s {
|
||||
|
||||
|
|
|
@ -1652,7 +1652,7 @@ static void aprs_mic_e (decode_aprs_t *A, packet_t pp, unsigned char *info, int
|
|||
// It is essential to keep trailing spaces. e.g. VX-8 suffix is "_ "
|
||||
|
||||
char mcomment[256];
|
||||
strlcpy (mcomment, info + sizeof(struct aprs_mic_e_s), sizeof(mcomment));
|
||||
strlcpy (mcomment, ((char*)info) + sizeof(struct aprs_mic_e_s), sizeof(mcomment));
|
||||
if (mcomment[strlen(mcomment)-1] == '\r') {
|
||||
mcomment[strlen(mcomment)-1] = '\0';
|
||||
}
|
||||
|
|
18
src/demod.c
18
src/demod.c
|
@ -63,11 +63,11 @@ static struct audio_s *save_audio_config_p;
|
|||
|
||||
// Current state of all the decoders.
|
||||
|
||||
static struct demodulator_state_s demodulator_state[MAX_CHANS][MAX_SUBCHANS];
|
||||
static struct demodulator_state_s demodulator_state[MAX_RADIO_CHANS][MAX_SUBCHANS];
|
||||
|
||||
|
||||
static int sample_sum[MAX_CHANS][MAX_SUBCHANS];
|
||||
static int sample_count[MAX_CHANS][MAX_SUBCHANS];
|
||||
static int sample_sum[MAX_RADIO_CHANS][MAX_SUBCHANS];
|
||||
static int sample_count[MAX_RADIO_CHANS][MAX_SUBCHANS];
|
||||
|
||||
|
||||
/*------------------------------------------------------------------
|
||||
|
@ -100,7 +100,7 @@ int demod_init (struct audio_s *pa)
|
|||
|
||||
save_audio_config_p = pa;
|
||||
|
||||
for (chan = 0; chan < MAX_CHANS; chan++) {
|
||||
for (chan = 0; chan < MAX_RADIO_CHANS; chan++) {
|
||||
|
||||
if (save_audio_config_p->chan_medium[chan] == MEDIUM_RADIO) {
|
||||
|
||||
|
@ -812,7 +812,7 @@ int demod_init (struct audio_s *pa)
|
|||
|
||||
// Now the virtual channels. FIXME: could be single loop.
|
||||
|
||||
for (chan = MAX_CHANS; chan < MAX_TOTAL_CHANS; chan++) {
|
||||
for (chan = MAX_RADIO_CHANS; chan < MAX_TOTAL_CHANS; chan++) {
|
||||
|
||||
// FIXME dw_printf ("-------- virtual channel loop %d \n", chan);
|
||||
|
||||
|
@ -927,7 +927,7 @@ int demod_get_sample (int a)
|
|||
*
|
||||
*--------------------------------------------------------------------*/
|
||||
|
||||
static volatile int mute_input[MAX_CHANS];
|
||||
static volatile int mute_input[MAX_RADIO_CHANS];
|
||||
|
||||
// New in 1.7.
|
||||
// A few people have a really bad audio cross talk situation where they receive their own transmissions.
|
||||
|
@ -939,7 +939,7 @@ static volatile int mute_input[MAX_CHANS];
|
|||
|
||||
void demod_mute_input (int chan, int mute_during_xmit)
|
||||
{
|
||||
assert (chan >= 0 && chan < MAX_CHANS);
|
||||
assert (chan >= 0 && chan < MAX_RADIO_CHANS);
|
||||
mute_input[chan] = mute_during_xmit;
|
||||
}
|
||||
|
||||
|
@ -952,7 +952,7 @@ void demod_process_sample (int chan, int subchan, int sam)
|
|||
|
||||
struct demodulator_state_s *D;
|
||||
|
||||
assert (chan >= 0 && chan < MAX_CHANS);
|
||||
assert (chan >= 0 && chan < MAX_RADIO_CHANS);
|
||||
assert (subchan >= 0 && subchan < MAX_SUBCHANS);
|
||||
|
||||
if (mute_input[chan]) {
|
||||
|
@ -1066,7 +1066,7 @@ alevel_t demod_get_audio_level (int chan, int subchan)
|
|||
struct demodulator_state_s *D;
|
||||
alevel_t alevel;
|
||||
|
||||
assert (chan >= 0 && chan < MAX_CHANS);
|
||||
assert (chan >= 0 && chan < MAX_RADIO_CHANS);
|
||||
assert (subchan >= 0 && subchan < MAX_SUBCHANS);
|
||||
|
||||
/* We have to consider two different cases here. */
|
||||
|
|
|
@ -395,7 +395,7 @@ void demod_9600_process_sample (int chan, int sam, int upsample, struct demodula
|
|||
|
||||
int subchan = 0;
|
||||
|
||||
assert (chan >= 0 && chan < MAX_CHANS);
|
||||
assert (chan >= 0 && chan < MAX_RADIO_CHANS);
|
||||
assert (subchan >= 0 && subchan < MAX_SUBCHANS);
|
||||
|
||||
/* Scale to nice number for convenience. */
|
||||
|
@ -611,7 +611,10 @@ inline static void nudge_pll (int chan, int subchan, int slice, float demod_out_
|
|||
|
||||
/* Overflow. Was large positive, wrapped around, now large negative. */
|
||||
|
||||
hdlc_rec_bit (chan, subchan, slice, demod_out_f > 0, D->modem_type == MODEM_SCRAMBLE, D->slicer[slice].lfsr);
|
||||
hdlc_rec_bit_new (chan, subchan, slice, demod_out_f > 0, D->modem_type == MODEM_SCRAMBLE, D->slicer[slice].lfsr,
|
||||
&(D->slicer[slice].pll_nudge_total), &(D->slicer[slice].pll_symbol_count));
|
||||
D->slicer[slice].pll_symbol_count++;
|
||||
|
||||
pll_dcd_each_symbol2 (D, chan, subchan, slice);
|
||||
}
|
||||
|
||||
|
@ -627,12 +630,14 @@ inline static void nudge_pll (int chan, int subchan, int slice, float demod_out_
|
|||
|
||||
float target = D->pll_step_per_sample * demod_out_f / (demod_out_f - D->slicer[slice].prev_demod_out_f);
|
||||
|
||||
signed int before = (signed int)(D->slicer[slice].data_clock_pll); // Treat as signed.
|
||||
if (D->slicer[slice].data_detect) {
|
||||
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 + target * (1.0f - D->pll_searching_inertia) );
|
||||
}
|
||||
D->slicer[slice].pll_nudge_total += (int64_t)((signed int)(D->slicer[slice].data_clock_pll)) - (int64_t)before;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -609,7 +609,7 @@ void demod_afsk_process_sample (int chan, int subchan, int sam, struct demodulat
|
|||
static int seq = 0; /* for log file name */
|
||||
#endif
|
||||
|
||||
assert (chan >= 0 && chan < MAX_CHANS);
|
||||
assert (chan >= 0 && chan < MAX_RADIO_CHANS);
|
||||
assert (subchan >= 0 && subchan < MAX_SUBCHANS);
|
||||
|
||||
/*
|
||||
|
|
116
src/demod_psk.c
116
src/demod_psk.c
|
@ -72,6 +72,9 @@
|
|||
* V.26 has two variations, A and B. Initially I implemented the A alternative.
|
||||
* It later turned out that the MFJ-2400 used the B alternative. In version 1.6 you have a
|
||||
* choice between compatibility with MFJ (and probably the others) or the original implementation.
|
||||
* The B alternative works a little more reliably, perhaps because there is never a
|
||||
* zero phase difference between adjacent symbols.
|
||||
* Eventually the A alternative might disappear to reduce confusion.
|
||||
*
|
||||
*---------------------------------------------------------------*/
|
||||
|
||||
|
@ -94,7 +97,7 @@
|
|||
#include "fsk_demod_state.h" // Values above override defaults.
|
||||
|
||||
#include "audio.h"
|
||||
#include "tune.h"
|
||||
//#include "tune.h" // obsolete. eventually remove all references.
|
||||
#include "fsk_gen_filter.h"
|
||||
#include "hdlc_rec.h"
|
||||
#include "textcolor.h"
|
||||
|
@ -102,7 +105,13 @@
|
|||
#include "dsp.h"
|
||||
|
||||
|
||||
|
||||
#define TUNE(envvar,param,name,fmt) { \
|
||||
char *e = getenv(envvar); \
|
||||
if (e != NULL) { \
|
||||
param = atof(e); \
|
||||
text_color_set (DW_COLOR_ERROR); \
|
||||
dw_printf ("TUNE: " name " = " fmt "\n", param); \
|
||||
} }
|
||||
|
||||
|
||||
static const int phase_to_gray_v26[4] = {0, 1, 3, 2};
|
||||
|
@ -202,9 +211,10 @@ void demod_psk_init (enum modem_t modem_type, enum v26_e v26_alt, int samples_pe
|
|||
D->num_slicers = 1; // Haven't thought about this yet. Is it even applicable?
|
||||
|
||||
|
||||
#ifdef TUNE_PROFILE
|
||||
profile = TUNE_PROFILE;
|
||||
#endif
|
||||
//#ifdef TUNE_PROFILE
|
||||
// profile = TUNE_PROFILE;
|
||||
//#endif
|
||||
TUNE("TUNE_PROFILE", profile, "profile", "%c")
|
||||
|
||||
if (modem_type == MODEM_QPSK) {
|
||||
|
||||
|
@ -290,9 +300,16 @@ void demod_psk_init (enum modem_t modem_type, enum v26_e v26_alt, int samples_pe
|
|||
|
||||
D->u.psk.delay_line_width_sym = 1.25; // Delay line > 13/12 * symbol period
|
||||
|
||||
// JWL experiment 11-7. Should delay be based on audio freq rather than baud?
|
||||
#if 0 // experiment made things much worse. 55 went down to 21.
|
||||
D->u.psk.coffs = (int) round( (11.f / 12.f) * (float)samples_per_sec / (float)carrier_freq );
|
||||
D->u.psk.boffs = (int) round( (float)samples_per_sec / (float)carrier_freq );
|
||||
D->u.psk.soffs = (int) round( (13.f / 12.f) * (float)samples_per_sec / (float)carrier_freq );
|
||||
#else
|
||||
D->u.psk.coffs = (int) round( (11.f / 12.f) * (float)samples_per_sec / (float)correct_baud );
|
||||
D->u.psk.boffs = (int) round( (float)samples_per_sec / (float)correct_baud );
|
||||
D->u.psk.soffs = (int) round( (13.f / 12.f) * (float)samples_per_sec / (float)correct_baud );
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
|
||||
|
@ -393,26 +410,40 @@ void demod_psk_init (enum modem_t modem_type, enum v26_e v26_alt, int samples_pe
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef TUNE_PRE_BAUD
|
||||
D->u.psk.prefilter_baud = TUNE_PRE_BAUD;
|
||||
#endif
|
||||
#ifdef TUNE_PRE_WINDOW
|
||||
D->u.psk.pre_window = TUNE_PRE_WINDOW;
|
||||
#endif
|
||||
//#ifdef TUNE_PRE_BAUD
|
||||
// D->u.psk.prefilter_baud = TUNE_PRE_BAUD;
|
||||
//#endif
|
||||
TUNE("TUNE_PRE_BAUD", D->u.psk.prefilter_baud, "prefilter_baud", "%.3f")
|
||||
|
||||
#ifdef TUNE_LPF_BAUD
|
||||
D->u.psk.lpf_baud = TUNE_LPF_BAUD;
|
||||
#endif
|
||||
#ifdef TUNE_LP_WINDOW
|
||||
D->u.psk.lp_window = TUNE_LP_WINDOW;
|
||||
#endif
|
||||
//#ifdef TUNE_PRE_WINDOW
|
||||
// D->u.psk.pre_window = TUNE_PRE_WINDOW;
|
||||
//#endif
|
||||
TUNE("TUNE_PRE_WINDOW", D->u.psk.pre_window, "pre_window", "%d")
|
||||
|
||||
#if defined(TUNE_PLL_SEARCHING)
|
||||
D->pll_searching_inertia = TUNE_PLL_SEARCHING;
|
||||
#endif
|
||||
#if defined(TUNE_PLL_LOCKED)
|
||||
D->pll_locked_inertia = TUNE_PLL_LOCKED;
|
||||
#endif
|
||||
//#ifdef TUNE_LPF_BAUD
|
||||
// D->u.psk.lpf_baud = TUNE_LPF_BAUD;
|
||||
//#endif
|
||||
//#ifdef TUNE_LP_WINDOW
|
||||
// D->u.psk.lp_window = TUNE_LP_WINDOW;
|
||||
//#endif
|
||||
TUNE("TUNE_LPF_BAUD", D->u.psk.lpf_baud, "lpf_baud", "%.3f")
|
||||
TUNE("TUNE_LP_WINDOW", D->u.psk.lp_window, "lp_window", "%d")
|
||||
|
||||
|
||||
TUNE("TUNE_LP_FILTER_WIDTH_SYM", D->u.psk.lp_filter_width_sym, "lp_filter_width_sym", "%.3f")
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//#if defined(TUNE_PLL_SEARCHING)
|
||||
// D->pll_searching_inertia = TUNE_PLL_SEARCHING;
|
||||
//#endif
|
||||
//#if defined(TUNE_PLL_LOCKED)
|
||||
// D->pll_locked_inertia = TUNE_PLL_LOCKED;
|
||||
//#endif
|
||||
TUNE("TUNE_PLL_LOCKED", D->pll_locked_inertia, "pll_locked_inertia", "%.2f")
|
||||
TUNE("TUNE_PLL_SEARCHING", D->pll_searching_inertia, "pll_searching_inertia", "%.2f")
|
||||
|
||||
|
||||
/*
|
||||
|
@ -427,17 +458,24 @@ void demod_psk_init (enum modem_t modem_type, enum v26_e v26_alt, int samples_pe
|
|||
*/
|
||||
|
||||
D->u.psk.pre_filter_taps = (int) round( D->u.psk.pre_filter_width_sym * (float)samples_per_sec / (float)correct_baud );
|
||||
|
||||
// JWL experiment 11/7 - Should delay line be based on audio frequency?
|
||||
D->u.psk.delay_line_taps = (int) round( D->u.psk.delay_line_width_sym * (float)samples_per_sec / (float)correct_baud );
|
||||
D->u.psk.delay_line_taps = (int) round( D->u.psk.delay_line_width_sym * (float)samples_per_sec / (float)correct_baud );
|
||||
|
||||
|
||||
D->u.psk.lp_filter_taps = (int) round( D->u.psk.lp_filter_width_sym * (float)samples_per_sec / (float)correct_baud );
|
||||
|
||||
|
||||
#ifdef TUNE_PRE_FILTER_TAPS
|
||||
D->u.psk.pre_filter_taps = TUNE_PRE_FILTER_TAPS;
|
||||
#endif
|
||||
//#ifdef TUNE_PRE_FILTER_TAPS
|
||||
// D->u.psk.pre_filter_taps = TUNE_PRE_FILTER_TAPS;
|
||||
//#endif
|
||||
TUNE("TUNE_PRE_FILTER_TAPS", D->u.psk.pre_filter_taps, "pre_filter_taps", "%d")
|
||||
|
||||
#ifdef TUNE_lp_filter_taps
|
||||
D->u.psk.lp_filter_taps = TUNE_lp_filter_taps;
|
||||
#endif
|
||||
//#ifdef TUNE_lp_filter_taps
|
||||
// D->u.psk.lp_filter_taps = TUNE_lp_filter_taps;
|
||||
//#endif
|
||||
TUNE("TUNE_LP_FILTER_TAPS", D->u.psk.lp_filter_taps, "lp_filter_taps (FIR)", "%d")
|
||||
|
||||
|
||||
if (D->u.psk.pre_filter_taps > MAX_FILTER_SIZE) {
|
||||
|
@ -665,7 +703,7 @@ void demod_psk_process_sample (int chan, int subchan, int sam, struct demodulato
|
|||
{
|
||||
int slice = 0; // Would it make sense to have more than one?
|
||||
|
||||
assert (chan >= 0 && chan < MAX_CHANS);
|
||||
assert (chan >= 0 && chan < MAX_RADIO_CHANS);
|
||||
assert (subchan >= 0 && subchan < MAX_SUBCHANS);
|
||||
|
||||
/* Scale to nice number for plotting during debug. */
|
||||
|
@ -800,16 +838,22 @@ static void nudge_pll (int chan, int subchan, int slice, int demod_bits, struct
|
|||
|
||||
int gray = demod_bits;
|
||||
|
||||
hdlc_rec_bit (chan, subchan, slice, (gray >> 1) & 1, 0, bit_quality[1]);
|
||||
hdlc_rec_bit (chan, subchan, slice, gray & 1, 0, bit_quality[0]);
|
||||
hdlc_rec_bit_new (chan, subchan, slice, (gray >> 1) & 1, 0, bit_quality[1],
|
||||
&(D->slicer[slice].pll_nudge_total), &(D->slicer[slice].pll_symbol_count));
|
||||
hdlc_rec_bit_new (chan, subchan, slice, gray & 1, 0, bit_quality[0],
|
||||
&(D->slicer[slice].pll_nudge_total), &(D->slicer[slice].pll_symbol_count));
|
||||
}
|
||||
else {
|
||||
int gray = demod_bits;
|
||||
|
||||
hdlc_rec_bit (chan, subchan, slice, (gray >> 2) & 1, 0, bit_quality[2]);
|
||||
hdlc_rec_bit (chan, subchan, slice, (gray >> 1) & 1, 0, bit_quality[1]);
|
||||
hdlc_rec_bit (chan, subchan, slice, gray & 1, 0, bit_quality[0]);
|
||||
hdlc_rec_bit_new (chan, subchan, slice, (gray >> 2) & 1, 0, bit_quality[2],
|
||||
&(D->slicer[slice].pll_nudge_total), &(D->slicer[slice].pll_symbol_count));
|
||||
hdlc_rec_bit_new (chan, subchan, slice, (gray >> 1) & 1, 0, bit_quality[1],
|
||||
&(D->slicer[slice].pll_nudge_total), &(D->slicer[slice].pll_symbol_count));
|
||||
hdlc_rec_bit_new (chan, subchan, slice, gray & 1, 0, bit_quality[0],
|
||||
&(D->slicer[slice].pll_nudge_total), &(D->slicer[slice].pll_symbol_count));
|
||||
}
|
||||
D->slicer[slice].pll_symbol_count++;
|
||||
pll_dcd_each_symbol2 (D, chan, subchan, slice);
|
||||
}
|
||||
|
||||
|
@ -826,12 +870,14 @@ static void nudge_pll (int chan, int subchan, int slice, int demod_bits, struct
|
|||
|
||||
pll_dcd_signal_transition2 (D, slice, D->slicer[slice].data_clock_pll);
|
||||
|
||||
signed int before = (signed int)(D->slicer[slice].data_clock_pll); // Treat as signed.
|
||||
if (D->slicer[slice].data_detect) {
|
||||
D->slicer[slice].data_clock_pll = (int)floorf((float)(D->slicer[slice].data_clock_pll) * D->pll_locked_inertia);
|
||||
}
|
||||
else {
|
||||
D->slicer[slice].data_clock_pll = (int)floorf((float)(D->slicer[slice].data_clock_pll) * D->pll_searching_inertia);
|
||||
}
|
||||
D->slicer[slice].pll_nudge_total += (int64_t)((signed int)(D->slicer[slice].data_clock_pll)) - (int64_t)before;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -91,7 +91,7 @@ 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];
|
||||
static int digi_count[MAX_TOTAL_CHANS][MAX_TOTAL_CHANS];
|
||||
|
||||
int digipeater_get_count (int from_chan, int to_chan) {
|
||||
return (digi_count[from_chan][to_chan]);
|
||||
|
@ -154,7 +154,7 @@ void digipeater (int from_chan, packet_t pp)
|
|||
|
||||
// Network TNC is OK for UI frames where we don't care about timing.
|
||||
|
||||
if ( from_chan < 0 || from_chan >= MAX_CHANS ||
|
||||
if ( from_chan < 0 || from_chan >= MAX_TOTAL_CHANS ||
|
||||
(save_audio_config_p->chan_medium[from_chan] != MEDIUM_RADIO &&
|
||||
save_audio_config_p->chan_medium[from_chan] != MEDIUM_NETTNC)) {
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
|
@ -195,13 +195,13 @@ void digipeater (int from_chan, packet_t pp)
|
|||
*
|
||||
*/
|
||||
|
||||
for (to_chan=0; to_chan<MAX_CHANS; to_chan++) {
|
||||
for (to_chan=0; to_chan<MAX_TOTAL_CHANS; to_chan++) {
|
||||
if (save_digi_config_p->enabled[from_chan][to_chan]) {
|
||||
if (to_chan == from_chan) {
|
||||
packet_t result;
|
||||
|
||||
result = digipeat_match (from_chan, pp, save_audio_config_p->achan[from_chan].mycall,
|
||||
save_audio_config_p->achan[to_chan].mycall,
|
||||
result = digipeat_match (from_chan, pp, save_audio_config_p->mycall[from_chan],
|
||||
save_audio_config_p->mycall[to_chan],
|
||||
&save_digi_config_p->alias[from_chan][to_chan], &save_digi_config_p->wide[from_chan][to_chan],
|
||||
to_chan, save_digi_config_p->preempt[from_chan][to_chan],
|
||||
save_digi_config_p->atgp[from_chan][to_chan],
|
||||
|
@ -222,13 +222,13 @@ void digipeater (int from_chan, packet_t pp)
|
|||
* These are lower priority
|
||||
*/
|
||||
|
||||
for (to_chan=0; to_chan<MAX_CHANS; to_chan++) {
|
||||
for (to_chan=0; to_chan<MAX_TOTAL_CHANS; to_chan++) {
|
||||
if (save_digi_config_p->enabled[from_chan][to_chan]) {
|
||||
if (to_chan != from_chan) {
|
||||
packet_t result;
|
||||
|
||||
result = digipeat_match (from_chan, pp, save_audio_config_p->achan[from_chan].mycall,
|
||||
save_audio_config_p->achan[to_chan].mycall,
|
||||
result = digipeat_match (from_chan, pp, save_audio_config_p->mycall[from_chan],
|
||||
save_audio_config_p->mycall[to_chan],
|
||||
&save_digi_config_p->alias[from_chan][to_chan], &save_digi_config_p->wide[from_chan][to_chan],
|
||||
to_chan, save_digi_config_p->preempt[from_chan][to_chan],
|
||||
save_digi_config_p->atgp[from_chan][to_chan],
|
||||
|
@ -641,9 +641,9 @@ void digi_regen (int from_chan, packet_t pp)
|
|||
|
||||
// dw_printf ("digi_regen()\n");
|
||||
|
||||
assert (from_chan >= 0 && from_chan < MAX_CHANS);
|
||||
assert (from_chan >= 0 && from_chan < MAX_TOTAL_CHANS);
|
||||
|
||||
for (to_chan=0; to_chan<MAX_CHANS; to_chan++) {
|
||||
for (to_chan=0; to_chan<MAX_TOTAL_CHANS; to_chan++) {
|
||||
if (save_digi_config_p->regen[from_chan][to_chan]) {
|
||||
result = ax25_dup (pp);
|
||||
if (result != NULL) {
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
#include "regex.h"
|
||||
|
||||
#include "direwolf.h" /* for MAX_CHANS */
|
||||
#include "direwolf.h" /* for MAX_TOTAL_CHANS */
|
||||
#include "ax25_pad.h" /* for packet_t */
|
||||
#include "audio.h" /* for radio channel properties */
|
||||
|
||||
|
@ -29,25 +29,25 @@ struct digi_config_s {
|
|||
* Rules for each of the [from_chan][to_chan] combinations.
|
||||
*/
|
||||
|
||||
regex_t alias[MAX_CHANS][MAX_CHANS];
|
||||
regex_t alias[MAX_TOTAL_CHANS][MAX_TOTAL_CHANS];
|
||||
|
||||
regex_t wide[MAX_CHANS][MAX_CHANS];
|
||||
regex_t wide[MAX_TOTAL_CHANS][MAX_TOTAL_CHANS];
|
||||
|
||||
int enabled[MAX_CHANS][MAX_CHANS];
|
||||
int enabled[MAX_TOTAL_CHANS][MAX_TOTAL_CHANS];
|
||||
|
||||
enum preempt_e { PREEMPT_OFF, PREEMPT_DROP, PREEMPT_MARK, PREEMPT_TRACE } preempt[MAX_CHANS][MAX_CHANS];
|
||||
enum preempt_e { PREEMPT_OFF, PREEMPT_DROP, PREEMPT_MARK, PREEMPT_TRACE } preempt[MAX_TOTAL_CHANS][MAX_TOTAL_CHANS];
|
||||
|
||||
// ATGP is an ugly hack for the specific need of ATGP which needs more that 8 digipeaters.
|
||||
// DO NOT put this in the User Guide. On a need to know basis.
|
||||
|
||||
char atgp[MAX_CHANS][MAX_CHANS][AX25_MAX_ADDR_LEN];
|
||||
char atgp[MAX_TOTAL_CHANS][MAX_TOTAL_CHANS][AX25_MAX_ADDR_LEN];
|
||||
|
||||
char *filter_str[MAX_CHANS+1][MAX_CHANS+1];
|
||||
char *filter_str[MAX_TOTAL_CHANS+1][MAX_TOTAL_CHANS+1];
|
||||
// NULL or optional Packet Filter strings such as "t/m".
|
||||
// Notice the size of arrays is one larger than normal.
|
||||
// That extra position is for the IGate.
|
||||
|
||||
int regen[MAX_CHANS][MAX_CHANS]; // Regenerate packet.
|
||||
int regen[MAX_TOTAL_CHANS][MAX_TOTAL_CHANS]; // Regenerate packet.
|
||||
// Sort of like digipeating but passed along unchanged.
|
||||
};
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
//
|
||||
// This file is part of Dire Wolf, an amateur radio packet TNC.
|
||||
//
|
||||
// Copyright (C) 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2019, 2020, 2021, 2023 John Langner, WB2OSZ
|
||||
// Copyright (C) 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2019, 2020, 2021, 2023, 2024 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
|
||||
|
@ -130,6 +130,7 @@
|
|||
#include "dns_sd_dw.h"
|
||||
#include "dlq.h" // for fec_type_t definition.
|
||||
#include "deviceid.h"
|
||||
#include "nettnc.h"
|
||||
|
||||
|
||||
//static int idx_decoded = 0;
|
||||
|
@ -228,6 +229,7 @@ int main (int argc, char *argv[])
|
|||
#endif
|
||||
int d_x_opt = 1; /* "-d x" option for FX.25. Default minimal. Repeat for more detail. -qx to silence. */
|
||||
int d_2_opt = 0; /* "-d 2" option for IL2P. Default minimal. Repeat for more detail. */
|
||||
int d_c_opt = 0; /* "-d c" option for connected mode data link state machine. */
|
||||
|
||||
int aprstt_debug = 0; /* "-d d" option for APRStt (think Dtmf) debug. */
|
||||
|
||||
|
@ -303,7 +305,7 @@ int main (int argc, char *argv[])
|
|||
text_color_init(t_opt);
|
||||
text_color_set(DW_COLOR_INFO);
|
||||
//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, "A", __DATE__);
|
||||
dw_printf ("Dire Wolf DEVELOPMENT version %d.%d %s (%s)\n", MAJOR_VERSION, MINOR_VERSION, "D", __DATE__);
|
||||
//dw_printf ("Dire Wolf version %d.%d\n", MAJOR_VERSION, MINOR_VERSION);
|
||||
|
||||
|
||||
|
@ -390,6 +392,7 @@ int main (int argc, char *argv[])
|
|||
text_color_set(DW_COLOR_ERROR);
|
||||
for (int n=0; n<15; n++) {
|
||||
dw_printf ("\n");
|
||||
dw_printf ("Why are you running this as root user?.\n");
|
||||
dw_printf ("Dire Wolf requires only privileges available to ordinary users.\n");
|
||||
dw_printf ("Running this as root is an unnecessary security risk.\n");
|
||||
//SLEEP_SEC(1);
|
||||
|
@ -558,7 +561,7 @@ int main (int argc, char *argv[])
|
|||
break;
|
||||
}
|
||||
}
|
||||
if (x_opt_chan < 0 || x_opt_chan >= MAX_CHANS) {
|
||||
if (x_opt_chan < 0 || x_opt_chan >= MAX_RADIO_CHANS) {
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf ("Invalid channel %d for -x. \n", x_opt_chan);
|
||||
text_color_set(DW_COLOR_INFO);
|
||||
|
@ -637,6 +640,7 @@ int main (int argc, char *argv[])
|
|||
#if USE_HAMLIB
|
||||
case 'h': d_h_opt++; break; // Hamlib verbose level.
|
||||
#endif
|
||||
case 'c': d_c_opt++; break; // Connected mode data link state machine
|
||||
case 'x': d_x_opt++; break; // FX.25
|
||||
case '2': d_2_opt++; break; // IL2P
|
||||
case 'd': aprstt_debug++; break; // APRStt (mnemonic Dtmf)
|
||||
|
@ -1004,6 +1008,13 @@ int main (int argc, char *argv[])
|
|||
fx25_init (d_x_opt);
|
||||
il2p_init (d_2_opt);
|
||||
|
||||
/*
|
||||
* New in 1.8 - Allow a channel to be mapped to a network TNC rather than
|
||||
* an internal modem and radio.
|
||||
* I put it here so channel properties would come out in right order.
|
||||
*/
|
||||
nettnc_init (&audio_config);
|
||||
|
||||
/*
|
||||
* Initialize the touch tone decoder & APRStt gateway.
|
||||
*/
|
||||
|
@ -1108,7 +1119,7 @@ int main (int argc, char *argv[])
|
|||
igate_init (&audio_config, &igate_config, &digi_config, d_i_opt);
|
||||
cdigipeater_init (&audio_config, &cdigi_config);
|
||||
pfilter_init (&igate_config, d_f_opt);
|
||||
ax25_link_init (&misc_config);
|
||||
ax25_link_init (&misc_config, d_c_opt);
|
||||
|
||||
/*
|
||||
* Provide the AGW & KISS socket interfaces for use by a client application.
|
||||
|
@ -1167,7 +1178,10 @@ int main (int argc, char *argv[])
|
|||
*
|
||||
* Inputs: chan - Audio channel number, 0 or 1.
|
||||
* subchan - Which modem caught it.
|
||||
* Special case -1 for DTMF decoder.
|
||||
* Special cases:
|
||||
* -1 for DTMF decoder.
|
||||
* -2 for channel mapped to APRS-IS.
|
||||
* -3 for channel mapped to network TNC.
|
||||
* slice - Slicer which caught it.
|
||||
* pp - Packet handle.
|
||||
* alevel - Audio level, range of 0 - 100.
|
||||
|
@ -1198,7 +1212,7 @@ void app_process_rec_packet (int chan, int subchan, int slice, packet_t pp, alev
|
|||
// Can indicate FX.25/IL2P or fix_bits.
|
||||
|
||||
assert (chan >= 0 && chan < MAX_TOTAL_CHANS); // TOTAL for virtual channels
|
||||
assert (subchan >= -2 && subchan < MAX_SUBCHANS);
|
||||
assert (subchan >= -3 && subchan < MAX_SUBCHANS);
|
||||
assert (slice >= 0 && slice < MAX_SLICERS);
|
||||
assert (pp != NULL); // 1.1J+
|
||||
|
||||
|
@ -1279,7 +1293,13 @@ void app_process_rec_packet (int chan, int subchan, int slice, packet_t pp, alev
|
|||
|
||||
ax25_get_addr_with_ssid(pp, h-1, probably_really);
|
||||
|
||||
dw_printf ("%s (probably %s) audio level = %s %s %s\n", heard, probably_really, alevel_text, display_retries, spectrum);
|
||||
// audio level applies only for internal modem channels.
|
||||
if (subchan >=0) {
|
||||
dw_printf ("%s (probably %s) audio level = %s %s %s\n", heard, probably_really, alevel_text, display_retries, spectrum);
|
||||
}
|
||||
else {
|
||||
dw_printf ("%s (probably %s)\n", heard, probably_really);
|
||||
}
|
||||
|
||||
}
|
||||
else if (strcmp(heard, "DTMF") == 0) {
|
||||
|
@ -1288,7 +1308,13 @@ void app_process_rec_packet (int chan, int subchan, int slice, packet_t pp, alev
|
|||
}
|
||||
else {
|
||||
|
||||
dw_printf ("%s audio level = %s %s %s\n", heard, alevel_text, display_retries, spectrum);
|
||||
// audio level applies only for internal modem channels.
|
||||
if (subchan >= 0) {
|
||||
dw_printf ("%s audio level = %s %s %s\n", heard, alevel_text, display_retries, spectrum);
|
||||
}
|
||||
else {
|
||||
dw_printf ("%s\n", heard);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1305,7 +1331,7 @@ void app_process_rec_packet (int chan, int subchan, int slice, packet_t pp, alev
|
|||
dw_printf ("Audio input level is too high. Reduce so most stations are around 50.\n");
|
||||
}
|
||||
// FIXME: rather than checking for ichannel, how about checking medium==radio
|
||||
else if (alevel.rec < 5 && chan != audio_config.igate_vchannel) {
|
||||
else if (alevel.rec < 5 && chan != audio_config.igate_vchannel && subchan != -3) {
|
||||
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf ("Audio input level is too low. Increase so most stations are around 50.\n");
|
||||
|
@ -1330,14 +1356,18 @@ void app_process_rec_packet (int chan, int subchan, int slice, packet_t pp, alev
|
|||
strlcpy (ts, "", sizeof(ts));
|
||||
}
|
||||
|
||||
if (subchan == -1) {
|
||||
if (subchan == -1) { // dtmf
|
||||
text_color_set(DW_COLOR_REC);
|
||||
dw_printf ("[%d.dtmf%s] ", chan, ts);
|
||||
}
|
||||
else if (subchan == -2) {
|
||||
else if (subchan == -2) { // APRS-IS
|
||||
text_color_set(DW_COLOR_REC);
|
||||
dw_printf ("[%d.is%s] ", chan, ts);
|
||||
}
|
||||
else if (subchan == -3) { // nettnc
|
||||
text_color_set(DW_COLOR_REC);
|
||||
dw_printf ("[%d%s] ", chan, ts);
|
||||
}
|
||||
else {
|
||||
if (ax25_is_aprs(pp)) {
|
||||
text_color_set(DW_COLOR_REC);
|
||||
|
@ -1498,7 +1528,7 @@ void app_process_rec_packet (int chan, int subchan, int slice, packet_t pp, alev
|
|||
0, 0, 0, A.g_comment, // freq, tone, offset
|
||||
ais_obj_info, sizeof(ais_obj_info));
|
||||
|
||||
snprintf (ais_obj_packet, sizeof(ais_obj_packet), "%s>%s%1d%1d:%s", A.g_src, APP_TOCALL, MAJOR_VERSION, MINOR_VERSION, ais_obj_info);
|
||||
snprintf (ais_obj_packet, sizeof(ais_obj_packet), "%s>%s%1d%1d,NOGATE:%s", A.g_src, APP_TOCALL, MAJOR_VERSION, MINOR_VERSION, ais_obj_info);
|
||||
|
||||
dw_printf ("[%d.AIS] %s\n", chan, ais_obj_packet);
|
||||
|
||||
|
@ -1614,9 +1644,10 @@ void app_process_rec_packet (int chan, int subchan, int slice, packet_t pp, alev
|
|||
* Use only those with correct CRC (or using FEC.)
|
||||
*/
|
||||
|
||||
if (retries == RETRY_NONE || fec_type == fec_type_fx25 || fec_type == fec_type_il2p) {
|
||||
|
||||
cdigipeater (chan, pp);
|
||||
if (chan < MAX_RADIO_CHANS) {
|
||||
if (retries == RETRY_NONE || fec_type == fec_type_fx25 || fec_type == fec_type_il2p) {
|
||||
cdigipeater (chan, pp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1708,6 +1739,7 @@ static void usage (char **argv)
|
|||
#if USE_HAMLIB
|
||||
dw_printf (" h h = hamlib increase verbose level.\n");
|
||||
#endif
|
||||
dw_printf (" c c = Connected mode data link state machine.\n");
|
||||
dw_printf (" x x = FX.25 increase verbose level.\n");
|
||||
dw_printf (" 2 2 = IL2P.\n");
|
||||
dw_printf (" d d = APRStt (DTMF to APRS object translation).\n");
|
||||
|
|
|
@ -56,15 +56,10 @@
|
|||
*
|
||||
* ADevice 0: channel 0
|
||||
* ADevice 1: left = 2, right = 3
|
||||
*
|
||||
* TODO1.2: Look for any places that have
|
||||
* for (ch=0; ch<MAX_CHANS; ch++) ...
|
||||
* and make sure they handle undefined channels correctly.
|
||||
*/
|
||||
|
||||
#define MAX_RADIO_CHANS ((MAX_ADEVS) * 2)
|
||||
|
||||
#define MAX_CHANS MAX_RADIO_CHANS // TODO: Replace all former with latter to avoid confusion with following.
|
||||
|
||||
#define MAX_TOTAL_CHANS 16 // v1.7 allows additional virtual channels which are connected
|
||||
// to something other than radio modems.
|
||||
|
@ -77,7 +72,7 @@
|
|||
*/
|
||||
|
||||
#ifdef USE_HAMLIB
|
||||
#define MAX_RIGS MAX_CHANS
|
||||
#define MAX_RIGS MAX_RADIO_CHANS
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
|
12
src/dlq.c
12
src/dlq.c
|
@ -498,7 +498,7 @@ void dlq_connect_request (char addrs[AX25_MAX_ADDRS][AX25_MAX_ADDR_LEN], int num
|
|||
dw_printf ("dlq_connect_request (...)\n");
|
||||
#endif
|
||||
|
||||
assert (chan >= 0 && chan < MAX_CHANS);
|
||||
assert (chan >= 0 && chan < MAX_RADIO_CHANS);
|
||||
|
||||
/* Allocate a new queue item. */
|
||||
|
||||
|
@ -556,7 +556,7 @@ void dlq_disconnect_request (char addrs[AX25_MAX_ADDRS][AX25_MAX_ADDR_LEN], int
|
|||
dw_printf ("dlq_disconnect_request (...)\n");
|
||||
#endif
|
||||
|
||||
assert (chan >= 0 && chan < MAX_CHANS);
|
||||
assert (chan >= 0 && chan < MAX_RADIO_CHANS);
|
||||
|
||||
/* Allocate a new queue item. */
|
||||
|
||||
|
@ -619,7 +619,7 @@ void dlq_outstanding_frames_request (char addrs[AX25_MAX_ADDRS][AX25_MAX_ADDR_LE
|
|||
dw_printf ("dlq_outstanding_frames_request (...)\n");
|
||||
#endif
|
||||
|
||||
assert (chan >= 0 && chan < MAX_CHANS);
|
||||
assert (chan >= 0 && chan < MAX_RADIO_CHANS);
|
||||
|
||||
/* Allocate a new queue item. */
|
||||
|
||||
|
@ -691,7 +691,7 @@ void dlq_xmit_data_request (char addrs[AX25_MAX_ADDRS][AX25_MAX_ADDR_LEN], int n
|
|||
dw_printf ("dlq_xmit_data_request (...)\n");
|
||||
#endif
|
||||
|
||||
assert (chan >= 0 && chan < MAX_CHANS);
|
||||
assert (chan >= 0 && chan < MAX_RADIO_CHANS);
|
||||
|
||||
/* Allocate a new queue item. */
|
||||
|
||||
|
@ -758,7 +758,7 @@ void dlq_register_callsign (char *addr, int chan, int client)
|
|||
dw_printf ("dlq_register_callsign (%s, chan=%d, client=%d)\n", addr, chan, client);
|
||||
#endif
|
||||
|
||||
assert (chan >= 0 && chan < MAX_CHANS);
|
||||
assert (chan >= 0 && chan < MAX_RADIO_CHANS);
|
||||
|
||||
/* Allocate a new queue item. */
|
||||
|
||||
|
@ -793,7 +793,7 @@ void dlq_unregister_callsign (char *addr, int chan, int client)
|
|||
dw_printf ("dlq_unregister_callsign (%s, chan=%d, client=%d)\n", addr, chan, client);
|
||||
#endif
|
||||
|
||||
assert (chan >= 0 && chan < MAX_CHANS);
|
||||
assert (chan >= 0 && chan < MAX_RADIO_CHANS);
|
||||
|
||||
/* Allocate a new queue item. */
|
||||
|
||||
|
|
11
src/dtmf.c
11
src/dtmf.c
|
@ -80,7 +80,7 @@ static struct dd_s { /* Separate for each audio channel. */
|
|||
char prev_debounced;
|
||||
int timeout;
|
||||
|
||||
} dd[MAX_CHANS];
|
||||
} dd[MAX_RADIO_CHANS];
|
||||
|
||||
|
||||
static int s_amplitude = 100; // range of 0 .. 100
|
||||
|
@ -129,7 +129,7 @@ void dtmf_init (struct audio_s *p_audio_config, int amp)
|
|||
* Larger = narrower bandwidth, slower response.
|
||||
*/
|
||||
|
||||
for (c=0; c<MAX_CHANS; c++) {
|
||||
for (c=0; c<MAX_RADIO_CHANS; c++) {
|
||||
struct dd_s *D = &(dd[c]);
|
||||
int a = ACHAN2ADEV(c);
|
||||
|
||||
|
@ -167,7 +167,7 @@ void dtmf_init (struct audio_s *p_audio_config, int amp)
|
|||
}
|
||||
}
|
||||
|
||||
for (c=0; c<MAX_CHANS; c++) {
|
||||
for (c=0; c<MAX_RADIO_CHANS; c++) {
|
||||
struct dd_s *D = &(dd[c]);
|
||||
D->n = 0;
|
||||
for (j=0; j<NUM_TONES; j++) {
|
||||
|
@ -214,6 +214,11 @@ char dtmf_sample (int c, float input)
|
|||
'7', '8', '9', 'C',
|
||||
'*', '0', '#', 'D' };
|
||||
|
||||
// Only applies to radio channels. Should not be here.
|
||||
if (c >= MAX_RADIO_CHANS) {
|
||||
return ('$');
|
||||
}
|
||||
|
||||
D = &(dd[c]);
|
||||
|
||||
for (i=0; i<NUM_TONES; i++) {
|
||||
|
|
|
@ -125,7 +125,7 @@ int dwsock_init(void)
|
|||
|
||||
/*-------------------------------------------------------------------
|
||||
*
|
||||
* Name: sock_connect
|
||||
* Name: dwsock_connect
|
||||
*
|
||||
* Purpose: Connect to given host / port.
|
||||
*
|
||||
|
|
|
@ -596,14 +596,22 @@ int encode_position (int messaging, int compressed, double lat, double lon, int
|
|||
presult[result_len] = '\0';
|
||||
|
||||
/* Altitude. Can be anywhere in comment. */
|
||||
// Officially, altitude must be six digits.
|
||||
// What about all the places on the earth's surface that are below sea level?
|
||||
// https://en.wikipedia.org/wiki/List_of_places_on_land_with_elevations_below_sea_level
|
||||
|
||||
// The MIC-E format allows negative altitudes; not allowing it for /A=123456 seems to be an oversight.
|
||||
// Most modern applications recognize the form /A=-12345 with minus and five digits.
|
||||
// This maintains the same total field width and the range is more than adequate.
|
||||
|
||||
if (alt_ft != G_UNKNOWN) {
|
||||
char salt[12];
|
||||
/* Not clear if altitude can be negative. */
|
||||
/* Be sure it will be converted to 6 digits. */
|
||||
if (alt_ft < 0) alt_ft = 0;
|
||||
// if (alt_ft < 0) alt_ft = 0;
|
||||
if (alt_ft < -99999) alt_ft = -99999;
|
||||
if (alt_ft > 999999) alt_ft = 999999;
|
||||
snprintf (salt, sizeof(salt), "/A=%06d", alt_ft);
|
||||
snprintf (salt, sizeof(salt), "/A=%06d", alt_ft); // /A=123456 ot /A=-12345
|
||||
strlcat (presult, salt, result_size);
|
||||
result_len += strlen(salt);
|
||||
}
|
||||
|
|
|
@ -469,7 +469,7 @@ struct demodulator_state_s
|
|||
*
|
||||
* Inputs: D Pointer to demodulator state.
|
||||
*
|
||||
* chan Radio channel: 0 to MAX_CHANS - 1
|
||||
* chan Radio channel: 0 to MAX_RADIO_CHANS - 1
|
||||
*
|
||||
* subchan Which of multiple demodulators: 0 to MAX_SUBCHANS - 1
|
||||
*
|
||||
|
|
|
@ -59,7 +59,7 @@ struct fx_context_s {
|
|||
unsigned char block[FX25_BLOCK_SIZE+1];
|
||||
};
|
||||
|
||||
static struct fx_context_s *fx_context[MAX_CHANS][MAX_SUBCHANS][MAX_SLICERS];
|
||||
static struct fx_context_s *fx_context[MAX_RADIO_CHANS][MAX_SUBCHANS][MAX_SLICERS];
|
||||
|
||||
static void process_rs_block (int chan, int subchan, int slice, struct fx_context_s *F);
|
||||
|
||||
|
@ -157,7 +157,7 @@ void fx25_rec_bit (int chan, int subchan, int slice, int dbit)
|
|||
|
||||
struct fx_context_s *F = fx_context[chan][subchan][slice];
|
||||
if (F == NULL) {
|
||||
assert (chan >= 0 && chan < MAX_CHANS);
|
||||
assert (chan >= 0 && chan < MAX_RADIO_CHANS);
|
||||
assert (subchan >= 0 && subchan < MAX_SUBCHANS);
|
||||
assert (slice >= 0 && slice < MAX_SLICERS);
|
||||
F = fx_context[chan][subchan][slice] = (struct fx_context_s *)malloc(sizeof (struct fx_context_s));
|
||||
|
@ -256,7 +256,7 @@ void fx25_rec_bit (int chan, int subchan, int slice, int dbit)
|
|||
|
||||
int fx25_rec_busy (int chan)
|
||||
{
|
||||
assert (chan >= 0 && chan < MAX_CHANS);
|
||||
assert (chan >= 0 && chan < MAX_RADIO_CHANS);
|
||||
|
||||
// This could be a little faster if we knew number of
|
||||
// subchannels and slicers but it is probably insignificant.
|
||||
|
|
|
@ -41,7 +41,7 @@ static void send_bit (int chan, int b);
|
|||
static int stuff_it (unsigned char *in, int ilen, unsigned char *out, int osize);
|
||||
|
||||
|
||||
static int number_of_bits_sent[MAX_CHANS]; // Count number of bits sent by "fx25_send_frame" or "???"
|
||||
static int number_of_bits_sent[MAX_RADIO_CHANS]; // Count number of bits sent by "fx25_send_frame" or "???"
|
||||
|
||||
|
||||
#if FXTEST
|
||||
|
@ -249,7 +249,7 @@ static void send_bytes (int chan, unsigned char *b, int count)
|
|||
*/
|
||||
static void send_bit (int chan, int b)
|
||||
{
|
||||
static int output[MAX_CHANS];
|
||||
static int output[MAX_RADIO_CHANS];
|
||||
|
||||
if (b == 0) {
|
||||
output[chan] = ! output[chan];
|
||||
|
|
|
@ -242,7 +242,7 @@ int main(int argc, char **argv)
|
|||
modem.adev[0].samples_per_sec = DEFAULT_SAMPLES_PER_SEC; /* -r option */
|
||||
modem.adev[0].bits_per_sample = DEFAULT_BITS_PER_SAMPLE; /* -8 for 8 instead of 16 bits */
|
||||
|
||||
for (chan = 0; chan < MAX_CHANS; chan++) {
|
||||
for (chan = 0; chan < MAX_RADIO_CHANS; chan++) {
|
||||
modem.achan[chan].modem_type = MODEM_AFSK; /* change with -g */
|
||||
modem.achan[chan].mark_freq = DEFAULT_MARK_FREQ; /* -m option */
|
||||
modem.achan[chan].space_freq = DEFAULT_SPACE_FREQ; /* -s option */
|
||||
|
|
|
@ -63,14 +63,14 @@ static struct audio_s *save_audio_config_p = NULL;
|
|||
|
||||
#define TICKS_PER_CYCLE ( 256.0 * 256.0 * 256.0 * 256.0 )
|
||||
|
||||
static int ticks_per_sample[MAX_CHANS]; /* Same for both channels of same soundcard */
|
||||
static int ticks_per_sample[MAX_RADIO_CHANS]; /* Same for both channels of same soundcard */
|
||||
/* because they have same sample rate */
|
||||
/* but less confusing to have for each channel. */
|
||||
|
||||
static int ticks_per_bit[MAX_CHANS];
|
||||
static int f1_change_per_sample[MAX_CHANS];
|
||||
static int f2_change_per_sample[MAX_CHANS];
|
||||
static float samples_per_symbol[MAX_CHANS];
|
||||
static int ticks_per_bit[MAX_RADIO_CHANS];
|
||||
static int f1_change_per_sample[MAX_RADIO_CHANS];
|
||||
static int f2_change_per_sample[MAX_RADIO_CHANS];
|
||||
static float samples_per_symbol[MAX_RADIO_CHANS];
|
||||
|
||||
|
||||
static short sine_table[256];
|
||||
|
@ -78,7 +78,7 @@ static short sine_table[256];
|
|||
|
||||
/* Accumulators. */
|
||||
|
||||
static unsigned int tone_phase[MAX_CHANS]; // Phase accumulator for tone generation.
|
||||
static unsigned int tone_phase[MAX_RADIO_CHANS]; // Phase accumulator for tone generation.
|
||||
// Upper bits are used as index into sine table.
|
||||
|
||||
#define PHASE_SHIFT_180 ( 128u << 24 )
|
||||
|
@ -86,11 +86,11 @@ static unsigned int tone_phase[MAX_CHANS]; // Phase accumulator for tone generat
|
|||
#define PHASE_SHIFT_45 ( 32u << 24 )
|
||||
|
||||
|
||||
static int bit_len_acc[MAX_CHANS]; // To accumulate fractional samples per bit.
|
||||
static int bit_len_acc[MAX_RADIO_CHANS]; // To accumulate fractional samples per bit.
|
||||
|
||||
static int lfsr[MAX_CHANS]; // Shift register for scrambler.
|
||||
static int lfsr[MAX_RADIO_CHANS]; // Shift register for scrambler.
|
||||
|
||||
static int bit_count[MAX_CHANS]; // Counter incremented for each bit transmitted
|
||||
static int bit_count[MAX_RADIO_CHANS]; // Counter incremented for each bit transmitted
|
||||
// on the channel. This is only used for QPSK.
|
||||
// The LSB determines if we save the bit until
|
||||
// next time, or send this one with the previously saved.
|
||||
|
@ -101,10 +101,10 @@ static int bit_count[MAX_CHANS]; // Counter incremented for each bit transmitted
|
|||
// For 8PSK, it has a different meaning. It is the
|
||||
// number of bits in 'save_bit' so we can accumulate
|
||||
// three for each symbol.
|
||||
static int save_bit[MAX_CHANS];
|
||||
static int save_bit[MAX_RADIO_CHANS];
|
||||
|
||||
|
||||
static int prev_dat[MAX_CHANS]; // Previous data bit. Used for G3RUH style.
|
||||
static int prev_dat[MAX_RADIO_CHANS]; // Previous data bit. Used for G3RUH style.
|
||||
|
||||
|
||||
|
||||
|
@ -163,7 +163,7 @@ int gen_tone_init (struct audio_s *audio_config_p, int amp, int gen_packets)
|
|||
|
||||
amp16bit = (int)((32767 * amp) / 100);
|
||||
|
||||
for (chan = 0; chan < MAX_CHANS; chan++) {
|
||||
for (chan = 0; chan < MAX_RADIO_CHANS; chan++) {
|
||||
|
||||
if (audio_config_p->chan_medium[chan] == MEDIUM_RADIO) {
|
||||
|
||||
|
@ -352,8 +352,8 @@ static const int gray2phase_v27[8] = {1, 0, 2, 3, 6, 7, 5, 4};
|
|||
|
||||
// #define PSKIQ 1 // not ready for prime time yet.
|
||||
#if PSKIQ
|
||||
static int xmit_octant[MAX_CHANS]; // absolute phase in 45 degree units.
|
||||
static int xmit_prev_octant[MAX_CHANS]; // from previous symbol.
|
||||
static int xmit_octant[MAX_RADIO_CHANS]; // absolute phase in 45 degree units.
|
||||
static int xmit_prev_octant[MAX_RADIO_CHANS]; // from previous symbol.
|
||||
|
||||
// For PSK, we generate the final signal by combining fixed frequency cosine and
|
||||
// sine by the following weights.
|
||||
|
|
|
@ -114,11 +114,11 @@ struct hdlc_state_s {
|
|||
int eas_fields_after_plus; /* Number of "-" characters after the "+". */
|
||||
};
|
||||
|
||||
static struct hdlc_state_s hdlc_state[MAX_CHANS][MAX_SUBCHANS][MAX_SLICERS];
|
||||
static struct hdlc_state_s hdlc_state[MAX_RADIO_CHANS][MAX_SUBCHANS][MAX_SLICERS];
|
||||
|
||||
static int num_subchan[MAX_CHANS]; //TODO1.2 use ptr rather than copy.
|
||||
static int num_subchan[MAX_RADIO_CHANS]; //TODO1.2 use ptr rather than copy.
|
||||
|
||||
static int composite_dcd[MAX_CHANS][MAX_SUBCHANS+1];
|
||||
static int composite_dcd[MAX_RADIO_CHANS][MAX_SUBCHANS+1];
|
||||
|
||||
|
||||
/***********************************************************************************
|
||||
|
@ -149,7 +149,7 @@ void hdlc_rec_init (struct audio_s *pa)
|
|||
|
||||
memset (composite_dcd, 0, sizeof(composite_dcd));
|
||||
|
||||
for (ch = 0; ch < MAX_CHANS; ch++)
|
||||
for (ch = 0; ch < MAX_RADIO_CHANS; ch++)
|
||||
{
|
||||
|
||||
if (pa->chan_medium[ch] == MEDIUM_RADIO) {
|
||||
|
@ -429,17 +429,24 @@ a good modem here and providing a result when it is received.
|
|||
***********************************************************************************/
|
||||
|
||||
void hdlc_rec_bit (int chan, int subchan, int slice, int raw, int is_scrambled, int not_used_remove)
|
||||
{
|
||||
static int64_t dummyll = 0;
|
||||
static int dummy = 0;
|
||||
hdlc_rec_bit_new (chan, subchan, slice, raw, is_scrambled, not_used_remove,
|
||||
&dummyll, &dummy);
|
||||
}
|
||||
|
||||
void hdlc_rec_bit_new (int chan, int subchan, int slice, int raw, int is_scrambled, int not_used_remove,
|
||||
int64_t *pll_nudge_total, int *pll_symbol_count)
|
||||
{
|
||||
|
||||
int dbit; /* Data bit after undoing NRZI. */
|
||||
/* Should be only 0 or 1. */
|
||||
struct hdlc_state_s *H;
|
||||
|
||||
assert (was_init == 1);
|
||||
|
||||
assert (chan >= 0 && chan < MAX_CHANS);
|
||||
assert (chan >= 0 && chan < MAX_RADIO_CHANS);
|
||||
assert (subchan >= 0 && subchan < MAX_SUBCHANS);
|
||||
|
||||
assert (slice >= 0 && slice < MAX_SLICERS);
|
||||
|
||||
// -e option can be used to artificially introduce the desired
|
||||
|
@ -467,7 +474,7 @@ void hdlc_rec_bit (int chan, int subchan, int slice, int raw, int is_scrambled,
|
|||
/*
|
||||
* Different state information for each channel / subchannel / slice.
|
||||
*/
|
||||
H = &hdlc_state[chan][subchan][slice];
|
||||
struct hdlc_state_s *H = &hdlc_state[chan][subchan][slice];
|
||||
|
||||
|
||||
/*
|
||||
|
@ -590,15 +597,43 @@ void hdlc_rec_bit (int chan, int subchan, int slice, int raw, int is_scrambled,
|
|||
#endif
|
||||
if (rrbb_get_len(H->rrbb) >= MIN_FRAME_LEN * 8) {
|
||||
|
||||
//JWL - end of frame
|
||||
|
||||
float speed_error; // in percentage.
|
||||
if (*pll_symbol_count > 0) { // avoid divde by 0.
|
||||
|
||||
// TODO:
|
||||
// Fudged to get +-2.0 with gen_packets -b 1224 & 1176.
|
||||
// Also initialized the symbol counter to -1.
|
||||
|
||||
speed_error = (float)((double)(*pll_nudge_total) * 100. / (256. * 256. * 256. * 256.) / (double)(*pll_symbol_count) + 0.02);
|
||||
|
||||
text_color_set(DW_COLOR_DEBUG);
|
||||
|
||||
// std dw_printf ("DEBUG: total %lld, count %d\n", *pll_nudge_total, *pll_symbol_count);
|
||||
// mingw
|
||||
// dw_printf ("DEBUG: total %I64d, count %d\n", *pll_nudge_total, *pll_symbol_count);
|
||||
// dw_printf ("DEBUG: speed error %+0.2f%% -> %+0.1f%% \n", speed_error, speed_error);
|
||||
}
|
||||
else {
|
||||
speed_error = 0;
|
||||
}
|
||||
rrbb_set_speed_error (H->rrbb, speed_error);
|
||||
|
||||
alevel_t alevel = demod_get_audio_level (chan, subchan);
|
||||
|
||||
rrbb_set_audio_level (H->rrbb, alevel);
|
||||
hdlc_rec2_block (H->rrbb);
|
||||
/* Now owned by someone else who will free it. */
|
||||
H->rrbb = NULL;
|
||||
|
||||
H->rrbb = rrbb_new (chan, subchan, slice, is_scrambled, H->lfsr, H->prev_descram); /* Allocate a new one. */
|
||||
}
|
||||
else {
|
||||
|
||||
//JWL - start of frame
|
||||
*pll_nudge_total = 0;
|
||||
*pll_symbol_count = -1; // comes out better than using 0.
|
||||
rrbb_clear (H->rrbb, is_scrambled, H->lfsr, H->prev_descram);
|
||||
}
|
||||
|
||||
|
@ -730,7 +765,7 @@ void dcd_change (int chan, int subchan, int slice, int state)
|
|||
{
|
||||
int old, new;
|
||||
|
||||
assert (chan >= 0 && chan < MAX_CHANS);
|
||||
assert (chan >= 0 && chan < MAX_RADIO_CHANS);
|
||||
assert (subchan >= 0 && subchan <= MAX_SUBCHANS);
|
||||
assert (slice >= 0 && slice < MAX_SLICERS);
|
||||
assert (state == 0 || state == 1);
|
||||
|
@ -791,7 +826,7 @@ int hdlc_rec_data_detect_any (int chan)
|
|||
{
|
||||
|
||||
int sc;
|
||||
assert (chan >= 0 && chan < MAX_CHANS);
|
||||
assert (chan >= 0 && chan < MAX_RADIO_CHANS);
|
||||
|
||||
for (sc = 0; sc < num_subchan[chan]; sc++) {
|
||||
if (composite_dcd[chan][sc] != 0)
|
||||
|
|
|
@ -1,12 +1,22 @@
|
|||
|
||||
/* hdlc_rec.h */
|
||||
|
||||
|
||||
|
||||
|
||||
#include <stdint.h> // int64_t
|
||||
|
||||
#include "audio.h"
|
||||
|
||||
|
||||
void hdlc_rec_init (struct audio_s *pa);
|
||||
|
||||
// TODO: change all to _new.
|
||||
void hdlc_rec_bit (int chan, int subchan, int slice, int raw, int is_scrambled, int descram_state);
|
||||
|
||||
void hdlc_rec_bit_new (int chan, int subchan, int slice, int raw, int is_scrambled, int descram_state,
|
||||
int64_t *pll_nudge_total, int *pll_nudge_count);
|
||||
|
||||
/* Provided elsewhere to process a complete frame. */
|
||||
|
||||
//void process_rec_frame (int chan, unsigned char *fbuf, int flen, int level);
|
||||
|
|
|
@ -216,6 +216,8 @@ void hdlc_rec2_init (struct audio_s *p_audio_config)
|
|||
* Purpose: Extract HDLC frame from a stream of bits.
|
||||
*
|
||||
* Inputs: block - Handle for bit array.
|
||||
* This will be deallocated so the caller
|
||||
* must not hold on to the address.
|
||||
*
|
||||
* Description: The other (original) hdlc decoder took one bit at a time
|
||||
* right out of the demodulator.
|
||||
|
@ -287,12 +289,10 @@ void hdlc_rec2_block (rrbb_t block)
|
|||
/* Let thru even with bad CRC. Of course, it still */
|
||||
/* needs to be a minimum number of whole octets. */
|
||||
ok = try_decode (block, chan, subchan, slice, alevel, retry_cfg, 1);
|
||||
rrbb_delete (block);
|
||||
}
|
||||
else {
|
||||
rrbb_delete (block);
|
||||
}
|
||||
|
||||
rrbb_delete (block);
|
||||
|
||||
} /* end hdlc_rec2_block */
|
||||
|
||||
|
||||
|
@ -438,7 +438,7 @@ static int try_to_fix_quick_now (rrbb_t block, int chan, int subchan, int slice,
|
|||
retry_cfg.u_bits.sep.bit_idx_c = -1;
|
||||
|
||||
#ifdef DEBUG_LATER
|
||||
tstart = dtime_now();
|
||||
tstart = dtime_monotonic();
|
||||
dw_printf ("*** Try flipping TWO SEPARATED BITS %d bits\n", len);
|
||||
#endif
|
||||
len = rrbb_get_len(block);
|
||||
|
|
|
@ -39,7 +39,7 @@ static void send_bit_nrzi (int, int);
|
|||
|
||||
|
||||
|
||||
static int number_of_bits_sent[MAX_CHANS]; // Count number of bits sent by "hdlc_send_frame" or "hdlc_send_flags"
|
||||
static int number_of_bits_sent[MAX_RADIO_CHANS]; // Count number of bits sent by "hdlc_send_frame" or "hdlc_send_flags"
|
||||
|
||||
|
||||
|
||||
|
@ -240,7 +240,7 @@ static void send_byte_msb_first (int chan, int x, int polarity)
|
|||
// Data (non flags) use bit stuffing.
|
||||
|
||||
|
||||
static int stuff[MAX_CHANS]; // Count number of "1" bits to keep track of when we
|
||||
static int stuff[MAX_RADIO_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.
|
||||
|
@ -284,7 +284,7 @@ static void send_data_nrzi (int chan, int x)
|
|||
|
||||
static void send_bit_nrzi (int chan, int b)
|
||||
{
|
||||
static int output[MAX_CHANS];
|
||||
static int output[MAX_RADIO_CHANS];
|
||||
|
||||
if (b == 0) {
|
||||
output[chan] = ! output[chan];
|
||||
|
|
26
src/igate.c
26
src/igate.c
|
@ -216,8 +216,8 @@ int main (int argc, char *argv[])
|
|||
|
||||
memset (&audio_config, 0, sizeof(audio_config));
|
||||
audio_config.adev[0].num_channels = 2;
|
||||
strlcpy (audio_config.achan[0].mycall, "WB2OSZ-1", sizeof(audio_config.achan[0].mycall));
|
||||
strlcpy (audio_config.achan[1].mycall, "WB2OSZ-2", sizeof(audio_config.achan[0].mycall));
|
||||
strlcpy (audio_config.mycall[0], "WB2OSZ-1", sizeof(audio_config.achan[0].mycall));
|
||||
strlcpy (audio_config.mycall[1], "WB2OSZ-2", sizeof(audio_config.achan[0].mycall));
|
||||
|
||||
memset (&igate_config, 0, sizeof(igate_config));
|
||||
|
||||
|
@ -909,10 +909,10 @@ void igate_send_rec_packet (int chan, packet_t recv_pp)
|
|||
// Beacon will be channel -1.
|
||||
// Client app to ICHANNEL is outside of radio channel range.
|
||||
|
||||
if (chan >= 0 && chan < MAX_CHANS && // in radio channel range
|
||||
save_digi_config_p->filter_str[chan][MAX_CHANS] != NULL) {
|
||||
if (chan >= 0 && chan < MAX_TOTAL_CHANS && // in radio channel range
|
||||
save_digi_config_p->filter_str[chan][MAX_TOTAL_CHANS] != NULL) {
|
||||
|
||||
if (pfilter(chan, MAX_CHANS, save_digi_config_p->filter_str[chan][MAX_CHANS], recv_pp, 1) != 1) {
|
||||
if (pfilter(chan, MAX_TOTAL_CHANS, save_digi_config_p->filter_str[chan][MAX_TOTAL_CHANS], recv_pp, 1) != 1) {
|
||||
|
||||
// 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.
|
||||
|
@ -920,7 +920,7 @@ void igate_send_rec_packet (int chan, packet_t recv_pp)
|
|||
|
||||
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]);
|
||||
dw_printf ("Packet from channel %d to IGate was rejected by filter: %s\n", chan, save_digi_config_p->filter_str[chan][MAX_TOTAL_CHANS]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -1141,7 +1141,7 @@ static void send_packet_to_server (packet_t pp, int chan)
|
|||
strlcat (msg, ",qAO,", sizeof(msg)); // new for version 1.4.
|
||||
}
|
||||
|
||||
strlcat (msg, save_audio_config_p->achan[chan].mycall, sizeof(msg));
|
||||
strlcat (msg, save_audio_config_p->mycall[chan], sizeof(msg));
|
||||
strlcat (msg, ":", sizeof(msg));
|
||||
|
||||
|
||||
|
@ -1781,7 +1781,7 @@ static void maybe_xmit_packet_from_igate (char *message, int to_chan)
|
|||
{
|
||||
int n;
|
||||
|
||||
assert (to_chan >= 0 && to_chan < MAX_CHANS);
|
||||
assert (to_chan >= 0 && to_chan < MAX_TOTAL_CHANS);
|
||||
|
||||
/*
|
||||
* Try to parse it into a packet object; we need this for the packet filtering.
|
||||
|
@ -1856,7 +1856,7 @@ static void maybe_xmit_packet_from_igate (char *message, int to_chan)
|
|||
* filtering by stations along the way or the q construct.
|
||||
*/
|
||||
|
||||
assert (to_chan >= 0 && to_chan < MAX_CHANS);
|
||||
assert (to_chan >= 0 && to_chan < MAX_TOTAL_CHANS);
|
||||
|
||||
|
||||
/*
|
||||
|
@ -1906,9 +1906,9 @@ static void maybe_xmit_packet_from_igate (char *message, int to_chan)
|
|||
|
||||
if ( ! msp_special_case) {
|
||||
|
||||
if (save_digi_config_p->filter_str[MAX_CHANS][to_chan] != NULL) {
|
||||
if (save_digi_config_p->filter_str[MAX_TOTAL_CHANS][to_chan] != NULL) {
|
||||
|
||||
if (pfilter(MAX_CHANS, to_chan, save_digi_config_p->filter_str[MAX_CHANS][to_chan], pp3, 1) != 1) {
|
||||
if (pfilter(MAX_TOTAL_CHANS, to_chan, save_digi_config_p->filter_str[MAX_TOTAL_CHANS][to_chan], pp3, 1) != 1) {
|
||||
|
||||
// Previously there was a debug message here about the packet being dropped by filtering.
|
||||
// This is now handled better by the "-df" command line option for filtering details.
|
||||
|
@ -1965,7 +1965,7 @@ static void maybe_xmit_packet_from_igate (char *message, int to_chan)
|
|||
char dest[AX25_MAX_ADDR_LEN]; /* Destination field. */
|
||||
ax25_get_addr_with_ssid (pp3, AX25_DESTINATION, dest);
|
||||
snprintf (payload, sizeof(payload), "%s>%s,TCPIP,%s*:%s",
|
||||
src, dest, save_audio_config_p->achan[to_chan].mycall, pinfo);
|
||||
src, dest, save_audio_config_p->mycall[to_chan], pinfo);
|
||||
|
||||
|
||||
#if DEBUGx
|
||||
|
@ -1991,7 +1991,7 @@ static void maybe_xmit_packet_from_igate (char *message, int to_chan)
|
|||
if (ig_to_tx_allow (pp3, to_chan)) {
|
||||
char radio [2400];
|
||||
snprintf (radio, sizeof(radio), "%s>%s%d%d%s:}%s",
|
||||
save_audio_config_p->achan[to_chan].mycall,
|
||||
save_audio_config_p->mycall[to_chan],
|
||||
APP_TOCALL, MAJOR_VERSION, MINOR_VERSION,
|
||||
save_igate_config_p->tx_via,
|
||||
payload);
|
||||
|
|
|
@ -69,7 +69,7 @@ struct il2p_context_s {
|
|||
int corrected; // Number of symbols corrected by RS FEC.
|
||||
};
|
||||
|
||||
static struct il2p_context_s *il2p_context[MAX_CHANS][MAX_SUBCHANS][MAX_SLICERS];
|
||||
static struct il2p_context_s *il2p_context[MAX_RADIO_CHANS][MAX_SUBCHANS][MAX_SLICERS];
|
||||
|
||||
|
||||
|
||||
|
@ -101,7 +101,7 @@ void il2p_rec_bit (int chan, int subchan, int slice, int dbit)
|
|||
|
||||
struct il2p_context_s *F = il2p_context[chan][subchan][slice];
|
||||
if (F == NULL) {
|
||||
assert (chan >= 0 && chan < MAX_CHANS);
|
||||
assert (chan >= 0 && chan < MAX_RADIO_CHANS);
|
||||
assert (subchan >= 0 && subchan < MAX_SUBCHANS);
|
||||
assert (slice >= 0 && slice < MAX_SLICERS);
|
||||
F = il2p_context[chan][subchan][slice] = (struct il2p_context_s *)malloc(sizeof (struct il2p_context_s));
|
||||
|
@ -251,12 +251,11 @@ void il2p_rec_bit (int chan, int subchan, int slice, int dbit)
|
|||
if (pp != NULL) {
|
||||
alevel_t alevel = demod_get_audio_level (chan, subchan);
|
||||
retry_t retries = F->corrected;
|
||||
int is_fx25 = 1; // FIXME: distinguish fx.25 and IL2P.
|
||||
// Currently this just means that a FEC mode was used.
|
||||
fec_type_t fec_type = fec_type_il2p;
|
||||
|
||||
// TODO: Could we put last 3 arguments in packet object rather than passing around separately?
|
||||
|
||||
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);
|
||||
}
|
||||
} // end block for local variables.
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
#include "gen_tone.h"
|
||||
|
||||
|
||||
static int number_of_bits_sent[MAX_CHANS]; // Count number of bits sent by "il2p_send_frame"
|
||||
static int number_of_bits_sent[MAX_RADIO_CHANS]; // Count number of bits sent by "il2p_send_frame"
|
||||
|
||||
static void send_bytes (int chan, unsigned char *b, int count, int polarity);
|
||||
static void send_bit (int chan, int b, int polarity);
|
||||
|
|
|
@ -612,7 +612,7 @@ void kiss_process_msg (unsigned char *kiss_msg, int kiss_len, int debug, struct
|
|||
/* Verify that the radio channel number is valid. */
|
||||
/* Any sort of medium should be OK here. */
|
||||
|
||||
if ((chan < 0 || chan >= MAX_CHANS || save_audio_config_p->chan_medium[chan] == MEDIUM_NONE)
|
||||
if ((chan < 0 || chan >= MAX_TOTAL_CHANS || save_audio_config_p->chan_medium[chan] == MEDIUM_NONE)
|
||||
&& save_audio_config_p->chan_medium[chan] != MEDIUM_IGATE) {
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf ("Invalid transmit channel %d from KISS client app.\n", chan);
|
||||
|
@ -663,10 +663,11 @@ void kiss_process_msg (unsigned char *kiss_msg, int kiss_len, int debug, struct
|
|||
}
|
||||
text_color_set(DW_COLOR_INFO);
|
||||
dw_printf ("KISS protocol set TXDELAY = %d (*10mS units = %d mS), chan %d\n", kiss_msg[1], kiss_msg[1] * 10, chan);
|
||||
if (kiss_msg[1] < 4 || kiss_msg[1] > 100) {
|
||||
if (kiss_msg[1] < 10 || kiss_msg[1] >= 100) {
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf ("Are you sure you want such an extreme value for TXDELAY?\n");
|
||||
dw_printf ("See \"Radio Channel - Transmit Timing\" section of User Guide for explanation.\n");
|
||||
dw_printf ("Read the Dire Wolf User Guide, \"Radio Channel - Transmit Timing\"\n");
|
||||
dw_printf ("section, to understand what this means.\n");
|
||||
}
|
||||
xmit_set_txdelay (chan, kiss_msg[1]);
|
||||
break;
|
||||
|
@ -683,7 +684,8 @@ void kiss_process_msg (unsigned char *kiss_msg, int kiss_len, int debug, struct
|
|||
if (kiss_msg[1] < 5 || kiss_msg[1] > 250) {
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf ("Are you sure you want such an extreme value for PERSIST?\n");
|
||||
dw_printf ("See \"Radio Channel - Transmit Timing\" section of User Guide for explanation.\n");
|
||||
dw_printf ("Read the Dire Wolf User Guide, \"Radio Channel - Transmit Timing\"\n");
|
||||
dw_printf ("section, to understand what this means.\n");
|
||||
}
|
||||
xmit_set_persist (chan, kiss_msg[1]);
|
||||
break;
|
||||
|
@ -700,7 +702,8 @@ void kiss_process_msg (unsigned char *kiss_msg, int kiss_len, int debug, struct
|
|||
if (kiss_msg[1] < 2 || kiss_msg[1] > 50) {
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf ("Are you sure you want such an extreme value for SLOTTIME?\n");
|
||||
dw_printf ("See \"Radio Channel - Transmit Timing\" section of User Guide for explanation.\n");
|
||||
dw_printf ("Read the Dire Wolf User Guide, \"Radio Channel - Transmit Timing\"\n");
|
||||
dw_printf ("section, to understand what this means.\n");
|
||||
}
|
||||
xmit_set_slottime (chan, kiss_msg[1]);
|
||||
break;
|
||||
|
@ -714,10 +717,11 @@ void kiss_process_msg (unsigned char *kiss_msg, int kiss_len, int debug, struct
|
|||
}
|
||||
text_color_set(DW_COLOR_INFO);
|
||||
dw_printf ("KISS protocol set TXtail = %d (*10mS units = %d mS), chan %d\n", kiss_msg[1], kiss_msg[1] * 10, chan);
|
||||
if (kiss_msg[1] < 2) {
|
||||
if (kiss_msg[1] < 5) {
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf ("Setting TXTAIL so low is asking for trouble. You probably don't want to do this.\n");
|
||||
dw_printf ("See \"Radio Channel - Transmit Timing\" section of User Guide for explanation.\n");
|
||||
dw_printf ("Read the Dire Wolf User Guide, \"Radio Channel - Transmit Timing\"\n");
|
||||
dw_printf ("section, to understand what this means.\n");
|
||||
}
|
||||
xmit_set_txtail (chan, kiss_msg[1]);
|
||||
break;
|
||||
|
|
|
@ -126,7 +126,7 @@ static struct {
|
|||
int age;
|
||||
unsigned int crc;
|
||||
int score;
|
||||
} candidate[MAX_CHANS][MAX_SUBCHANS][MAX_SLICERS];
|
||||
} candidate[MAX_RADIO_CHANS][MAX_SUBCHANS][MAX_SLICERS];
|
||||
|
||||
|
||||
|
||||
|
@ -135,7 +135,7 @@ static struct {
|
|||
#define PROCESS_AFTER_BITS 3
|
||||
|
||||
|
||||
static int process_age[MAX_CHANS];
|
||||
static int process_age[MAX_RADIO_CHANS];
|
||||
|
||||
static void pick_best_candidate (int chan);
|
||||
|
||||
|
@ -172,7 +172,7 @@ void multi_modem_init (struct audio_s *pa)
|
|||
demod_init (save_audio_config_p);
|
||||
hdlc_rec_init (save_audio_config_p);
|
||||
|
||||
for (chan=0; chan<MAX_CHANS; chan++) {
|
||||
for (chan=0; chan<MAX_RADIO_CHANS; chan++) {
|
||||
if (save_audio_config_p->chan_medium[chan] == MEDIUM_RADIO) {
|
||||
if (save_audio_config_p->achan[chan].baud <= 0) {
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
|
@ -222,7 +222,7 @@ void multi_modem_init (struct audio_s *pa)
|
|||
*
|
||||
*------------------------------------------------------------------------------*/
|
||||
|
||||
static float dc_average[MAX_CHANS];
|
||||
static float dc_average[MAX_RADIO_CHANS];
|
||||
|
||||
int multi_modem_get_dc_average (int chan)
|
||||
{
|
||||
|
@ -319,7 +319,7 @@ void multi_modem_process_rec_frame (int chan, int subchan, int slice, unsigned c
|
|||
packet_t pp;
|
||||
|
||||
|
||||
assert (chan >= 0 && chan < MAX_CHANS);
|
||||
assert (chan >= 0 && chan < MAX_RADIO_CHANS);
|
||||
assert (subchan >= 0 && subchan < MAX_SUBCHANS);
|
||||
assert (slice >= 0 && slice < MAX_SUBCHANS);
|
||||
|
||||
|
@ -329,8 +329,15 @@ void multi_modem_process_rec_frame (int chan, int subchan, int slice, unsigned c
|
|||
char nmea[256];
|
||||
ais_to_nmea (fbuf, flen, nmea, sizeof(nmea));
|
||||
|
||||
// The intention is for the AIS sentences to go only to attached applications.
|
||||
// e.g. SARTrack knows how to parse the AIS sentences.
|
||||
|
||||
// Put NOGATE in path so RF>IS IGates will block this.
|
||||
// TODO: Use station callsign, rather than "AIS," so we know where it is coming from,
|
||||
// if it happens to get onto RF somehow.
|
||||
|
||||
char monfmt[276];
|
||||
snprintf (monfmt, sizeof(monfmt), "AIS>%s%1d%1d:{%c%c%s", APP_TOCALL, MAJOR_VERSION, MINOR_VERSION, USER_DEF_USER_ID, USER_DEF_TYPE_AIS, nmea);
|
||||
snprintf (monfmt, sizeof(monfmt), "AIS>%s%1d%1d,NOGATE:{%c%c%s", APP_TOCALL, MAJOR_VERSION, MINOR_VERSION, USER_DEF_USER_ID, USER_DEF_TYPE_AIS, nmea);
|
||||
pp = ax25_from_text (monfmt, 1);
|
||||
|
||||
// alevel gets in there somehow making me question why it is passed thru here.
|
||||
|
@ -338,7 +345,7 @@ void multi_modem_process_rec_frame (int chan, int subchan, int slice, unsigned c
|
|||
else if (save_audio_config_p->achan[chan].modem_type == MODEM_EAS) {
|
||||
char monfmt[300]; // EAS SAME message max length is 268
|
||||
|
||||
snprintf (monfmt, sizeof(monfmt), "EAS>%s%1d%1d:{%c%c%s", APP_TOCALL, MAJOR_VERSION, MINOR_VERSION, USER_DEF_USER_ID, USER_DEF_TYPE_EAS, fbuf);
|
||||
snprintf (monfmt, sizeof(monfmt), "EAS>%s%1d%1d,NOGATE:{%c%c%s", APP_TOCALL, MAJOR_VERSION, MINOR_VERSION, USER_DEF_USER_ID, USER_DEF_TYPE_EAS, fbuf);
|
||||
pp = ax25_from_text (monfmt, 1);
|
||||
|
||||
// alevel gets in there somehow making me question why it is passed thru here.
|
||||
|
|
|
@ -99,7 +99,7 @@ typedef enum token_type_e { TOKEN_AND, TOKEN_OR, TOKEN_NOT, TOKEN_LPAREN, TOKEN_
|
|||
|
||||
typedef struct pfstate_s {
|
||||
|
||||
int from_chan; /* From and to channels. MAX_CHANS is used for IGate. */
|
||||
int from_chan; /* From and to channels. MAX_TOTAL_CHANS is used for IGate. */
|
||||
int to_chan; /* Used only for debug and error messages. */
|
||||
|
||||
/*
|
||||
|
@ -175,7 +175,7 @@ static char *bool2text (int val)
|
|||
*
|
||||
* Inputs: from_chan - Channel packet is coming from.
|
||||
* to_chan - Channel packet is going to.
|
||||
* Both are 0 .. MAX_CHANS-1 or MAX_CHANS for IGate.
|
||||
* Both are 0 .. MAX_TOTAL_CHANS-1 or MAX_TOTAL_CHANS for IGate.
|
||||
* For debug/error messages only.
|
||||
*
|
||||
* filter - String of filter specs and logical operators to combine them.
|
||||
|
@ -201,8 +201,8 @@ int pfilter (int from_chan, int to_chan, char *filter, packet_t pp, int is_aprs)
|
|||
char *p;
|
||||
int result;
|
||||
|
||||
assert (from_chan >= 0 && from_chan <= MAX_CHANS);
|
||||
assert (to_chan >= 0 && to_chan <= MAX_CHANS);
|
||||
assert (from_chan >= 0 && from_chan <= MAX_TOTAL_CHANS);
|
||||
assert (to_chan >= 0 && to_chan <= MAX_TOTAL_CHANS);
|
||||
|
||||
memset (&pfstate, 0, sizeof(pfstate));
|
||||
|
||||
|
@ -258,10 +258,10 @@ int pfilter (int from_chan, int to_chan, char *filter, packet_t pp, int is_aprs)
|
|||
|
||||
if (s_debug >= 1) {
|
||||
text_color_set(DW_COLOR_DEBUG);
|
||||
if (from_chan == MAX_CHANS) {
|
||||
if (from_chan == MAX_TOTAL_CHANS) {
|
||||
dw_printf (" Packet filter from IGate to radio channel %d returns %s\n", to_chan, bool2text(result));
|
||||
}
|
||||
else if (to_chan == MAX_CHANS) {
|
||||
else if (to_chan == MAX_TOTAL_CHANS) {
|
||||
dw_printf (" Packet filter from radio channel %d to IGate returns %s\n", from_chan, bool2text(result));
|
||||
}
|
||||
else if (is_aprs) {
|
||||
|
@ -1478,9 +1478,9 @@ static void print_error (pfstate_t *pf, char *msg)
|
|||
{
|
||||
char intro[50];
|
||||
|
||||
if (pf->from_chan == MAX_CHANS) {
|
||||
if (pf->from_chan == MAX_TOTAL_CHANS) {
|
||||
|
||||
if (pf->to_chan == MAX_CHANS) {
|
||||
if (pf->to_chan == MAX_TOTAL_CHANS) {
|
||||
snprintf (intro, sizeof(intro), "filter[IG,IG]: ");
|
||||
}
|
||||
else {
|
||||
|
@ -1489,7 +1489,7 @@ static void print_error (pfstate_t *pf, char *msg)
|
|||
}
|
||||
else {
|
||||
|
||||
if (pf->to_chan == MAX_CHANS) {
|
||||
if (pf->to_chan == MAX_TOTAL_CHANS) {
|
||||
snprintf (intro, sizeof(intro), "filter[%d,IG]: ", pf->from_chan);
|
||||
}
|
||||
else {
|
||||
|
|
34
src/ptt.c
34
src/ptt.c
|
@ -730,12 +730,12 @@ int gpiod_probe(const char *chip_name, int line_number)
|
|||
|
||||
|
||||
|
||||
static HANDLE ptt_fd[MAX_CHANS][NUM_OCTYPES];
|
||||
static HANDLE ptt_fd[MAX_RADIO_CHANS][NUM_OCTYPES];
|
||||
/* Serial port handle or fd. */
|
||||
/* Could be the same for two channels */
|
||||
/* if using both RTS and DTR. */
|
||||
#if USE_HAMLIB
|
||||
static RIG *rig[MAX_CHANS][NUM_OCTYPES];
|
||||
static RIG *rig[MAX_RADIO_CHANS][NUM_OCTYPES];
|
||||
#endif
|
||||
|
||||
static char otnames[NUM_OCTYPES][8];
|
||||
|
@ -761,7 +761,7 @@ void ptt_init (struct audio_s *audio_config_p)
|
|||
strlcpy (otnames[OCTYPE_CON], "CON", sizeof(otnames[OCTYPE_CON]));
|
||||
|
||||
|
||||
for (ch = 0; ch < MAX_CHANS; ch++) {
|
||||
for (ch = 0; ch < MAX_RADIO_CHANS; ch++) {
|
||||
int ot;
|
||||
|
||||
for (ot = 0; ot < NUM_OCTYPES; ot++) {
|
||||
|
@ -791,7 +791,7 @@ void ptt_init (struct audio_s *audio_config_p)
|
|||
* Set up serial ports.
|
||||
*/
|
||||
|
||||
for (ch = 0; ch < MAX_CHANS; ch++) {
|
||||
for (ch = 0; ch < MAX_RADIO_CHANS; ch++) {
|
||||
|
||||
if (audio_config_p->chan_medium[ch] == MEDIUM_RADIO) {
|
||||
int ot;
|
||||
|
@ -906,7 +906,7 @@ void ptt_init (struct audio_s *audio_config_p)
|
|||
*/
|
||||
|
||||
using_gpio = 0;
|
||||
for (ch=0; ch<MAX_CHANS; ch++) {
|
||||
for (ch=0; ch<MAX_RADIO_CHANS; ch++) {
|
||||
if (save_audio_config_p->chan_medium[ch] == MEDIUM_RADIO) {
|
||||
int ot;
|
||||
for (ot = 0; ot < NUM_OCTYPES; ot++) {
|
||||
|
@ -927,7 +927,7 @@ void ptt_init (struct audio_s *audio_config_p)
|
|||
}
|
||||
#if defined(USE_GPIOD)
|
||||
// GPIOD
|
||||
for (ch = 0; ch < MAX_CHANS; ch++) {
|
||||
for (ch = 0; ch < MAX_RADIO_CHANS; ch++) {
|
||||
if (save_audio_config_p->chan_medium[ch] == MEDIUM_RADIO) {
|
||||
for (int ot = 0; ot < NUM_OCTYPES; ot++) {
|
||||
if (audio_config_p->achan[ch].octrl[ot].ptt_method == PTT_METHOD_GPIOD) {
|
||||
|
@ -952,7 +952,7 @@ void ptt_init (struct audio_s *audio_config_p)
|
|||
* the pins we want to use.
|
||||
*/
|
||||
|
||||
for (ch = 0; ch < MAX_CHANS; ch++) {
|
||||
for (ch = 0; ch < MAX_RADIO_CHANS; ch++) {
|
||||
if (save_audio_config_p->chan_medium[ch] == MEDIUM_RADIO) {
|
||||
|
||||
int ot; // output control type, PTT, DCD, CON, ...
|
||||
|
@ -984,7 +984,7 @@ void ptt_init (struct audio_s *audio_config_p)
|
|||
|
||||
#if ( defined(__i386__) || defined(__x86_64__) ) && ( defined(__linux__) || defined(__unix__) )
|
||||
|
||||
for (ch = 0; ch < MAX_CHANS; ch++) {
|
||||
for (ch = 0; ch < MAX_RADIO_CHANS; ch++) {
|
||||
if (save_audio_config_p->chan_medium[ch] == MEDIUM_RADIO) {
|
||||
int ot;
|
||||
for (ot = 0; ot < NUM_OCTYPES; ot++) {
|
||||
|
@ -1051,7 +1051,7 @@ void ptt_init (struct audio_s *audio_config_p)
|
|||
#endif /* x86 Linux */
|
||||
|
||||
#ifdef USE_HAMLIB
|
||||
for (ch = 0; ch < MAX_CHANS; ch++) {
|
||||
for (ch = 0; ch < MAX_RADIO_CHANS; ch++) {
|
||||
if (save_audio_config_p->chan_medium[ch] == MEDIUM_RADIO) {
|
||||
int ot;
|
||||
for (ot = 0; ot < NUM_OCTYPES; ot++) {
|
||||
|
@ -1163,7 +1163,7 @@ void ptt_init (struct audio_s *audio_config_p)
|
|||
|
||||
#if USE_CM108
|
||||
|
||||
for (ch = 0; ch < MAX_CHANS; ch++) {
|
||||
for (ch = 0; ch < MAX_RADIO_CHANS; ch++) {
|
||||
|
||||
if (audio_config_p->chan_medium[ch] == MEDIUM_RADIO) {
|
||||
int ot;
|
||||
|
@ -1185,7 +1185,7 @@ void ptt_init (struct audio_s *audio_config_p)
|
|||
|
||||
/* Why doesn't it transmit? Probably forgot to specify PTT option. */
|
||||
|
||||
for (ch=0; ch<MAX_CHANS; ch++) {
|
||||
for (ch=0; ch<MAX_RADIO_CHANS; ch++) {
|
||||
if (audio_config_p->chan_medium[ch] == MEDIUM_RADIO) {
|
||||
if(audio_config_p->achan[ch].octrl[OCTYPE_PTT].ptt_method == PTT_METHOD_NONE) {
|
||||
text_color_set(DW_COLOR_INFO);
|
||||
|
@ -1251,14 +1251,14 @@ void ptt_set (int ot, int chan, int ptt_signal)
|
|||
int ptt2 = ptt_signal;
|
||||
|
||||
assert (ot >= 0 && ot < NUM_OCTYPES);
|
||||
assert (chan >= 0 && chan < MAX_CHANS);
|
||||
assert (chan >= 0 && chan < MAX_RADIO_CHANS);
|
||||
|
||||
if (ptt_debug_level >= 1) {
|
||||
text_color_set(DW_COLOR_DEBUG);
|
||||
dw_printf ("%s %d = %d\n", otnames[ot], chan, ptt_signal);
|
||||
}
|
||||
|
||||
assert (chan >= 0 && chan < MAX_CHANS);
|
||||
assert (chan >= 0 && chan < MAX_RADIO_CHANS);
|
||||
|
||||
if ( save_audio_config_p->chan_medium[chan] != MEDIUM_RADIO) {
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
|
@ -1494,7 +1494,7 @@ void ptt_set (int ot, int chan, int ptt_signal)
|
|||
int get_input (int it, int chan)
|
||||
{
|
||||
assert (it >= 0 && it < NUM_ICTYPES);
|
||||
assert (chan >= 0 && chan < MAX_CHANS);
|
||||
assert (chan >= 0 && chan < MAX_RADIO_CHANS);
|
||||
|
||||
if ( save_audio_config_p->chan_medium[chan] != MEDIUM_RADIO) {
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
|
@ -1559,7 +1559,7 @@ void ptt_term (void)
|
|||
{
|
||||
int n;
|
||||
|
||||
for (n = 0; n < MAX_CHANS; n++) {
|
||||
for (n = 0; n < MAX_RADIO_CHANS; n++) {
|
||||
if (save_audio_config_p->chan_medium[n] == MEDIUM_RADIO) {
|
||||
int ot;
|
||||
for (ot = 0; ot < NUM_OCTYPES; ot++) {
|
||||
|
@ -1568,7 +1568,7 @@ void ptt_term (void)
|
|||
}
|
||||
}
|
||||
|
||||
for (n = 0; n < MAX_CHANS; n++) {
|
||||
for (n = 0; n < MAX_RADIO_CHANS; n++) {
|
||||
if (save_audio_config_p->chan_medium[n] == MEDIUM_RADIO) {
|
||||
int ot;
|
||||
for (ot = 0; ot < NUM_OCTYPES; ot++) {
|
||||
|
@ -1586,7 +1586,7 @@ void ptt_term (void)
|
|||
|
||||
#ifdef USE_HAMLIB
|
||||
|
||||
for (n = 0; n < MAX_CHANS; n++) {
|
||||
for (n = 0; n < MAX_RADIO_CHANS; n++) {
|
||||
if (save_audio_config_p->chan_medium[n] == MEDIUM_RADIO) {
|
||||
int ot;
|
||||
for (ot = 0; ot < NUM_OCTYPES; ot++) {
|
||||
|
|
|
@ -108,6 +108,7 @@
|
|||
#include "dtmf.h"
|
||||
#include "aprs_tt.h"
|
||||
#include "ax25_link.h"
|
||||
#include "ring.h"
|
||||
|
||||
|
||||
#if __WIN32__
|
||||
|
@ -278,7 +279,7 @@ static void * recv_adev_thread (void *arg)
|
|||
// Try to re-init the audio device a couple times before giving up?
|
||||
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf ("Terminating after audio input failure.\n");
|
||||
dw_printf ("Terminating after audio device %d input failure.\n", a);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
|
|
|
@ -83,7 +83,7 @@ rrbb_t rrbb_new (int chan, int subchan, int slice, int is_scrambled, int descram
|
|||
{
|
||||
rrbb_t result;
|
||||
|
||||
assert (chan >= 0 && chan < MAX_CHANS);
|
||||
assert (chan >= 0 && chan < MAX_RADIO_CHANS);
|
||||
assert (subchan >= 0 && subchan < MAX_SUBCHANS);
|
||||
assert (slice >= 0 && slice < MAX_SLICERS);
|
||||
|
||||
|
@ -333,7 +333,7 @@ int rrbb_get_chan (rrbb_t b)
|
|||
assert (b->magic1 == MAGIC1);
|
||||
assert (b->magic2 == MAGIC2);
|
||||
|
||||
assert (b->chan >= 0 && b->chan < MAX_CHANS);
|
||||
assert (b->chan >= 0 && b->chan < MAX_RADIO_CHANS);
|
||||
|
||||
return (b->chan);
|
||||
}
|
||||
|
|
12
src/server.c
12
src/server.c
|
@ -1413,7 +1413,7 @@ static THREAD_F cmd_listen_thread (void *arg)
|
|||
/*
|
||||
* Take some precautions to guard against bad data which could cause problems later.
|
||||
*/
|
||||
if (cmd.hdr.portx < 0 || cmd.hdr.portx >= MAX_CHANS) {
|
||||
if (cmd.hdr.portx < 0 || cmd.hdr.portx >= MAX_TOTAL_CHANS) {
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf ("\nInvalid port number, %d, in command '%c', from AGW client application %d.\n",
|
||||
cmd.hdr.portx, cmd.hdr.datakind, client);
|
||||
|
@ -1544,7 +1544,7 @@ static THREAD_F cmd_listen_thread (void *arg)
|
|||
// No other place cares about total number.
|
||||
|
||||
count = 0;
|
||||
for (j=0; j<MAX_CHANS; j++) {
|
||||
for (j=0; j<MAX_TOTAL_CHANS; j++) {
|
||||
if (save_audio_config_p->chan_medium[j] == MEDIUM_RADIO ||
|
||||
save_audio_config_p->chan_medium[j] == MEDIUM_IGATE ||
|
||||
save_audio_config_p->chan_medium[j] == MEDIUM_NETTNC) {
|
||||
|
@ -1553,7 +1553,7 @@ static THREAD_F cmd_listen_thread (void *arg)
|
|||
}
|
||||
snprintf (reply.info, sizeof(reply.info), "%d;", count);
|
||||
|
||||
for (j=0; j<MAX_CHANS; j++) {
|
||||
for (j=0; j<MAX_TOTAL_CHANS; j++) {
|
||||
|
||||
switch (save_audio_config_p->chan_medium[j]) {
|
||||
|
||||
|
@ -1850,7 +1850,7 @@ static THREAD_F cmd_listen_thread (void *arg)
|
|||
|
||||
// Connected mode can only be used with internal modems.
|
||||
|
||||
if (chan >= 0 && chan < MAX_CHANS && save_audio_config_p->chan_medium[chan] == MEDIUM_RADIO) {
|
||||
if (chan >= 0 && chan < MAX_RADIO_CHANS && save_audio_config_p->chan_medium[chan] == MEDIUM_RADIO) {
|
||||
ok = 1;
|
||||
dlq_register_callsign (cmd.hdr.call_from, chan, client);
|
||||
}
|
||||
|
@ -1879,7 +1879,7 @@ static THREAD_F cmd_listen_thread (void *arg)
|
|||
|
||||
// Connected mode can only be used with internal modems.
|
||||
|
||||
if (chan >= 0 && chan < MAX_CHANS && save_audio_config_p->chan_medium[chan] == MEDIUM_RADIO) {
|
||||
if (chan >= 0 && chan < MAX_RADIO_CHANS && save_audio_config_p->chan_medium[chan] == MEDIUM_RADIO) {
|
||||
dlq_unregister_callsign (cmd.hdr.call_from, chan, client);
|
||||
}
|
||||
else {
|
||||
|
@ -2066,7 +2066,7 @@ static THREAD_F cmd_listen_thread (void *arg)
|
|||
reply.hdr.data_len_NETLE = host2netle(4);
|
||||
|
||||
int n = 0;
|
||||
if (cmd.hdr.portx >= 0 && cmd.hdr.portx < MAX_CHANS) {
|
||||
if (cmd.hdr.portx >= 0 && cmd.hdr.portx < MAX_RADIO_CHANS) {
|
||||
// Count both normal and expedited in transmit queue for given channel.
|
||||
n = tq_count (cmd.hdr.portx, -1, "", "", 0);
|
||||
}
|
||||
|
|
|
@ -71,7 +71,7 @@
|
|||
#define T_NUM_ANALOG 5 /* Number of analog channels. */
|
||||
#define T_NUM_DIGITAL 8 /* Number of digital channels. */
|
||||
|
||||
#define T_STR_LEN 16 /* Max len for labels and units. */
|
||||
#define T_STR_LEN 32 /* Max len for labels and units. */
|
||||
|
||||
|
||||
#define MAGIC1 0x5a1111a5 /* For checking storage allocation problems. */
|
||||
|
|
|
@ -285,7 +285,7 @@ int main (int argc, char *argv[])
|
|||
setlinebuf (stdout);
|
||||
#endif
|
||||
|
||||
start_dtime = dtime_now();
|
||||
start_dtime = dtime_monotonic();
|
||||
|
||||
/*
|
||||
* Extract command line args.
|
||||
|
@ -615,7 +615,7 @@ void process_rec_data (int my_index, char *data)
|
|||
* and sent to a common function to check that they
|
||||
* all arrived in order.
|
||||
*
|
||||
* Global Out: is_connected - Updated when connected/disconnected notifications are received.
|
||||
* Global Out: is_connected - Updated when connected/disconnected notfications are received.
|
||||
*
|
||||
* Description: Perform any necessary configuration for the TNC then wait
|
||||
* for responses and process them.
|
||||
|
@ -859,7 +859,7 @@ static void * tnc_thread_net (void *arg)
|
|||
* What did we get?
|
||||
*/
|
||||
|
||||
dnow = dtime_now();
|
||||
dnow = dtime_monotonic();
|
||||
|
||||
switch (mon_cmd.datakind) {
|
||||
|
||||
|
@ -943,7 +943,7 @@ static void * tnc_thread_net (void *arg)
|
|||
* and sent to a common function to check that they
|
||||
* all arrived in order.
|
||||
*
|
||||
* Global Out: is_connected - Updated when connected/disconnected notifications are received.
|
||||
* Global Out: is_connected - Updated when connected/disconnected notfications are received.
|
||||
*
|
||||
* Description: Perform any necessary configuration for the TNC then wait
|
||||
* for responses and process them.
|
||||
|
@ -1038,12 +1038,12 @@ static void * tnc_thread_serial (void *arg)
|
|||
done = 1;
|
||||
}
|
||||
else if (ch == XOFF) {
|
||||
double dnow = dtime_now();
|
||||
double dnow = dtime_monotonic();
|
||||
printf("%*s[R %.3f] <XOFF>\n", my_index*column_width, "", dnow-start_dtime);
|
||||
busy[my_index] = 1;
|
||||
}
|
||||
else if (ch == XON) {
|
||||
double dnow = dtime_now();
|
||||
double dnow = dtime_monotonic();
|
||||
printf("%*s[R %.3f] <XON>\n", my_index*column_width, "", dnow-start_dtime);
|
||||
busy[my_index] = 0;
|
||||
}
|
||||
|
@ -1070,7 +1070,7 @@ static void * tnc_thread_serial (void *arg)
|
|||
|
||||
if (len > 0) {
|
||||
|
||||
double dnow = dtime_now();
|
||||
double dnow = dtime_monotonic();
|
||||
|
||||
printf("%*s[R %.3f] %s\n", my_index*column_width, "", dnow-start_dtime, result);
|
||||
|
||||
|
@ -1109,7 +1109,7 @@ static void * tnc_thread_serial (void *arg)
|
|||
static void tnc_connect (int from, int to)
|
||||
{
|
||||
|
||||
double dnow = dtime_now();
|
||||
double dnow = dtime_monotonic();
|
||||
|
||||
printf("%*s[T %.3f] *** Send connect request ***\n", from*column_width, "", dnow-start_dtime);
|
||||
|
||||
|
@ -1160,7 +1160,7 @@ static void tnc_connect (int from, int to)
|
|||
|
||||
static void tnc_disconnect (int from, int to)
|
||||
{
|
||||
double dnow = dtime_now();
|
||||
double dnow = dtime_monotonic();
|
||||
|
||||
printf("%*s[T %.3f] *** Send disconnect request ***\n", from*column_width, "", dnow-start_dtime);
|
||||
|
||||
|
@ -1201,7 +1201,7 @@ static void tnc_disconnect (int from, int to)
|
|||
|
||||
static void tnc_reset (int from, int to)
|
||||
{
|
||||
double dnow = dtime_now();
|
||||
double dnow = dtime_monotonic();
|
||||
|
||||
printf("%*s[T %.3f] *** Send reset ***\n", from*column_width, "", dnow-start_dtime);
|
||||
|
||||
|
@ -1232,7 +1232,7 @@ static void tnc_reset (int from, int to)
|
|||
|
||||
static void tnc_send_data (int from, int to, char * data)
|
||||
{
|
||||
double dnow = dtime_now();
|
||||
double dnow = dtime_monotonic();
|
||||
|
||||
printf("%*s[T %.3f] %s\n", from*column_width, "", dnow-start_dtime, data);
|
||||
|
||||
|
@ -1257,7 +1257,7 @@ static void tnc_send_data (int from, int to, char * data)
|
|||
else {
|
||||
|
||||
// The assumption is that we are in CONVERS mode.
|
||||
// The data should be terminated by carriage return.
|
||||
// The data sould be terminated by carriage return.
|
||||
|
||||
int timeout = 600; // 60 sec. I've seen it take more than 20.
|
||||
while (timeout > 0 && busy[from]) {
|
||||
|
|
66
src/tq.c
66
src/tq.c
|
@ -52,10 +52,10 @@
|
|||
#include "dedupe.h"
|
||||
#include "igate.h"
|
||||
#include "dtime_now.h"
|
||||
#include "nettnc.h"
|
||||
|
||||
|
||||
|
||||
static packet_t queue_head[MAX_CHANS][TQ_NUM_PRIO]; /* Head of linked list for each queue. */
|
||||
static packet_t queue_head[MAX_RADIO_CHANS][TQ_NUM_PRIO]; /* Head of linked list for each queue. */
|
||||
|
||||
|
||||
static dw_mutex_t tq_mutex; /* Critical section for updating queues. */
|
||||
|
@ -63,15 +63,15 @@ static dw_mutex_t tq_mutex; /* Critical section for updating queues. */
|
|||
|
||||
#if __WIN32__
|
||||
|
||||
static HANDLE wake_up_event[MAX_CHANS]; /* Notify transmit thread when queue not empty. */
|
||||
static HANDLE wake_up_event[MAX_RADIO_CHANS]; /* Notify transmit thread when queue not empty. */
|
||||
|
||||
#else
|
||||
|
||||
static pthread_cond_t wake_up_cond[MAX_CHANS]; /* Notify transmit thread when queue not empty. */
|
||||
static pthread_cond_t wake_up_cond[MAX_RADIO_CHANS]; /* Notify transmit thread when queue not empty. */
|
||||
|
||||
static pthread_mutex_t wake_up_mutex[MAX_CHANS]; /* Required by cond_wait. */
|
||||
static pthread_mutex_t wake_up_mutex[MAX_RADIO_CHANS]; /* Required by cond_wait. */
|
||||
|
||||
static int xmit_thread_is_waiting[MAX_CHANS];
|
||||
static int xmit_thread_is_waiting[MAX_RADIO_CHANS];
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -128,7 +128,7 @@ void tq_init (struct audio_s *audio_config_p)
|
|||
|
||||
save_audio_config_p = audio_config_p;
|
||||
|
||||
for (c=0; c<MAX_CHANS; c++) {
|
||||
for (c=0; c<MAX_RADIO_CHANS; c++) {
|
||||
for (p=0; p<TQ_NUM_PRIO; p++) {
|
||||
queue_head[c][p] = NULL;
|
||||
}
|
||||
|
@ -147,7 +147,7 @@ void tq_init (struct audio_s *audio_config_p)
|
|||
|
||||
#if __WIN32__
|
||||
|
||||
for (c = 0; c < MAX_CHANS; c++) {
|
||||
for (c = 0; c < MAX_RADIO_CHANS; c++) {
|
||||
|
||||
if (audio_config_p->chan_medium[c] == MEDIUM_RADIO) {
|
||||
|
||||
|
@ -164,7 +164,7 @@ void tq_init (struct audio_s *audio_config_p)
|
|||
#else
|
||||
int err;
|
||||
|
||||
for (c = 0; c < MAX_CHANS; c++) {
|
||||
for (c = 0; c < MAX_RADIO_CHANS; c++) {
|
||||
|
||||
xmit_thread_is_waiting[c] = 0;
|
||||
|
||||
|
@ -199,6 +199,9 @@ void tq_init (struct audio_s *audio_config_p)
|
|||
* New in 1.7:
|
||||
* Channel can be assigned to IGate rather than a radio.
|
||||
*
|
||||
* New in 1.8:
|
||||
* Channel can be assigned to a network TNC.
|
||||
*
|
||||
* prio - Priority, use TQ_PRIO_0_HI for digipeated or
|
||||
* TQ_PRIO_1_LO for normal.
|
||||
*
|
||||
|
@ -252,10 +255,13 @@ void tq_append (int chan, int prio, packet_t pp)
|
|||
#endif
|
||||
|
||||
// New in 1.7 - A channel can be assigned to the IGate rather than a radio.
|
||||
// New in 1.8: Assign a channel to external network TNC.
|
||||
// Send somewhere else, rather than the transmit queue.
|
||||
|
||||
#ifndef DIGITEST // avoid dtest link error
|
||||
|
||||
if (save_audio_config_p->chan_medium[chan] == MEDIUM_IGATE) {
|
||||
if (save_audio_config_p->chan_medium[chan] == MEDIUM_IGATE ||
|
||||
save_audio_config_p->chan_medium[chan] == MEDIUM_NETTNC) {
|
||||
|
||||
char ts[100]; // optional time stamp.
|
||||
|
||||
|
@ -274,21 +280,39 @@ void tq_append (int chan, int prio, packet_t pp)
|
|||
unsigned char *pinfo;
|
||||
int info_len = ax25_get_info (pp, &pinfo);
|
||||
text_color_set(DW_COLOR_XMIT);
|
||||
dw_printf ("[%d>is%s] ", chan, ts);
|
||||
dw_printf ("%s", stemp); /* stations followed by : */
|
||||
ax25_safe_print ((char *)pinfo, info_len, ! ax25_is_aprs(pp));
|
||||
dw_printf ("\n");
|
||||
|
||||
igate_send_rec_packet (chan, pp);
|
||||
if (save_audio_config_p->chan_medium[chan] == MEDIUM_IGATE) {
|
||||
|
||||
dw_printf ("[%d>is%s] ", chan, ts);
|
||||
dw_printf ("%s", stemp); /* stations followed by : */
|
||||
ax25_safe_print ((char *)pinfo, info_len, ! ax25_is_aprs(pp));
|
||||
dw_printf ("\n");
|
||||
|
||||
igate_send_rec_packet (chan, pp);
|
||||
}
|
||||
else { // network TNC
|
||||
dw_printf ("[%d>nt%s] ", chan, ts);
|
||||
dw_printf ("%s", stemp); /* stations followed by : */
|
||||
ax25_safe_print ((char *)pinfo, info_len, ! ax25_is_aprs(pp));
|
||||
dw_printf ("\n");
|
||||
|
||||
nettnc_send_packet (chan, pp);
|
||||
|
||||
}
|
||||
|
||||
ax25_delete(pp);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Normal case - put in queue for radio transmission.
|
||||
// Error if trying to transmit to a radio channel which was not configured.
|
||||
|
||||
if (chan < 0 || chan >= MAX_CHANS || save_audio_config_p->chan_medium[chan] == MEDIUM_NONE) {
|
||||
if (chan < 0 || chan >= MAX_RADIO_CHANS || save_audio_config_p->chan_medium[chan] == MEDIUM_NONE) {
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf ("ERROR - Request to transmit on invalid radio channel %d.\n", chan);
|
||||
dw_printf ("This is probably a client application error, not a problem with direwolf.\n");
|
||||
|
@ -490,7 +514,7 @@ void lm_data_request (int chan, int prio, packet_t pp)
|
|||
}
|
||||
#endif
|
||||
|
||||
if (chan < 0 || chan >= MAX_CHANS || save_audio_config_p->chan_medium[chan] != MEDIUM_RADIO) {
|
||||
if (chan < 0 || chan >= MAX_RADIO_CHANS || save_audio_config_p->chan_medium[chan] != MEDIUM_RADIO) {
|
||||
// Connected mode is allowed only with internal modems.
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf ("ERROR - Request to transmit on invalid radio channel %d.\n", chan);
|
||||
|
@ -648,7 +672,7 @@ void lm_seize_request (int chan)
|
|||
#endif
|
||||
|
||||
|
||||
if (chan < 0 || chan >= MAX_CHANS || save_audio_config_p->chan_medium[chan] != MEDIUM_RADIO) {
|
||||
if (chan < 0 || chan >= MAX_RADIO_CHANS || save_audio_config_p->chan_medium[chan] != MEDIUM_RADIO) {
|
||||
// Connected mode is allowed only with internal modems.
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf ("ERROR - Request to transmit on invalid radio channel %d.\n", chan);
|
||||
|
@ -748,7 +772,7 @@ void tq_wait_while_empty (int chan)
|
|||
text_color_set(DW_COLOR_DEBUG);
|
||||
dw_printf ("tq_wait_while_empty (%d) : enter critical section\n", chan);
|
||||
#endif
|
||||
assert (chan >= 0 && chan < MAX_CHANS);
|
||||
assert (chan >= 0 && chan < MAX_RADIO_CHANS);
|
||||
|
||||
dw_mutex_lock (&tq_mutex);
|
||||
|
||||
|
@ -944,7 +968,7 @@ static int tq_is_empty (int chan)
|
|||
{
|
||||
int p;
|
||||
|
||||
assert (chan >= 0 && chan < MAX_CHANS);
|
||||
assert (chan >= 0 && chan < MAX_RADIO_CHANS);
|
||||
|
||||
|
||||
for (p=0; p<TQ_NUM_PRIO; p++) {
|
||||
|
@ -1001,7 +1025,7 @@ int tq_count (int chan, int prio, char *source, char *dest, int bytes)
|
|||
|
||||
// Array bounds check. FIXME: TODO: should have internal error instead of dying.
|
||||
|
||||
if (chan < 0 || chan >= MAX_CHANS || prio < 0 || prio >= TQ_NUM_PRIO) {
|
||||
if (chan < 0 || chan >= MAX_RADIO_CHANS || prio < 0 || prio >= TQ_NUM_PRIO) {
|
||||
text_color_set(DW_COLOR_DEBUG);
|
||||
dw_printf ("INTERNAL ERROR - tq_count(%d, %d, \"%s\", \"%s\", %d)\n", chan, prio, source, dest, bytes);
|
||||
return (0);
|
||||
|
|
|
@ -819,10 +819,10 @@ static void xmit_object_report (int i, int first_time)
|
|||
*/
|
||||
|
||||
if (save_tt_config_p->obj_xmit_chan >= 0) {
|
||||
strlcpy (stemp, save_audio_config_p->achan[save_tt_config_p->obj_xmit_chan].mycall, sizeof(stemp));
|
||||
strlcpy (stemp, save_audio_config_p->mycall[save_tt_config_p->obj_xmit_chan], sizeof(stemp));
|
||||
}
|
||||
else {
|
||||
strlcpy (stemp, save_audio_config_p->achan[save_tt_config_p->obj_recv_chan].mycall, sizeof(stemp));
|
||||
strlcpy (stemp, save_audio_config_p->mycall[save_tt_config_p->obj_recv_chan], sizeof(stemp));
|
||||
}
|
||||
strlcat (stemp, ">", sizeof(stemp));
|
||||
strlcat (stemp, APP_TOCALL, sizeof(stemp));
|
||||
|
@ -1134,7 +1134,7 @@ int main (int argc, char *argv[])
|
|||
|
||||
memset (&my_audio_config, 0, sizeof(my_audio_config));
|
||||
|
||||
strlcpy (my_audio_config.achan[0].mycall, "WB2OSZ-15", sizeof(my_audio_config.achan[0].mycall));
|
||||
strlcpy (my_audio_config.mycall[0], "WB2OSZ-15", sizeof(my_audio_config.mycall[0]));
|
||||
|
||||
/* Fake TT gateway config. */
|
||||
|
||||
|
|
30
src/xmit.c
30
src/xmit.c
|
@ -88,24 +88,24 @@
|
|||
*/
|
||||
|
||||
|
||||
static int xmit_slottime[MAX_CHANS]; /* Slot time in 10 mS units for persistence algorithm. */
|
||||
static int xmit_slottime[MAX_RADIO_CHANS]; /* Slot time in 10 mS units for persistence algorithm. */
|
||||
|
||||
static int xmit_persist[MAX_CHANS]; /* Sets probability for transmitting after each */
|
||||
static int xmit_persist[MAX_RADIO_CHANS]; /* Sets probability for transmitting after each */
|
||||
/* slot time delay. Transmit if a random number */
|
||||
/* in range of 0 - 255 <= persist value. */
|
||||
/* Otherwise wait another slot time and try again. */
|
||||
|
||||
static int xmit_txdelay[MAX_CHANS]; /* After turning on the transmitter, */
|
||||
static int xmit_txdelay[MAX_RADIO_CHANS]; /* After turning on the transmitter, */
|
||||
/* send "flags" for txdelay * 10 mS. */
|
||||
|
||||
static int xmit_txtail[MAX_CHANS]; /* Amount of time to keep transmitting after we */
|
||||
static int xmit_txtail[MAX_RADIO_CHANS]; /* Amount of time to keep transmitting after we */
|
||||
/* are done sending the data. This is to avoid */
|
||||
/* dropping PTT too soon and chopping off the end */
|
||||
/* of the frame. Again 10 mS units. */
|
||||
|
||||
static int xmit_fulldup[MAX_CHANS]; /* Full duplex if non-zero. */
|
||||
static int xmit_fulldup[MAX_RADIO_CHANS]; /* Full duplex if non-zero. */
|
||||
|
||||
static int xmit_bits_per_sec[MAX_CHANS]; /* Data transmission rate. */
|
||||
static int xmit_bits_per_sec[MAX_RADIO_CHANS]; /* Data transmission rate. */
|
||||
/* Often called baud rate which is equivalent for */
|
||||
/* 1200 & 9600 cases but could be different with other */
|
||||
/* modulation techniques. */
|
||||
|
@ -211,11 +211,11 @@ void xmit_init (struct audio_s *p_modem, int debug_xmit_packet)
|
|||
int ad;
|
||||
|
||||
#if __WIN32__
|
||||
HANDLE xmit_th[MAX_CHANS];
|
||||
HANDLE xmit_th[MAX_RADIO_CHANS];
|
||||
#else
|
||||
//pthread_attr_t attr;
|
||||
//struct sched_param sp;
|
||||
pthread_t xmit_tid[MAX_CHANS];
|
||||
pthread_t xmit_tid[MAX_RADIO_CHANS];
|
||||
#endif
|
||||
//int e;
|
||||
|
||||
|
@ -247,7 +247,7 @@ void xmit_init (struct audio_s *p_modem, int debug_xmit_packet)
|
|||
* TODO1.2: Any reason to use global config rather than making a copy?
|
||||
*/
|
||||
|
||||
for (j=0; j<MAX_CHANS; j++) {
|
||||
for (j=0; j<MAX_RADIO_CHANS; j++) {
|
||||
xmit_bits_per_sec[j] = p_modem->achan[j].baud;
|
||||
xmit_slottime[j] = p_modem->achan[j].slottime;
|
||||
xmit_persist[j] = p_modem->achan[j].persist;
|
||||
|
@ -276,7 +276,7 @@ void xmit_init (struct audio_s *p_modem, int debug_xmit_packet)
|
|||
// underrun on the audio output device.
|
||||
|
||||
|
||||
for (j=0; j<MAX_CHANS; j++) {
|
||||
for (j=0; j<MAX_RADIO_CHANS; j++) {
|
||||
|
||||
if (p_modem->chan_medium[j] == MEDIUM_RADIO) {
|
||||
#if __WIN32__
|
||||
|
@ -365,35 +365,35 @@ void xmit_init (struct audio_s *p_modem, int debug_xmit_packet)
|
|||
|
||||
void xmit_set_txdelay (int channel, int value)
|
||||
{
|
||||
if (channel >= 0 && channel < MAX_CHANS) {
|
||||
if (channel >= 0 && channel < MAX_RADIO_CHANS) {
|
||||
xmit_txdelay[channel] = value;
|
||||
}
|
||||
}
|
||||
|
||||
void xmit_set_persist (int channel, int value)
|
||||
{
|
||||
if (channel >= 0 && channel < MAX_CHANS) {
|
||||
if (channel >= 0 && channel < MAX_RADIO_CHANS) {
|
||||
xmit_persist[channel] = value;
|
||||
}
|
||||
}
|
||||
|
||||
void xmit_set_slottime (int channel, int value)
|
||||
{
|
||||
if (channel >= 0 && channel < MAX_CHANS) {
|
||||
if (channel >= 0 && channel < MAX_RADIO_CHANS) {
|
||||
xmit_slottime[channel] = value;
|
||||
}
|
||||
}
|
||||
|
||||
void xmit_set_txtail (int channel, int value)
|
||||
{
|
||||
if (channel >= 0 && channel < MAX_CHANS) {
|
||||
if (channel >= 0 && channel < MAX_RADIO_CHANS) {
|
||||
xmit_txtail[channel] = value;
|
||||
}
|
||||
}
|
||||
|
||||
void xmit_set_fulldup (int channel, int value)
|
||||
{
|
||||
if (channel >= 0 && channel < MAX_CHANS) {
|
||||
if (channel >= 0 && channel < MAX_RADIO_CHANS) {
|
||||
xmit_fulldup[channel] = value;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue