Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,9 @@ list(APPEND direwolf_SOURCES
morse.c
multi_modem.c
waypoint.c
tnc_common.c
nettnc.c
sertnc.c
serial_port.c
pfilter.c
ptt.c
Expand Down
10 changes: 9 additions & 1 deletion src/audio.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@ 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. (new in 1.8)
MEDIUM_NETTNC, // Remote network TNC. (new in 1.8)
MEDIUM_SERTNC }; // Local serial TNC. (new in 1.8)


typedef enum sanity_e { SANITY_APRS, SANITY_AX25, SANITY_NONE } sanity_t;
Expand Down Expand Up @@ -152,6 +153,7 @@ struct audio_s {
// MEDIUM_RADIO for internal modem. (only possibility earlier)
// MEDIUM_IGATE allows application access to IGate.
// MEDIUM_NETTNC for external TNC via TCP.
// MEDIUM_SERTNC for external TNC via serial port.

int igate_vchannel; /* Virtual channel mapped to APRS-IS. */
/* -1 for none. */
Expand All @@ -164,6 +166,12 @@ struct audio_s {

int nettnc_port[MAX_TOTAL_CHANS]; // Network TNC TCP port.

// Applies only to serial TNC type channels.

char sertnc_device[MAX_TOTAL_CHANS][80]; // Serial TNC device name.

int sertnc_baud[MAX_TOTAL_CHANS]; // Serial TNC baud rate.



/* Properties for each radio channel, common to receive and transmit. */
Expand Down
3 changes: 2 additions & 1 deletion src/beacon.c
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,8 @@ void beacon_init (struct audio_s *pmodem, struct misc_config_s *pconfig, struct
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) {
g_modem_config_p->chan_medium[chan] == MEDIUM_NETTNC ||
g_modem_config_p->chan_medium[chan] == MEDIUM_SERTNC) {

if (strlen(g_modem_config_p->mycall[chan]) > 0 &&
strcasecmp(g_modem_config_p->mycall[chan], "N0CALL") != 0 &&
Expand Down
3 changes: 2 additions & 1 deletion src/cdigipeater.c
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,8 @@ void cdigipeater (int from_chan, packet_t pp)

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) ) {
save_audio_config_p->chan_medium[from_chan] != MEDIUM_NETTNC &&
save_audio_config_p->chan_medium[from_chan] != MEDIUM_SERTNC) ) {
text_color_set(DW_COLOR_ERROR);
dw_printf ("cdigipeater: Did not expect to receive on invalid channel %d.\n", from_chan);
return;
Expand Down
87 changes: 80 additions & 7 deletions src/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -1381,6 +1381,70 @@ void config_init (char *fname, struct audio_s *p_audio_config,
p_audio_config->nettnc_port[nchan] = atoi(t);
}

/*
* SCHANNEL chan device baudrate - Define Serial TNC virtual channel.
*
* This allows a client application to talk to to an external TNC over serial 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.
* device = device (serial port) name of serial TNC.
* baudrate = baud rate for communicating with serial TNC.
*
* Future: Might allow selection of channel on the serial TNC.
* For now, ignore incoming and set to 0 for outgoing.
*
* FIXME: Can't set mycall for schannel.
*/

else if (strcasecmp(t, "SCHANNEL") == 0) {
t = split(NULL,0);
if (t == NULL) {
text_color_set(DW_COLOR_ERROR);
dw_printf ("Line %d: Missing virtual channel number for SCHANNEL 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_SERTNC;
}
else {
text_color_set(DW_COLOR_ERROR);
dw_printf ("Line %d: SCHANNEL 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: SCHANNEL 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 serial TNC device for SCHANNEL command.\n", line);
continue;
}
strlcpy (p_audio_config->sertnc_device[nchan], t, sizeof(p_audio_config->sertnc_device[nchan]));
int n;
t = split(NULL,0);
if (t != NULL) {
n = atoi(t);
if (n != 1200 && n != 2400 && n != 4800 && n != 9600 && n != 19200 && n != 38400 && n != 57600 && n != 115200) {
text_color_set(DW_COLOR_ERROR);
dw_printf ("Line %d: Warning: Unsupported data rate of %d bits per second. Using 9600.\n", line, n);
n = 9600;
}
p_audio_config->sertnc_baud[nchan] = n;
}
else {
p_audio_config->sertnc_baud[nchan] = 9600;
}
}

/*
* MYCALL station
*/
Expand Down Expand Up @@ -2749,7 +2813,8 @@ void config_init (char *fname, struct audio_s *p_audio_config,
// Channels specified must be radio channels or network TNCs.

if (p_audio_config->chan_medium[from_chan] != MEDIUM_RADIO &&
p_audio_config->chan_medium[from_chan] != MEDIUM_NETTNC) {
p_audio_config->chan_medium[from_chan] != MEDIUM_NETTNC &&
p_audio_config->chan_medium[from_chan] != MEDIUM_SERTNC) {
text_color_set(DW_COLOR_ERROR);
dw_printf ("Config file, line %d: FROM-channel %d is not valid.\n",
line, from_chan);
Expand Down Expand Up @@ -2777,7 +2842,8 @@ void config_init (char *fname, struct audio_s *p_audio_config,
}

if (p_audio_config->chan_medium[to_chan] != MEDIUM_RADIO &&
p_audio_config->chan_medium[to_chan] != MEDIUM_NETTNC) {
p_audio_config->chan_medium[to_chan] != MEDIUM_NETTNC &&
p_audio_config->chan_medium[to_chan] != MEDIUM_SERTNC) {
text_color_set(DW_COLOR_ERROR);
dw_printf ("Config file, line %d: TO-channel %d is not valid.\n",
line, to_chan);
Expand Down Expand Up @@ -3111,7 +3177,8 @@ void config_init (char *fname, struct audio_s *p_audio_config,
}

if (p_audio_config->chan_medium[from_chan] != MEDIUM_RADIO &&
p_audio_config->chan_medium[from_chan] != MEDIUM_NETTNC) {
p_audio_config->chan_medium[from_chan] != MEDIUM_NETTNC &&
p_audio_config->chan_medium[from_chan] != MEDIUM_SERTNC) {
text_color_set(DW_COLOR_ERROR);
dw_printf ("Config file, line %d: FROM-channel %d is not valid.\n",
line, from_chan);
Expand Down Expand Up @@ -3149,7 +3216,8 @@ void config_init (char *fname, struct audio_s *p_audio_config,
continue;
}
if (p_audio_config->chan_medium[to_chan] != MEDIUM_RADIO &&
p_audio_config->chan_medium[to_chan] != MEDIUM_NETTNC) {
p_audio_config->chan_medium[to_chan] != MEDIUM_NETTNC &&
p_audio_config->chan_medium[to_chan] != MEDIUM_SERTNC) {
text_color_set(DW_COLOR_ERROR);
dw_printf ("Config file, line %d: TO-channel %d is not valid.\n",
line, to_chan);
Expand Down Expand Up @@ -4429,7 +4497,8 @@ void config_init (char *fname, struct audio_s *p_audio_config,
x = -1;
}
else if (p_audio_config->chan_medium[x] != MEDIUM_RADIO &&
p_audio_config->chan_medium[x] != MEDIUM_NETTNC) {
p_audio_config->chan_medium[x] != MEDIUM_NETTNC &&
p_audio_config->chan_medium[x] != MEDIUM_SERTNC) {
text_color_set(DW_COLOR_ERROR);
dw_printf ("Config file, line %d: TTOBJ transmit channel %d is not valid.\n", line, x);
x = -1;
Expand Down Expand Up @@ -5784,7 +5853,9 @@ void config_init (char *fname, struct audio_s *p_audio_config,
/* When IGate is enabled, all radio channels must have a callsign associated. */

if (strlen(p_igate_config->t2_login) > 0 &&
(p_audio_config->chan_medium[i] == MEDIUM_RADIO || p_audio_config->chan_medium[i] == MEDIUM_NETTNC)) {
(p_audio_config->chan_medium[i] == MEDIUM_RADIO ||
p_audio_config->chan_medium[i] == MEDIUM_NETTNC ||
p_audio_config->chan_medium[i] == MEDIUM_SERTNC)) {

if (strcmp(p_audio_config->mycall[i], "NOCALL") == 0 || strcmp(p_audio_config->mycall[i], "N0CALL") == 0) {
text_color_set(DW_COLOR_ERROR);
Expand All @@ -5810,7 +5881,9 @@ void config_init (char *fname, struct audio_s *p_audio_config,

if (strlen(p_igate_config->t2_login) > 0) {
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_audio_config->chan_medium[j] == MEDIUM_RADIO ||
p_audio_config->chan_medium[j] == MEDIUM_NETTNC ||
p_audio_config->chan_medium[j] == MEDIUM_SERTNC) {
if (p_digi_config->filter_str[MAX_TOTAL_CHANS][j] == NULL) {
p_digi_config->filter_str[MAX_TOTAL_CHANS][j] = strdup("i/180");
}
Expand Down
3 changes: 2 additions & 1 deletion src/digipeater.c
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,8 @@ void digipeater (int from_chan, packet_t pp)

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)) {
save_audio_config_p->chan_medium[from_chan] != MEDIUM_NETTNC &&
save_audio_config_p->chan_medium[from_chan] != MEDIUM_SERTNC)) {
text_color_set(DW_COLOR_ERROR);
dw_printf ("APRS digipeater: Did not expect to receive on invalid channel %d.\n", from_chan);
}
Expand Down
21 changes: 14 additions & 7 deletions src/direwolf.c
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@
#include "dlq.h" // for fec_type_t definition.
#include "deviceid.h"
#include "nettnc.h"
#include "sertnc.h"


//static int idx_decoded = 0;
Expand Down Expand Up @@ -1018,11 +1019,12 @@ int main (int argc, char *argv[])
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.
* New in 1.8 - Allow a channel to be mapped to a network or serial 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);
sertnc_init (&audio_config);

/*
* Initialize the touch tone decoder & APRStt gateway.
Expand Down Expand Up @@ -1191,6 +1193,7 @@ int main (int argc, char *argv[])
* -1 for DTMF decoder.
* -2 for channel mapped to APRS-IS.
* -3 for channel mapped to network TNC.
* -4 for channel mapped to serial TNC.
* slice - Slicer which caught it.
* pp - Packet handle.
* alevel - Audio level, range of 0 - 100.
Expand Down Expand Up @@ -1221,7 +1224,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 >= -3 && subchan < MAX_SUBCHANS);
assert (subchan >= -4 && subchan < MAX_SUBCHANS);
assert (slice >= 0 && slice < MAX_SLICERS);
assert (pp != NULL); // 1.1J+

Expand Down Expand Up @@ -1342,7 +1345,7 @@ void app_process_rec_packet (int chan, int subchan, int slice, packet_t pp, alev
dw_printf ("Setting audio input level so most stations are around 50 will provide good dyanmic range.\n");
}
// FIXME: rather than checking for ichannel, how about checking medium==radio
else if (alevel.rec < 5 && chan != audio_config.igate_vchannel && subchan != -3) {
else if (alevel.rec < 5 && chan != audio_config.igate_vchannel && subchan != SUBCHAN_NETTNC && subchan != SUBCHAN_SERTNC) {

text_color_set(DW_COLOR_ERROR);
dw_printf ("Audio input level is too low. Increase so most stations are around 50.\n");
Expand All @@ -1367,15 +1370,19 @@ void app_process_rec_packet (int chan, int subchan, int slice, packet_t pp, alev
strlcpy (ts, "", sizeof(ts));
}

if (subchan == -1) { // dtmf
if (subchan == SUBCHAN_DTMF) {
text_color_set(DW_COLOR_REC);
dw_printf ("[%d.dtmf%s] ", chan, ts);
}
else if (subchan == -2) { // APRS-IS
else if (subchan == SUBCHAN_APRSIS) {
text_color_set(DW_COLOR_REC);
dw_printf ("[%d.is%s] ", chan, ts);
}
else if (subchan == -3) { // nettnc
else if (subchan == SUBCHAN_NETTNC) {
text_color_set(DW_COLOR_REC);
dw_printf ("[%d%s] ", chan, ts);
}
else if (subchan == SUBCHAN_SERTNC) {
text_color_set(DW_COLOR_REC);
dw_printf ("[%d%s] ", chan, ts);
}
Expand Down
6 changes: 5 additions & 1 deletion src/dlq.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,13 @@ typedef struct dlq_item_s {

int subchan; /* Winning "subchannel" when using multiple */
/* decoders on one channel. */
/* Special case, -1 means DTMF decoder. */
/* Maybe we should have a different type in this case? */

#define SUBCHAN_DTMF -1
#define SUBCHAN_APRSIS -2
#define SUBCHAN_NETTNC -3
#define SUBCHAN_SERTNC -4

int slice; /* Winning slicer. */

packet_t pp; /* Pointer to frame structure. */
Expand Down
Loading
Loading