mirror of https://github.com/wb2osz/direwolf.git
Full Duplex.
This commit is contained in:
parent
59d6708698
commit
f6c0049e40
|
@ -13,6 +13,8 @@ This is a snapshot of ongoing development towards version of 1.5. Some features
|
||||||
|
|
||||||
- PTT using GPIO pin of CM108/CM119 (e.g. DMK URI, RB-USB RIM)
|
- PTT using GPIO pin of CM108/CM119 (e.g. DMK URI, RB-USB RIM)
|
||||||
|
|
||||||
|
- Full Duplex operation. (Put "FULLDUP ON" in channel section of configuration file.)
|
||||||
|
|
||||||
|
|
||||||
### Bugs Fixed: ###
|
### Bugs Fixed: ###
|
||||||
|
|
||||||
|
|
7
audio.h
7
audio.h
|
@ -281,7 +281,10 @@ struct audio_s {
|
||||||
/* are done sending the data. This is to avoid */
|
/* are done sending the data. This is to avoid */
|
||||||
/* dropping PTT too soon and chopping off the end */
|
/* dropping PTT too soon and chopping off the end */
|
||||||
/* of the frame. Again 10 mS units. */
|
/* of the frame. Again 10 mS units. */
|
||||||
/* At this point, I'm thinking of 10 as the default. */
|
/* At this point, I'm thinking of 10 (= 100 mS) as the default */
|
||||||
|
/* because we're not quite sure when the soundcard audio stops. */
|
||||||
|
|
||||||
|
int fulldup; /* Full Duplex. */
|
||||||
|
|
||||||
} achan[MAX_CHANS];
|
} achan[MAX_CHANS];
|
||||||
|
|
||||||
|
@ -368,7 +371,7 @@ struct audio_s {
|
||||||
#define DEFAULT_PERSIST 63
|
#define DEFAULT_PERSIST 63
|
||||||
#define DEFAULT_TXDELAY 30
|
#define DEFAULT_TXDELAY 30
|
||||||
#define DEFAULT_TXTAIL 10
|
#define DEFAULT_TXTAIL 10
|
||||||
|
#define DEFAULT_FULLDUP 0
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Note that we have two versions of these in audio.c and audio_win.c.
|
* Note that we have two versions of these in audio.c and audio_win.c.
|
||||||
|
|
37
config.c
37
config.c
|
@ -794,6 +794,7 @@ void config_init (char *fname, struct audio_s *p_audio_config,
|
||||||
p_audio_config->achan[channel].persist = DEFAULT_PERSIST;
|
p_audio_config->achan[channel].persist = DEFAULT_PERSIST;
|
||||||
p_audio_config->achan[channel].txdelay = DEFAULT_TXDELAY;
|
p_audio_config->achan[channel].txdelay = DEFAULT_TXDELAY;
|
||||||
p_audio_config->achan[channel].txtail = DEFAULT_TXTAIL;
|
p_audio_config->achan[channel].txtail = DEFAULT_TXTAIL;
|
||||||
|
p_audio_config->achan[channel].fulldup = DEFAULT_FULLDUP;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* First channel should always be valid. */
|
/* First channel should always be valid. */
|
||||||
|
@ -1784,7 +1785,7 @@ void config_init (char *fname, struct audio_s *p_audio_config,
|
||||||
// Failure at this point is not an error.
|
// Failure at this point is not an error.
|
||||||
// See if config file sets it explicitly before complaining.
|
// See if config file sets it explicitly before complaining.
|
||||||
|
|
||||||
cm108_find_ptt (p_audio_config->adev[ACHAN2ADEV(channel)].adevice_out,
|
cm108_find_ptt (p_audio_config->adev[ACHAN2ADEV(channel)].adevice_out,
|
||||||
p_audio_config->achan[channel].octrl[ot].ptt_device,
|
p_audio_config->achan[channel].octrl[ot].ptt_device,
|
||||||
(int)sizeof(p_audio_config->achan[channel].octrl[ot].ptt_device));
|
(int)sizeof(p_audio_config->achan[channel].octrl[ot].ptt_device));
|
||||||
|
|
||||||
|
@ -1923,7 +1924,7 @@ void config_init (char *fname, struct audio_s *p_audio_config,
|
||||||
*
|
*
|
||||||
* TXINH - TX holdoff input
|
* TXINH - TX holdoff input
|
||||||
*
|
*
|
||||||
* xxx GPIO [-]gpio-num (only type supported yet)
|
* TXINH GPIO [-]gpio-num (only type supported so far)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
else if (strcasecmp(t, "TXINH") == 0) {
|
else if (strcasecmp(t, "TXINH") == 0) {
|
||||||
|
@ -1966,7 +1967,7 @@ void config_init (char *fname, struct audio_s *p_audio_config,
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* DWAIT - Extra delay for receiver squelch.
|
* DWAIT n - Extra delay for receiver squelch. n = 10 mS units.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
else if (strcasecmp(t, "DWAIT") == 0) {
|
else if (strcasecmp(t, "DWAIT") == 0) {
|
||||||
|
@ -1990,7 +1991,7 @@ void config_init (char *fname, struct audio_s *p_audio_config,
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* SLOTTIME - For non-digipeat transmit delay timing.
|
* SLOTTIME n - For non-digipeat transmit delay timing. n = 10 mS units.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
else if (strcasecmp(t, "SLOTTIME") == 0) {
|
else if (strcasecmp(t, "SLOTTIME") == 0) {
|
||||||
|
@ -2038,7 +2039,7 @@ void config_init (char *fname, struct audio_s *p_audio_config,
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* TXDELAY - For transmit delay timing.
|
* TXDELAY n - For transmit delay timing. n = 10 mS units.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
else if (strcasecmp(t, "TXDELAY") == 0) {
|
else if (strcasecmp(t, "TXDELAY") == 0) {
|
||||||
|
@ -2062,7 +2063,7 @@ void config_init (char *fname, struct audio_s *p_audio_config,
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* TXTAIL - For transmit timing.
|
* TXTAIL n - For transmit timing. n = 10 mS units.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
else if (strcasecmp(t, "TXTAIL") == 0) {
|
else if (strcasecmp(t, "TXTAIL") == 0) {
|
||||||
|
@ -2085,6 +2086,30 @@ void config_init (char *fname, struct audio_s *p_audio_config,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* FULLDUP {on|off} - Full Duplex
|
||||||
|
*/
|
||||||
|
else if (strcasecmp(t, "FULLDUP") == 0) {
|
||||||
|
|
||||||
|
t = split(NULL,0);
|
||||||
|
if (t == NULL) {
|
||||||
|
text_color_set(DW_COLOR_ERROR);
|
||||||
|
dw_printf ("Line %d: Missing parameter for FULLDUP command. Expecting ON or OFF.\n", line);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (strcasecmp(t, "ON") == 0) {
|
||||||
|
p_audio_config->achan[channel].fulldup = 1;
|
||||||
|
}
|
||||||
|
else if (strcasecmp(t, "OFF") == 0) {
|
||||||
|
p_audio_config->achan[channel].fulldup = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
p_audio_config->achan[channel].fulldup = 0;
|
||||||
|
text_color_set(DW_COLOR_ERROR);
|
||||||
|
dw_printf ("Line %d: Expected ON or OFF for FULLDUP.\n", line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* SPEECH script
|
* SPEECH script
|
||||||
*
|
*
|
||||||
|
|
Binary file not shown.
|
@ -58,7 +58,8 @@
|
||||||
* Spec says it is obsolete but Xastir
|
* Spec says it is obsolete but Xastir
|
||||||
* sends it and we respect it.
|
* sends it and we respect it.
|
||||||
*
|
*
|
||||||
* _5 FullDuplex Ignored.
|
* _5 FullDuplex Full Duplex. Transmit immediately without
|
||||||
|
* waiting for channel to be clear.
|
||||||
*
|
*
|
||||||
* _6 SetHardware TNC specific.
|
* _6 SetHardware TNC specific.
|
||||||
*
|
*
|
||||||
|
@ -644,7 +645,8 @@ void kiss_process_msg (unsigned char *kiss_msg, int kiss_len, int debug, int cli
|
||||||
case KISS_CMD_FULLDUPLEX: /* 5 = FullDuplex */
|
case KISS_CMD_FULLDUPLEX: /* 5 = FullDuplex */
|
||||||
|
|
||||||
text_color_set(DW_COLOR_INFO);
|
text_color_set(DW_COLOR_INFO);
|
||||||
dw_printf ("KISS protocol set FullDuplex = %d, port %d - Ignored\n", kiss_msg[1], port);
|
dw_printf ("KISS protocol set FullDuplex = %d, port %d\n", kiss_msg[1], port);
|
||||||
|
xmit_set_fulldup (port, kiss_msg[1]);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case KISS_CMD_SET_HARDWARE: /* 6 = TNC specific */
|
case KISS_CMD_SET_HARDWARE: /* 6 = TNC specific */
|
||||||
|
|
38
xmit.c
38
xmit.c
|
@ -2,7 +2,7 @@
|
||||||
//
|
//
|
||||||
// This file is part of Dire Wolf, an amateur radio packet TNC.
|
// This file is part of Dire Wolf, an amateur radio packet TNC.
|
||||||
//
|
//
|
||||||
// Copyright (C) 2011, 2013, 2014, 2015, 2016 John Langner, WB2OSZ
|
// Copyright (C) 2011, 2013, 2014, 2015, 2016, 2017 John Langner, WB2OSZ
|
||||||
//
|
//
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// 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
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
@ -101,6 +101,8 @@ static int xmit_txtail[MAX_CHANS]; /* Amount of time to keep transmitting after
|
||||||
/* dropping PTT too soon and chopping off the end */
|
/* dropping PTT too soon and chopping off the end */
|
||||||
/* of the frame. Again 10 mS units. */
|
/* of the frame. Again 10 mS units. */
|
||||||
|
|
||||||
|
static int xmit_fulldup[MAX_CHANS]; /* Full duplex if non-zero. */
|
||||||
|
|
||||||
static int xmit_bits_per_sec[MAX_CHANS]; /* Data transmission rate. */
|
static int xmit_bits_per_sec[MAX_CHANS]; /* Data transmission rate. */
|
||||||
/* Often called baud rate which is equivalent in */
|
/* Often called baud rate which is equivalent in */
|
||||||
/* this case but could be different with other */
|
/* this case but could be different with other */
|
||||||
|
@ -137,7 +139,7 @@ static dw_mutex_t audio_out_dev_mutex[MAX_ADEVS];
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static int wait_for_clear_channel (int channel, int slotttime, int persist);
|
static int wait_for_clear_channel (int channel, int slotttime, int persist, int fulldup);
|
||||||
static void xmit_ax25_frames (int c, int p, packet_t pp, int max_bundle);
|
static void xmit_ax25_frames (int c, int p, packet_t pp, int max_bundle);
|
||||||
static int send_one_frame (int c, int p, packet_t pp);
|
static int send_one_frame (int c, int p, packet_t pp);
|
||||||
static void xmit_speech (int c, packet_t pp);
|
static void xmit_speech (int c, packet_t pp);
|
||||||
|
@ -218,6 +220,7 @@ void xmit_init (struct audio_s *p_modem, int debug_xmit_packet)
|
||||||
xmit_persist[j] = p_modem->achan[j].persist;
|
xmit_persist[j] = p_modem->achan[j].persist;
|
||||||
xmit_txdelay[j] = p_modem->achan[j].txdelay;
|
xmit_txdelay[j] = p_modem->achan[j].txdelay;
|
||||||
xmit_txtail[j] = p_modem->achan[j].txtail;
|
xmit_txtail[j] = p_modem->achan[j].txtail;
|
||||||
|
xmit_fulldup[j] = p_modem->achan[j].fulldup;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
|
@ -306,6 +309,7 @@ void xmit_init (struct audio_s *p_modem, int debug_xmit_packet)
|
||||||
* xmit_set_persist
|
* xmit_set_persist
|
||||||
* xmit_set_slottime
|
* xmit_set_slottime
|
||||||
* xmit_set_txtail
|
* xmit_set_txtail
|
||||||
|
* xmit_set_fulldup
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* Purpose: The KISS protocol, and maybe others, can specify
|
* Purpose: The KISS protocol, and maybe others, can specify
|
||||||
|
@ -355,6 +359,13 @@ void xmit_set_txtail (int channel, int value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void xmit_set_fulldup (int channel, int value)
|
||||||
|
{
|
||||||
|
if (channel >= 0 && channel < MAX_CHANS) {
|
||||||
|
xmit_fulldup[channel] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------------
|
/*-------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
|
@ -490,7 +501,7 @@ static void * xmit_thread (void *arg)
|
||||||
* If there is something in the high priority queue, begin transmitting immediately.
|
* If there is something in the high priority queue, begin transmitting immediately.
|
||||||
* Otherwise, wait a random amount of time, in hopes of minimizing collisions.
|
* Otherwise, wait a random amount of time, in hopes of minimizing collisions.
|
||||||
*/
|
*/
|
||||||
ok = wait_for_clear_channel (chan, xmit_slottime[chan], xmit_persist[chan]);
|
ok = wait_for_clear_channel (chan, xmit_slottime[chan], xmit_persist[chan], xmit_fulldup[chan]);
|
||||||
|
|
||||||
prio = TQ_PRIO_1_LO;
|
prio = TQ_PRIO_1_LO;
|
||||||
pp = tq_remove (chan, TQ_PRIO_0_HI);
|
pp = tq_remove (chan, TQ_PRIO_0_HI);
|
||||||
|
@ -670,6 +681,8 @@ static void * xmit_thread (void *arg)
|
||||||
* Once we have control of the channel, we might as well keep going.
|
* Once we have control of the channel, we might as well keep going.
|
||||||
* [High] Priority frames will always go to head of the line,
|
* [High] Priority frames will always go to head of the line,
|
||||||
*
|
*
|
||||||
|
* Version 1.5: Add full duplex option.
|
||||||
|
*
|
||||||
*--------------------------------------------------------------------*/
|
*--------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
||||||
|
@ -1231,12 +1244,19 @@ static void xmit_dtmf (int c, packet_t pp, int speed)
|
||||||
* slottime - Amount of time to wait for each iteration
|
* slottime - Amount of time to wait for each iteration
|
||||||
* of the waiting algorithm. 10 mSec units.
|
* of the waiting algorithm. 10 mSec units.
|
||||||
*
|
*
|
||||||
* persist - Probability of transmitting
|
* persist - Probability of transmitting.
|
||||||
|
*
|
||||||
|
* fulldup - Full duplex. Just start sending immediately.
|
||||||
*
|
*
|
||||||
* Returns: 1 for OK. 0 for timeout.
|
* Returns: 1 for OK. 0 for timeout.
|
||||||
*
|
*
|
||||||
* Description: New in version 1.2: also obtain a lock on audio out device.
|
* Description: New in version 1.2: also obtain a lock on audio out device.
|
||||||
*
|
*
|
||||||
|
* New in version 1.5: full duplex.
|
||||||
|
* Just start transmitting rather than waiting for clear channel.
|
||||||
|
* This would only be appropriate when transmit and receive are
|
||||||
|
* using different radio freqencies. e.g. VHF up, UHF down satellite.
|
||||||
|
*
|
||||||
* Transmit delay algorithm:
|
* Transmit delay algorithm:
|
||||||
*
|
*
|
||||||
* Wait for channel to be clear.
|
* Wait for channel to be clear.
|
||||||
|
@ -1271,10 +1291,17 @@ static void xmit_dtmf (int c, packet_t pp, int speed)
|
||||||
#define WAIT_TIMEOUT_MS (60 * 1000)
|
#define WAIT_TIMEOUT_MS (60 * 1000)
|
||||||
#define WAIT_CHECK_EVERY_MS 10
|
#define WAIT_CHECK_EVERY_MS 10
|
||||||
|
|
||||||
static int wait_for_clear_channel (int chan, int slottime, int persist)
|
static int wait_for_clear_channel (int chan, int slottime, int persist, int fulldup)
|
||||||
{
|
{
|
||||||
int n = 0;
|
int n = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* For dull duplex we skip the channel busy check and random wait.
|
||||||
|
* We still need to wait if operating in stereo and the other audio
|
||||||
|
* half is busy.
|
||||||
|
*/
|
||||||
|
if ( ! fulldup) {
|
||||||
|
|
||||||
start_over_again:
|
start_over_again:
|
||||||
|
|
||||||
while (hdlc_rec_data_detect_any(chan)) {
|
while (hdlc_rec_data_detect_any(chan)) {
|
||||||
|
@ -1318,6 +1345,7 @@ start_over_again:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is to prevent two channels from transmitting at the same time
|
* This is to prevent two channels from transmitting at the same time
|
||||||
|
|
2
xmit.h
2
xmit.h
|
@ -16,6 +16,8 @@ extern void xmit_set_slottime (int channel, int value);
|
||||||
|
|
||||||
extern void xmit_set_txtail (int channel, int value);
|
extern void xmit_set_txtail (int channel, int value);
|
||||||
|
|
||||||
|
extern void xmit_set_fulldup (int channel, int value);
|
||||||
|
|
||||||
|
|
||||||
extern int xmit_speak_it (char *script, int c, char *msg);
|
extern int xmit_speak_it (char *script, int c, char *msg);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue