/* -*- mode: c; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4; coding: utf-8 -*- */ /************************************************************************************ ** ** ** UHSDR ** ** a powerful firmware for STM32 based SDR transceivers ** ** ** **--------------------------------------------------------------------------------** ** ** ** Description: Please provide one ** ** Licence: GNU GPLv3 ** ************************************************************************************/ #include #include "ui_driver.h" // for pushing into UI buffer #include "uhsdr_digi_buffer.h" #define DIGIMODES_TX_BUFFER_SIZE 128 static __IO uint8_t digimodes_tx_buffer[DIGIMODES_TX_BUFFER_SIZE]; static __IO int32_t digimodes_tx_buffer_head = 0; static __IO int32_t digimodes_tx_tail = 0; static __IO uint32_t active_consumer = 0; // keeps prev consumer to restore it by calling DigiModes_Restore_BufferConsumer(); static __IO uint32_t prev_consumer = CW; void DigiModes_Restore_BufferConsumer() { active_consumer = prev_consumer; } /* * The UI consumer has higher priority to protect it by changing modes. * UI should release buffer by calling DigiModes_Restore_BufferConsumer() */ digi_buff_consumer_t DigiModes_Set_BufferConsumer( digi_buff_consumer_t consumer ) { assert((consumer & RTTY) || (consumer & BPSK) || (consumer & CW) || (consumer & UI)); if ( active_consumer == UI ) // <- UI has higher priority { prev_consumer = consumer; // in case we change mode return prev_consumer; } prev_consumer = active_consumer; active_consumer = consumer; return prev_consumer; } uint8_t DigiModes_TxBufferHasData() { int32_t len = digimodes_tx_buffer_head - digimodes_tx_tail; return len < 0 ? ( len + DIGIMODES_TX_BUFFER_SIZE ) : len; } bool DigiModes_TxBufferRemove( uint8_t* c_ptr, digi_buff_consumer_t consumer ) { assert( c_ptr ); assert((consumer & RTTY) || (consumer & BPSK) || (consumer & CW) || (consumer & UI)); bool retval = false; if ( consumer == active_consumer && digimodes_tx_buffer_head != digimodes_tx_tail) { *c_ptr = digimodes_tx_buffer[digimodes_tx_tail]; digimodes_tx_tail = (digimodes_tx_tail + 1) % DIGIMODES_TX_BUFFER_SIZE; // push removed char to UI buffer to display it on the screen. // characters for UI and CW prints when they add to digi_buffer if ( active_consumer == RTTY || active_consumer == BPSK ) { UiDriver_TextMsgPutChar( *c_ptr ); } retval = true; } return retval; } /* no room left in the buffer returns 0 */ int32_t DigiModes_TxBufferPutChar( uint8_t c, digi_buff_consumer_t source ) { assert((source & CW) || (source & KeyBoard) || (source & UI)); int32_t ret = 0; /* * In case when source and consumer are equal we just * print on the screen without putting into digi_buffer * to prevent from infinite loop * ( CW working as a source and receiver at the same time ) */ if ( active_consumer == source ) { if(!(ts.dmod_mode == DEMOD_CW && !ts.cw_decoder_enable)) { UiDriver_TextMsgPutChar( c ); } } else { int32_t next_head = (digimodes_tx_buffer_head + 1) % DIGIMODES_TX_BUFFER_SIZE; if (next_head != digimodes_tx_tail) { /* there is room */ digimodes_tx_buffer[digimodes_tx_buffer_head] = c; digimodes_tx_buffer_head = next_head; /* * If the consumer is UI we print on the screen * right the way on the inputing text into buffer */ if ( active_consumer == UI ) { if(!(ts.dmod_mode == DEMOD_CW && !ts.cw_decoder_enable)) { UiDriver_TextMsgPutChar( c ); } } ret ++; } } return ret; } void DigiModes_TxBufferPutSign( const char* s, digi_buff_consumer_t source ) { assert( s ); assert((source & CW) || (source & KeyBoard)); DigiModes_TxBufferPutChar( '<', source ); DigiModes_TxBufferPutChar( s[0], source ); DigiModes_TxBufferPutChar( s[1], source ); DigiModes_TxBufferPutChar( '>', source ); } void DigiModes_TxBufferReset() { digimodes_tx_tail = digimodes_tx_buffer_head; } #if defined(_UNIT_TEST_) uint32_t DigiModes_TxBufferGetCurrentConsumer( void ) { return active_consumer; } uint32_t DigiModes_TxBufferGetPrevConsumer( void ) { return prev_consumer; } #endif