diff --git a/CHANGES.md b/CHANGES.md index dbaf01d..0ad322d 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -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) +- Full Duplex operation. (Put "FULLDUP ON" in channel section of configuration file.) + ### Bugs Fixed: ### diff --git a/audio.h b/audio.h index 13fb22c..322de61 100644 --- a/audio.h +++ b/audio.h @@ -281,7 +281,10 @@ struct audio_s { /* 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. */ - /* 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]; @@ -368,7 +371,7 @@ struct audio_s { #define DEFAULT_PERSIST 63 #define DEFAULT_TXDELAY 30 #define DEFAULT_TXTAIL 10 - +#define DEFAULT_FULLDUP 0 /* * Note that we have two versions of these in audio.c and audio_win.c. diff --git a/config.c b/config.c index ed8a20e..8c74c0d 100644 --- a/config.c +++ b/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].txdelay = DEFAULT_TXDELAY; p_audio_config->achan[channel].txtail = DEFAULT_TXTAIL; + p_audio_config->achan[channel].fulldup = DEFAULT_FULLDUP; } /* First channel should always be valid. */ @@ -1778,13 +1779,13 @@ void config_init (char *fname, struct audio_s *p_audio_config, // User can override for special cases. p_audio_config->achan[channel].octrl[ot].ptt_invert = 0; // High for transmit. strcpy (p_audio_config->achan[channel].octrl[ot].ptt_device, ""); - + // Try to find PTT device for audio output device. // Simplifiying assumption is that we have one radio per USB Audio Adapter. // Failure at this point is not an error. // 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, (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 * - * xxx GPIO [-]gpio-num (only type supported yet) + * TXINH GPIO [-]gpio-num (only type supported so far) */ 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) { @@ -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) { @@ -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) { @@ -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) { @@ -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 * diff --git a/doc/User-Guide.pdf b/doc/User-Guide.pdf index f2418dc..867fff6 100644 Binary files a/doc/User-Guide.pdf and b/doc/User-Guide.pdf differ diff --git a/kiss_frame.c b/kiss_frame.c index 1db115c..cb138dd 100644 --- a/kiss_frame.c +++ b/kiss_frame.c @@ -58,7 +58,8 @@ * Spec says it is obsolete but Xastir * 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. * @@ -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 */ 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; case KISS_CMD_SET_HARDWARE: /* 6 = TNC specific */ diff --git a/xmit.c b/xmit.c index ee82ee1..2999dcf 100644 --- a/xmit.c +++ b/xmit.c @@ -2,7 +2,7 @@ // // 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 // 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 */ /* 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. */ /* Often called baud rate which is equivalent in */ /* 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 int send_one_frame (int c, int p, 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_txdelay[j] = p_modem->achan[j].txdelay; xmit_txtail[j] = p_modem->achan[j].txtail; + xmit_fulldup[j] = p_modem->achan[j].fulldup; } #if DEBUG @@ -306,6 +309,7 @@ void xmit_init (struct audio_s *p_modem, int debug_xmit_packet) * xmit_set_persist * xmit_set_slottime * xmit_set_txtail + * xmit_set_fulldup * * * 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. * 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; 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. * [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 * 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. * * 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: * * 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_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; +/* + * 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: while (hdlc_rec_data_detect_any(chan)) { @@ -1318,6 +1345,7 @@ start_over_again: break; } } + } /* * This is to prevent two channels from transmitting at the same time diff --git a/xmit.h b/xmit.h index b444f1e..248037d 100644 --- a/xmit.h +++ b/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_fulldup (int channel, int value); + extern int xmit_speak_it (char *script, int c, char *msg);