From 323b56a98d622d601a9b3de755b4e1a1e681aa6d Mon Sep 17 00:00:00 2001 From: c vw Date: Sun, 16 Jan 2022 12:54:37 +0100 Subject: [PATCH] Protect sending of ozy buffers with a MUTEX, since this is needed for TCP and USB traffic. --- old_protocol.c | 134 ++++++++++++++++++++++++++----------------------- 1 file changed, 70 insertions(+), 64 deletions(-) diff --git a/old_protocol.c b/old_protocol.c index 2e7d22c..fb5327d 100644 --- a/old_protocol.c +++ b/old_protocol.c @@ -139,7 +139,6 @@ static int running; static long ep4_sequence; static uint32_t last_seq_num=-0xffffffff; -static int suppress_ozy_packet = 0; static int tx_fifo_flag = 0; static int current_rx=0; @@ -210,6 +209,21 @@ static unsigned char usb_buffer_block = 0; static GMutex dump_mutex; +// +// To avoid race conditions, we need a mutex covering the next three functions +// that are called both by the RX and TX thread, and are filling and sending the +// output buffer. +// +static pthread_mutex_t send_audio_mutex = PTHREAD_MUTEX_INITIALIZER; + +// +// This mutex "protects" ozy_send_buffer. This is necessary only for +// TCP and USB-OZY connections. +// +static pthread_mutex_t send_ozy_mutex = PTHREAD_MUTEX_INITIALIZER; + + + // // Ring buffer for outgoing samples. // Samples going to the radio are produces in big chunks. @@ -268,6 +282,11 @@ void dump_buffer(unsigned char *buffer,int length,const char *who) { } void old_protocol_stop() { + // + // Mutex is needed since in the TCP case, sending TX IQ packets + // must not occur while the "stop" packet is sent. + // + pthread_mutex_lock(&send_ozy_mutex); #ifdef USBOZY if(device!=DEVICE_OZY) { #endif @@ -276,15 +295,14 @@ void old_protocol_stop() { #ifdef USBOZY } #endif + pthread_mutex_unlock(&send_ozy_mutex); } void old_protocol_run() { - // - // Several things done in metis_restart are also needed for - // USBOZY - // g_print("%s\n",__FUNCTION__); + pthread_mutex_lock(&send_ozy_mutex); metis_restart(); + pthread_mutex_unlock(&send_ozy_mutex); } void old_protocol_set_mic_sample_rate(int rate) { @@ -294,6 +312,7 @@ void old_protocol_set_mic_sample_rate(int rate) { void old_protocol_init(int rx,int pixels,int rate) { int i; g_print("old_protocol_init: num_hpsdr_receivers=%d\n",how_many_receivers()); + pthread_mutex_lock(&send_ozy_mutex); old_protocol_set_mic_sample_rate(rate); @@ -339,6 +358,7 @@ void old_protocol_init(int rx,int pixels,int rate) { } metis_restart(); + pthread_mutex_unlock(&send_ozy_mutex); } @@ -533,8 +553,6 @@ static gpointer receive_thread(gpointer arg) { g_print( "old_protocol: receive_thread\n"); running=1; - //metis_restart(); - length=sizeof(addr); while(running) { @@ -1195,38 +1213,43 @@ static void process_ozy_input_buffer(unsigned char *buffer) { // ship out two buffers with 2*63 samples // the k-loop could be done with 1-2 memcpy // - for (int j=0; j<2; j++) { - unsigned char *p=output_buffer+8; - for (int k=0; k<63; k++) { - *p++ = TXRINGBUF[txring_outptr++]; - *p++ = TXRINGBUF[txring_outptr++]; - *p++ = TXRINGBUF[txring_outptr++]; - *p++ = TXRINGBUF[txring_outptr++]; - *p++ = TXRINGBUF[txring_outptr++]; - *p++ = TXRINGBUF[txring_outptr++]; - *p++ = TXRINGBUF[txring_outptr++]; - *p++ = TXRINGBUF[txring_outptr++]; - if (txring_outptr >= TXRINGBUFLEN) txring_outptr=0; + if (pthread_mutex_trylock(&send_ozy_mutex)) { + // + // This can only happen if the GUI thread initiates + // a protocol stop/start sequence, as it does e.g. + // when changing the number of receivers, changing + // the sample rate, en/dis-abling PURESIGNAL or + // DIVERSITY, or executing the RESTART button. + // In these cases, the TX ring buffer is reset anywas + // so we do not have to do anything here. + // + } else { + for (int j=0; j<2; j++) { + unsigned char *p=output_buffer+8; + for (int k=0; k<63; k++) { + *p++ = TXRINGBUF[txring_outptr++]; + *p++ = TXRINGBUF[txring_outptr++]; + *p++ = TXRINGBUF[txring_outptr++]; + *p++ = TXRINGBUF[txring_outptr++]; + *p++ = TXRINGBUF[txring_outptr++]; + *p++ = TXRINGBUF[txring_outptr++]; + *p++ = TXRINGBUF[txring_outptr++]; + *p++ = TXRINGBUF[txring_outptr++]; + if (txring_outptr >= TXRINGBUFLEN) txring_outptr=0; + } + ozy_send_buffer(); } - ozy_send_buffer(); - } - micsamplecount=0; + micsamplecount=0; + pthread_mutex_unlock(&send_ozy_mutex); + } } } } } -// -// To avoid race conditions, we need a mutex covering the next three functions -// that are called both by the RX and TX thread, and are filling and sending the -// output buffer. -// - -static pthread_mutex_t send_buffer_mutex = PTHREAD_MUTEX_INITIALIZER; - void old_protocol_audio_samples(RECEIVER *rx,short left_audio_sample,short right_audio_sample) { if(!isTransmitting()) { - pthread_mutex_lock(&send_buffer_mutex); + pthread_mutex_lock(&send_audio_mutex); if (txring_flag) { // // First time we arrive here after a TX->RX transition: @@ -1259,7 +1282,7 @@ void old_protocol_audio_samples(RECEIVER *rx,short left_audio_sample,short right TXRINGBUF[txring_inptr++]=0; TXRINGBUF[txring_inptr++]=0; if (txring_inptr >= TXRINGBUFLEN) txring_inptr=0; - pthread_mutex_unlock(&send_buffer_mutex); + pthread_mutex_unlock(&send_audio_mutex); } } @@ -1272,7 +1295,7 @@ void old_protocol_audio_samples(RECEIVER *rx,short left_audio_sample,short right // void old_protocol_iq_samples_with_sidetone(int isample, int qsample, int side) { if(isTransmitting()) { - pthread_mutex_lock(&send_buffer_mutex); + pthread_mutex_lock(&send_audio_mutex); if (!txring_flag) { // // First time we arrive here after a RX->TX transition: @@ -1298,13 +1321,13 @@ void old_protocol_iq_samples_with_sidetone(int isample, int qsample, int side) { TXRINGBUF[txring_inptr++]=qsample >> 8; TXRINGBUF[txring_inptr++]=qsample; if (txring_inptr >= TXRINGBUFLEN) txring_inptr=0; - pthread_mutex_unlock(&send_buffer_mutex); + pthread_mutex_unlock(&send_audio_mutex); } } void old_protocol_iq_samples(int isample,int qsample) { if(isTransmitting()) { - pthread_mutex_lock(&send_buffer_mutex); + pthread_mutex_lock(&send_audio_mutex); if (!txring_flag) { // // First time we arrive here after a RX->TX transition: @@ -1323,7 +1346,7 @@ void old_protocol_iq_samples(int isample,int qsample) { TXRINGBUF[txring_inptr++]=qsample >> 8; TXRINGBUF[txring_inptr++]=qsample; if (txring_inptr >= TXRINGBUFLEN) txring_inptr=0; - pthread_mutex_unlock(&send_buffer_mutex); + pthread_mutex_unlock(&send_audio_mutex); } } @@ -2065,17 +2088,6 @@ static void ozyusb_write(unsigned char* buffer,int length) break; } */ - // - // DL1YCF: - // Although the METIS offset is not used for OZY, we have to maintain it - // since it triggers the "alternating" sending of C0=0 and C0!=0 - // C+C packets in ozy_send_buffer(). - // - if (metis_offset == 8) { - metis_offset = 520; - } else { - metis_offset = 8; - } } #endif @@ -2099,19 +2111,9 @@ static int metis_write(unsigned char ep,unsigned char* buffer,int length) { metis_buffer[6]=(send_sequence>>8)&0xFF; metis_buffer[7]=(send_sequence)&0xFF; - // - // When using UDP, the buffer will ALWAYS be sent. However, when using TCP, - // we must be able to suppress sending buffers HERE asynchronously - // when we want to sent a METIS start or stop packet. This is so because TCP - // is a byte stream, and data from two sources might end up interleaved - // In order not to confuse the SDR, we increase the sequence number only - // for packets actually sent. - // - if (!suppress_ozy_packet) { - // send the buffer - send_sequence++; - metis_send_buffer(&metis_buffer[0],1032); - } + send_sequence++; + metis_send_buffer(&metis_buffer[0],1032); + metis_offset=8; } @@ -2161,14 +2163,15 @@ static void metis_restart() { for (i=0; i<8; i++) { ozy_send_buffer(); } - - usleep(250000); + usleep(100000); // start the data flowing + // No mutex here, since metis_restart() is mutex protected #ifdef USBOZY if(device!=DEVICE_OZY) { #endif metis_start_stop(1); + usleep(100000); #ifdef USBOZY } #endif @@ -2180,6 +2183,11 @@ static void metis_start_stop(int command) { unsigned char buffer[1032]; g_print("%s: %d\n",__FUNCTION__,command); + // + // Clear TX IQ ring buffer + // + txring_inptr = 0; + txring_outptr = 0; #ifdef USBOZY if(device!=DEVICE_OZY) { @@ -2202,7 +2210,6 @@ static void metis_start_stop(int command) { // Stop the sending of TX/audio packets (1032-byte-length) and wait a while // Then, send the start/stop buffer with a length of 1032 // - suppress_ozy_packet=1; usleep(100000); for(i=4;i<1032;i++) { buffer[i]=0x00; @@ -2213,7 +2220,6 @@ static void metis_start_stop(int command) { // This prevents mangling of data from TX/audio and Start/Stop packets. // usleep(100000); - suppress_ozy_packet=0; } if (command == 0 && tcp_socket >= 0) { // We just have sent a METIS stop in TCP -- 2.45.2