Skip to content

Commit

Permalink
New NCHANNEL feature.
Browse files Browse the repository at this point in the history
  • Loading branch information
wb2osz committed Jul 18, 2024
1 parent c05669a commit ae888b0
Show file tree
Hide file tree
Showing 56 changed files with 697 additions and 391 deletions.
3 changes: 3 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 ##
Expand Down
2 changes: 1 addition & 1 deletion conf/generic.conf
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
1 change: 1 addition & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ list(APPEND direwolf_SOURCES
morse.c
multi_modem.c
waypoint.c
nettnc.c
serial_port.c
pfilter.c
ptt.c
Expand Down
2 changes: 1 addition & 1 deletion src/agwlib.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion src/appserver.c
Original file line number Diff line number Diff line change
Expand Up @@ -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))) {
Expand Down
8 changes: 4 additions & 4 deletions src/aprs_tt.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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';
}
Expand Down Expand Up @@ -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 != '.') {
Expand Down
11 changes: 6 additions & 5 deletions src/atest.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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",
Expand All @@ -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 */
Expand Down Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion src/audio.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
27 changes: 21 additions & 6 deletions src/audio.h
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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)
Expand All @@ -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. */

Expand All @@ -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;
Expand Down Expand Up @@ -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 */
Expand Down
2 changes: 1 addition & 1 deletion src/audio_portaudio.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
20 changes: 15 additions & 5 deletions src/audio_win.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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");
Expand All @@ -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);

Expand Down
39 changes: 33 additions & 6 deletions src/ax25_link.c
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -679,18 +679,45 @@ 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)
{

/*
* Save parameters for later use.
*/
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 */


Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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;

Expand Down
2 changes: 1 addition & 1 deletion src/ax25_link.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);



Expand Down
18 changes: 16 additions & 2 deletions src/ax25_pad.c
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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
Expand Down
Loading

0 comments on commit ae888b0

Please sign in to comment.