Skip to content

Commit

Permalink
Use mutex for writing audio buffer data
Browse files Browse the repository at this point in the history
  • Loading branch information
dl1ycf committed Nov 24, 2021
1 parent fa02786 commit 2cd52ca
Show file tree
Hide file tree
Showing 2 changed files with 119 additions and 56 deletions.
75 changes: 46 additions & 29 deletions new_protocol.c
Original file line number Diff line number Diff line change
Expand Up @@ -210,16 +210,19 @@ static unsigned char high_priority_buffer_to_radio[1444];
static unsigned char transmit_specific_buffer[60];
static unsigned char receive_specific_buffer[1444];

// DL1YCF
//
// new_protocol_receive_specific and friends are not thread-safe, but called
// periodically from timer thread and asynchronously from everywhere else
// therefore we need to implement a critical section for each of these functions.
// It seems that this is not necessary for the audio and TX-IQ buffers.
// The audio buffer needs a mutex since both RX and TX threads may write to
// this one (CW side tone).
//

static pthread_mutex_t rx_spec_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t tx_spec_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t hi_prio_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t general_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t audio_buffer_mutex = PTHREAD_MUTEX_INITIALIZER;

static int local_ptt=0;

Expand Down Expand Up @@ -384,11 +387,18 @@ void new_protocol_init(int pixels) {
int rc;
spectrumWIDTH=pixels;

//
// This is the hard (compile-time) limit on the number of DDCs
//
if (MAX_DDC > 7) {
g_print("%s: MAX_DDC exceeds allowed range\n", __FUNCTION__);
exit(-1);
}
g_print("new_protocol_init: MIC_SAMPLES=%d\n",MIC_SAMPLES);

memset(rxcase , 0, MAX_DDC*sizeof(int));
memset(rxid , 0, MAX_DDC*sizeof(int));
memset(ddc_sequence, 0, MAX_DDC*sizeof(long));
memset(rxcase , 0, sizeof(rxcase));
memset(rxid , 0, sizeof(rxid));
memset(ddc_sequence, 0, sizeof(ddc_sequence));
update_action_table();

#ifdef INCLUDED
Expand Down Expand Up @@ -602,7 +612,7 @@ static void new_protocol_general() {
general_buffer[37]=0x08; // phase word (not frequency)
general_buffer[38]=0x01; // enable hardware timer

if(band->disablePA) {
if(!pa_enabled || band->disablePA) {
general_buffer[58]=0x00;
} else {
general_buffer[58]=0x01; // enable PA
Expand Down Expand Up @@ -1394,9 +1404,9 @@ void new_protocol_restart() {
micsamples_sequence=0;
audiosequence=0;
tx_iq_sequence=0;
memset(rxcase , 0, MAX_DDC*sizeof(int));
memset(rxid , 0, MAX_DDC*sizeof(int));
memset(ddc_sequence, 0, MAX_DDC*sizeof(long));
memset(rxcase , 0, sizeof(rxcase));
memset(rxid , 0, sizeof(rxid));
memset(ddc_sequence, 0, sizeof(ddc_sequence));
update_action_table();
// running is set to 1 at the top of new_protocol_thread,
// but this may lead to race conditions. So out of paranoia,
Expand Down Expand Up @@ -1874,33 +1884,37 @@ static void process_mic_data(int bytes) {
void new_protocol_cw_audio_samples(short left_audio_sample,short right_audio_sample) {
int rc;
int txmode=get_tx_mode();
//
// Only process samples if transmitting in CW

if (isTransmitting() && (txmode==modeCWU || txmode==modeCWL)) {
//
// Only process samples if transmitting in CW
//

// insert the samples
audiobuffer[audioindex++]=left_audio_sample>>8;
audiobuffer[audioindex++]=left_audio_sample;
audiobuffer[audioindex++]=right_audio_sample>>8;
audiobuffer[audioindex++]=right_audio_sample;
pthread_mutex_lock(&audio_buffer_mutex);
// insert the samples
audiobuffer[audioindex++]=left_audio_sample>>8;
audiobuffer[audioindex++]=left_audio_sample;
audiobuffer[audioindex++]=right_audio_sample>>8;
audiobuffer[audioindex++]=right_audio_sample;

if(audioindex>=sizeof(audiobuffer)) {
if(audioindex>=sizeof(audiobuffer)) {

// insert the sequence
audiobuffer[0]=audiosequence>>24;
audiobuffer[1]=audiosequence>>16;
audiobuffer[2]=audiosequence>>8;
audiobuffer[3]=audiosequence;
// insert the sequence
audiobuffer[0]=audiosequence>>24;
audiobuffer[1]=audiosequence>>16;
audiobuffer[2]=audiosequence>>8;
audiobuffer[3]=audiosequence;

// send the buffer
// send the buffer

rc=sendto(data_socket,audiobuffer,sizeof(audiobuffer),0,(struct sockaddr*)&audio_addr,audio_addr_length);
if(rc!=sizeof(audiobuffer)) {
g_print("sendto socket failed for %ld bytes of audio: %d\n",(long)sizeof(audiobuffer),rc);
rc=sendto(data_socket,audiobuffer,sizeof(audiobuffer),0,(struct sockaddr*)&audio_addr,audio_addr_length);
if(rc!=sizeof(audiobuffer)) {
g_print("sendto socket failed for %ld bytes of audio: %d\n",(long)sizeof(audiobuffer),rc);
}
audioindex=4;
audiosequence++;
}
audioindex=4;
audiosequence++;
}
pthread_mutex_unlock(&audio_buffer_mutex);
}
}

Expand All @@ -1910,8 +1924,10 @@ void new_protocol_audio_samples(RECEIVER *rx,short left_audio_sample,short right
int txmode=get_tx_mode();
//
// Only process samples if NOT transmitting in CW
//
if (isTransmitting() && (txmode==modeCWU || txmode==modeCWL)) return;

pthread_mutex_lock(&audio_buffer_mutex);
// insert the samples
audiobuffer[audioindex++]=left_audio_sample>>8;
audiobuffer[audioindex++]=left_audio_sample;
Expand All @@ -1935,6 +1951,7 @@ void new_protocol_audio_samples(RECEIVER *rx,short left_audio_sample,short right
audioindex=4;
audiosequence++;
}
pthread_mutex_unlock(&audio_buffer_mutex);
}

void new_protocol_flush_iq_samples() {
Expand Down
100 changes: 73 additions & 27 deletions old_protocol.c
Original file line number Diff line number Diff line change
Expand Up @@ -1323,12 +1323,42 @@ static void process_ozy_input_buffer(unsigned char *buffer) {
}
}

//
// 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.
//
// In 99% if the cases, the check on isTransmitting() controls that only one
// of the functions becomes active, but at the moment of a RX/TX transition
// this may fail.
//
// So "blocking" can only occur very rarely, such that the lock/unlock
// should cost only few CPU cycles.
//

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()) {
output_buffer[output_buffer_index++]=left_audio_sample>>8;
output_buffer[output_buffer_index++]=left_audio_sample;
output_buffer[output_buffer_index++]=right_audio_sample>>8;
output_buffer[output_buffer_index++]=right_audio_sample;
pthread_mutex_lock(&send_buffer_mutex);
//
// The HL2 makes no use of audio samples, but instead
// uses them to write to extended addrs which we do not
// want to do un-intentionally, therefore send zeros
// We could also stop this data stream during TX
// completely
//
if (device == DEVICE_HERMES_LITE2) {
output_buffer[output_buffer_index++]=0;
output_buffer[output_buffer_index++]=0;
output_buffer[output_buffer_index++]=0;
output_buffer[output_buffer_index++]=0;
} else {
output_buffer[output_buffer_index++]=left_audio_sample>>8;
output_buffer[output_buffer_index++]=left_audio_sample;
output_buffer[output_buffer_index++]=right_audio_sample>>8;
output_buffer[output_buffer_index++]=right_audio_sample;
}
output_buffer[output_buffer_index++]=0;
output_buffer[output_buffer_index++]=0;
output_buffer[output_buffer_index++]=0;
Expand All @@ -1337,6 +1367,7 @@ void old_protocol_audio_samples(RECEIVER *rx,short left_audio_sample,short right
ozy_send_buffer();
output_buffer_index=8;
}
pthread_mutex_unlock(&send_buffer_mutex);
}
}

Expand All @@ -1349,10 +1380,18 @@ 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()) {
output_buffer[output_buffer_index++]=side >> 8;
output_buffer[output_buffer_index++]=side;
output_buffer[output_buffer_index++]=side >> 8;
output_buffer[output_buffer_index++]=side;
pthread_mutex_lock(&send_buffer_mutex);
if (device == DEVICE_HERMES_LITE2) {
output_buffer[output_buffer_index++]=0;
output_buffer[output_buffer_index++]=0;
output_buffer[output_buffer_index++]=0;
output_buffer[output_buffer_index++]=0;
} else {
output_buffer[output_buffer_index++]=side >> 8;
output_buffer[output_buffer_index++]=side;
output_buffer[output_buffer_index++]=side >> 8;
output_buffer[output_buffer_index++]=side;
}
output_buffer[output_buffer_index++]=isample>>8;
output_buffer[output_buffer_index++]=isample;
output_buffer[output_buffer_index++]=qsample>>8;
Expand All @@ -1361,11 +1400,13 @@ void old_protocol_iq_samples_with_sidetone(int isample, int qsample, int side) {
ozy_send_buffer();
output_buffer_index=8;
}
pthread_mutex_unlock(&send_buffer_mutex);
}
}

void old_protocol_iq_samples(int isample,int qsample) {
if(isTransmitting()) {
pthread_mutex_lock(&send_buffer_mutex);
output_buffer[output_buffer_index++]=0;
output_buffer[output_buffer_index++]=0;
output_buffer[output_buffer_index++]=0;
Expand All @@ -1378,6 +1419,7 @@ void old_protocol_iq_samples(int isample,int qsample) {
ozy_send_buffer();
output_buffer_index=8;
}
pthread_mutex_unlock(&send_buffer_mutex);
}
}

Expand All @@ -1387,7 +1429,8 @@ void ozy_send_buffer() {
int txmode=get_tx_mode();
int txvfo=get_tx_vfo();
int i;
BAND *band;
BAND *rxband=band_get_band(vfo[VFO_A].band);
BAND *txband=band_get_band(vfo[txvfo].band);
int num_hpsdr_receivers=how_many_receivers();
int rx1channel = first_receiver_channel();
int rx2channel = second_receiver_channel();
Expand Down Expand Up @@ -1453,10 +1496,8 @@ void ozy_send_buffer() {
if(classE) {
output_buffer[C2]|=0x01;
}
band=band_get_band(vfo[VFO_A].band);
if(isTransmitting()) {
band=band_get_band(vfo[txvfo].band);
output_buffer[C2]|=band->OCtx<<1;
output_buffer[C2]|=txband->OCtx<<1;
if(tune) {
if(OCmemory_tune_time!=0) {
struct timeval te;
Expand All @@ -1470,7 +1511,7 @@ void ozy_send_buffer() {
}
}
} else {
output_buffer[C2]|=band->OCrx<<1;
output_buffer[C2]|=rxband->OCrx<<1;
}

output_buffer[C3] = (receiver[0]->alex_attenuation) & 0x03; // do not set higher bits
Expand Down Expand Up @@ -1639,11 +1680,6 @@ void ozy_send_buffer() {
break;
case 3:
{
//BAND *band=band_get_current_band();
band=band_get_band(vfo[VFO_A].band);
if(isTransmitting()) {
band=band_get_band(vfo[txvfo].band);
}
int power=0;
static int last_power=0;
//
Expand All @@ -1669,7 +1705,7 @@ static int last_power=0;
// last_power=power;
//}

//fprintf(stderr,"%s: band=%s disablePA=%d\n",__FUNCTION__,band->title,band->disablePA);
//fprintf(stderr,"%s: TXband=%s disablePA=%d\n",__FUNCTION__,txband->title,txband->disablePA);


output_buffer[C0]=0x12;
Expand All @@ -1683,22 +1719,21 @@ static int last_power=0;
if(mic_linein) {
output_buffer[C2]|=0x02;
}
if(filter_board==APOLLO || device==DEVICE_HERMES_LITE2) {
if(filter_board==APOLLO) {
output_buffer[C2]|=0x2C;
}
if((filter_board==APOLLO) && tune) {
output_buffer[C2]|=0x10;
}
if((device==DEVICE_HERMES_LITE2) && pa_enabled) {
output_buffer[C2]|=0x10; // Enable PA
}
if(band_get_current()==band6) {
output_buffer[C3]=output_buffer[C3]|0x40; // Alex 6M low noise amplifier
}
if(isTransmitting() && band->disablePA) {
output_buffer[C2]|=0x40; // Manual Filter Selection
output_buffer[C3]|=0x20; // bypass all RX filters
if(txband->disablePA || !pa_enabled) {
output_buffer[C3]|=0x80; // disable Alex T/R relay
if (isTransmitting()) {
output_buffer[C2]|=0x40; // Manual Filter Selection
output_buffer[C3]|=0x20; // bypass all RX filters
}
}
#ifdef PURESIGNAL
//
Expand Down Expand Up @@ -1735,6 +1770,17 @@ static int last_power=0;
}
}
#endif
if (device==DEVICE_HERMES_LITE2) {
// do not set any Apollo/Alex bits (ADDR=0x09 bits 0:23)
// ADDR=0x09 bit 19 follows "PA enable" state
// ADDR=0x09 bit 20 follows "TUNE" state
// ADDR=0x09 bit 18 always cleared (external tuner enabled)
output_buffer[C2]= 0x00;
output_buffer[C3]= 0x00;
output_buffer[C4]= 0x00;
if (pa_enabled && !txband->disablePA) output_buffer[C2] |= 0x08;
if (tune) output_buffer[C2] |= 0x10;
}
#ifdef DEBUG_PROTO
CHECK(output_buffer[C1], C1_DRIVE);
CHECK((output_buffer[C2] & 0xE0) >> 5, C2_FB);
Expand All @@ -1744,8 +1790,8 @@ static int last_power=0;
CHECK((output_buffer[C3] & 0x80) >> 7, C3_TXDIS);
CHECK(output_buffer[C4], C4_LPF);
#endif
}
break;
}
case 4:
output_buffer[C0]=0x14;
output_buffer[C1]=0x00;
Expand Down

0 comments on commit 2cd52ca

Please sign in to comment.