UHSDR/UHSDR-active-devel/mchf-eclipse/drivers/audio/cw/uhsdr_digi_buffer.c
2022-11-08 16:13:55 +01:00

147 lines
4.9 KiB
C

/* -*- 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 <assert.h>
#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