From 3a9f59def98970cbb2e42f176463d570eac3dfe7 Mon Sep 17 00:00:00 2001 From: Ed Gonzalez Date: Wed, 26 Aug 2015 11:27:01 -0500 Subject: [PATCH] Add DSTAR TX State machine to handle transmit. Move current TX Logic from sched_waveform to the TX State Machine --- DSP_API/SmartSDR_Interface/sched_waveform.c | 120 ++----------- DSP_API/ThumbDV/dstar.c | 182 +++++++++++++++++--- DSP_API/ThumbDV/dstar.h | 16 +- 3 files changed, 183 insertions(+), 135 deletions(-) diff --git a/DSP_API/SmartSDR_Interface/sched_waveform.c b/DSP_API/SmartSDR_Interface/sched_waveform.c index b8df951..9923def 100644 --- a/DSP_API/SmartSDR_Interface/sched_waveform.c +++ b/DSP_API/SmartSDR_Interface/sched_waveform.c @@ -194,15 +194,6 @@ static BOOL _end_of_transmission = FALSE; #define FREEDV_NSAMPLES 160 -static void icom_byteToBits( unsigned char byte, BOOL * bits ) { - unsigned char mask = 0x01; - uint32 i = 0; - - for ( i = 0 ; i < 8 ; i++, mask <<= 1 ) { - bits[i] = ( byte & mask ) ? TRUE : FALSE; - } -} - void sched_waveform_sendStatus( uint32 slice ) { dstar_updateStatus( _dstar, slice, STATUS_TX ); } @@ -488,9 +479,9 @@ static void * _sched_waveform_thread( void * param ) { BOOL ambe_packet_out = FALSE; if ( state == DEMOD_TRUE ) { - ambe_packet_out = dstar_stateMachine( _dstar, TRUE, ambe_out, 9 ); + ambe_packet_out = dstar_rxStateMachine( _dstar, TRUE, ambe_out, 9 ); } else if ( state == DEMOD_FALSE ) { - ambe_packet_out = dstar_stateMachine( _dstar, FALSE, ambe_out, 9 ); + ambe_packet_out = dstar_rxStateMachine( _dstar, FALSE, ambe_out, 9 ); } else { /* Nothing to do since we have not "locked" a bit out yet */ } @@ -612,70 +603,20 @@ static void * _sched_waveform_thread( void * param ) { decode_out = thumbDV_encode( _dv_serial_fd, speech_in, mod_out, DV_PACKET_SAMPLES ); } - float buf[DSTAR_RADIO_BIT_LENGTH]; uint32 j = 0; if ( initial_tx ) { initial_tx = FALSE; - /* Create Sync */ - for ( i = 0 ; i < 64 + 20; i += 2 ) { - gmsk_encode( _gmsk_mod, TRUE, buf, DSTAR_RADIO_BIT_LENGTH ); + _dstar->tx_state = BIT_FRAME_SYNC; - for ( j = 0 ; j < DSTAR_RADIO_BIT_LENGTH ; j++ ) { - cbWriteFloat( TX4_cb, buf[j] ); - } + dstar_txStateMachine(_dstar, _gmsk_mod, TX4_cb, NULL); - gmsk_encode( _gmsk_mod, FALSE, buf, DSTAR_RADIO_BIT_LENGTH ); + _dstar->tx_state = HEADER_PROCESSING; - for ( j = 0 ; j < DSTAR_RADIO_BIT_LENGTH ; j++ ) { - cbWriteFloat( TX4_cb, buf[j] ); - } - } + dstar_txStateMachine(_dstar, _gmsk_mod, TX4_cb, NULL); - for ( i = 0 ; i < FRAME_SYNC_LENGTH_BITS ; i++ ) { - gmsk_encode( _gmsk_mod, FRAME_SYNC_BITS[i], buf, DSTAR_RADIO_BIT_LENGTH ); - - for ( j = 0 ; j < DSTAR_RADIO_BIT_LENGTH ; j++ ) { - cbWriteFloat( TX4_cb, buf[j] ); - } - } - - dstar_pfcs pfcs; - pfcs.crc16 = 0xFFFF; - - unsigned char header_bytes[RADIO_HEADER_LENGTH_BITS] = {0}; - dstar_headerToBytes( &( _dstar->outgoing_header ), header_bytes ); - dstar_pfcsUpdateBuffer( &pfcs, header_bytes, 312 / 8 ); - dstar_pfcsResult( &pfcs, header_bytes + 312 / 8 ); - - output( "Main: PFCS Bytes: 0x%08X 0x%08X\n", *( header_bytes + 312 / 8 ), *( header_bytes + 320 / 8 ) ); - - BOOL bits[FEC_SECTION_LENGTH_BITS] = {0}; - - gmsk_bytesToBits( header_bytes, bits, 328 ); - BOOL encoded[RADIO_HEADER_LENGTH_BITS * 2] = {0}; - BOOL interleaved[RADIO_HEADER_LENGTH_BITS * 2] = {0}; - BOOL scrambled[RADIO_HEADER_LENGTH_BITS * 2] = {0}; - uint32 outLen = 0; - dstar_FECencode( bits, encoded, RADIO_HEADER_LENGTH_BITS, &outLen ); - //output("Encode outLen = %d\n", outLen); - - outLen = FEC_SECTION_LENGTH_BITS; - dstar_interleave( encoded, interleaved, outLen ); - - uint32 count = 0; - dstar_scramble( interleaved, scrambled, outLen, &count ); - output( "Count = %d\n", count ); - - for ( i = 0 ; i < count ; i++ ) { - gmsk_encode( _gmsk_mod, scrambled[i], buf, DSTAR_RADIO_BIT_LENGTH ); - - for ( j = 0 ; j < DSTAR_RADIO_BIT_LENGTH ; j++ ) { - cbWriteFloat( TX4_cb, buf[j] ); - } - } initial_tx_flush = TRUE; @@ -685,30 +626,12 @@ static void * _sched_waveform_thread( void * param ) { float data_buf[DATA_FRAME_LENGTH_BITS * DSTAR_RADIO_BIT_LENGTH] = {0}; if ( decode_out != 0 ) { - BOOL bits[8] = {0} ; - uint32 k = 0; - - for ( i = 0 ; i < VOICE_FRAME_LENGTH_BYTES ; i++ ) { - icom_byteToBits( mod_out[i], bits ); - - for ( j = 0 ; j < 8 ; j++ ) { - gmsk_encode( _gmsk_mod, bits[j], buf, DSTAR_RADIO_BIT_LENGTH ); - - for ( k = 0 ; k < DSTAR_RADIO_BIT_LENGTH ; k++ ) { - cbWriteFloat( TX4_cb, buf[k] ); - } - } - } + _dstar->tx_state = VOICE_FRAME; + dstar_txStateMachine(_dstar, _gmsk_mod, TX4_cb, mod_out); if ( dstar_tx_frame_count % 21 == 0 ) { - /* Sync Bits */ - unsigned char sync_bytes[3] = {0}; - memcpy( sync_bytes, DATA_SYNC_BYTES, 3 ); - gmsk_encodeBuffer( _gmsk_mod, sync_bytes, DATA_FRAME_LENGTH_BITS, data_buf, DATA_FRAME_LENGTH_BITS * DSTAR_RADIO_BIT_LENGTH ); - - for ( i = 0 ; i < DATA_FRAME_LENGTH_BITS * DSTAR_RADIO_BIT_LENGTH ; i++ ) { - cbWriteFloat( TX4_cb, data_buf[i] ); - } + _dstar->tx_state = DATA_SYNC_FRAME; + dstar_txStateMachine(_dstar, _gmsk_mod, TX4_cb, NULL); } else { @@ -780,28 +703,9 @@ static void * _sched_waveform_thread( void * param ) { if ( _end_of_transmission && !inhibit_tx ) { - float end_buf[END_PATTERN_LENGTH_BITS * DSTAR_RADIO_BIT_LENGTH] = {0.0}; - unsigned char end_bytes[END_PATTERN_LENGTH_BYTES] = {0}; - memcpy( end_bytes, END_PATTERN_BYTES, END_PATTERN_LENGTH_BYTES * sizeof( unsigned char ) ); - gmsk_encodeBuffer( _gmsk_mod, end_bytes, END_PATTERN_LENGTH_BITS, end_buf, END_PATTERN_LENGTH_BITS * DSTAR_RADIO_BIT_LENGTH ); + _dstar->tx_state = END_PATTERN; - for ( i = 0 ; i < END_PATTERN_LENGTH_BITS * DSTAR_RADIO_BIT_LENGTH ; i++ ) { - cbWriteFloat( TX4_cb, end_buf[i] ); - } - - for ( i = 0 ; i < 20 ; i += 2 ) { - gmsk_encode( _gmsk_mod, TRUE, buf, DSTAR_RADIO_BIT_LENGTH ); - - for ( j = 0 ; j < DSTAR_RADIO_BIT_LENGTH ; j++ ) { - cbWriteFloat( TX4_cb, buf[j] ); - } - - gmsk_encode( _gmsk_mod, FALSE, buf, DSTAR_RADIO_BIT_LENGTH ); - - for ( j = 0 ; j < DSTAR_RADIO_BIT_LENGTH ; j++ ) { - cbWriteFloat( TX4_cb, buf[j] ); - } - } + dstar_txStateMachine(_dstar, _gmsk_mod, TX4_cb, NULL); flush_tx = TRUE; initial_tx_flush = TRUE; diff --git a/DSP_API/ThumbDV/dstar.c b/DSP_API/ThumbDV/dstar.c index a684df0..ffff3af 100644 --- a/DSP_API/ThumbDV/dstar.c +++ b/DSP_API/ThumbDV/dstar.c @@ -38,6 +38,7 @@ #include "thumbDV.h" #include "dstar.h" #include "slow_data.h" +#include "circular_buffer.h" #define SCRAMBLER_TABLE_BITS_LENGTH 720U #define SCRAMBLER_TABLE_BYTES_LENGTH 90U @@ -180,6 +181,15 @@ static const unsigned short ccittTab[] = { 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78 }; +void icom_byteToBits( unsigned char byte, BOOL * bits ) { + unsigned char mask = 0x01; + uint32 i = 0; + + for ( i = 0 ; i < 8 ; i++, mask <<= 1 ) { + bits[i] = ( byte & mask ) ? TRUE : FALSE; + } +} + void dstar_scramble( BOOL * in, BOOL * out, uint32 length, uint32 * scramble_count ) { if ( out == NULL || in == NULL || scramble_count == NULL ) { output( "Null inOut pointer\n" ); @@ -478,7 +488,8 @@ DSTAR_MACHINE dstar_createMachine( void ) { DSTAR_MACHINE machine = safe_malloc( sizeof( dstar_machine ) ); memset( machine, 0, sizeof( dstar_machine ) ); - machine->state = BIT_FRAME_SYNC_WAIT; + machine->rx_state = BIT_FRAME_SYNC; + machine->tx_state = BIT_FRAME_SYNC; BOOL syn_bits[15 + 4] = {0}; uint32 i = 0; @@ -636,7 +647,138 @@ void dstar_updateStatus( DSTAR_MACHINE machine, uint32 slice, enum STATUS_TYPE } } -BOOL dstar_stateMachine( DSTAR_MACHINE machine, BOOL in_bit, unsigned char * ambe_out, uint32 ambe_buf_len ) { +void dstar_txStateMachine( DSTAR_MACHINE machine, GMSK_MOD gmsk_mod, Circular_Float_Buffer tx_cb, unsigned char * mod_audio) +{ + uint32 i = 0; + uint32 j = 0; + float buf[DSTAR_RADIO_BIT_LENGTH]; + dstar_pfcs pfcs; + + switch ( machine->tx_state ) { + case BIT_FRAME_SYNC: + /* Create Sync */ + for ( i = 0 ; i < 64 + 20; i += 2 ) { + gmsk_encode( gmsk_mod, TRUE, buf, DSTAR_RADIO_BIT_LENGTH ); + + for ( j = 0 ; j < DSTAR_RADIO_BIT_LENGTH ; j++ ) { + cbWriteFloat( tx_cb, buf[j] ); + } + + gmsk_encode( gmsk_mod, FALSE, buf, DSTAR_RADIO_BIT_LENGTH ); + + for ( j = 0 ; j < DSTAR_RADIO_BIT_LENGTH ; j++ ) { + cbWriteFloat( tx_cb, buf[j] ); + } + } + + for ( i = 0 ; i < FRAME_SYNC_LENGTH_BITS ; i++ ) { + gmsk_encode( gmsk_mod, FRAME_SYNC_BITS[i], buf, DSTAR_RADIO_BIT_LENGTH ); + + for ( j = 0 ; j < DSTAR_RADIO_BIT_LENGTH ; j++ ) { + cbWriteFloat( tx_cb, buf[j] ); + } + } + break; + case HEADER_PROCESSING: + + pfcs.crc16 = 0xFFFF; + + unsigned char header_bytes[RADIO_HEADER_LENGTH_BITS] = {0}; + dstar_headerToBytes( &( machine->outgoing_header ), header_bytes ); + dstar_pfcsUpdateBuffer( &pfcs, header_bytes, 312 / 8 ); + dstar_pfcsResult( &pfcs, header_bytes + 312 / 8 ); + + output( "Main: PFCS Bytes: 0x%08X 0x%08X\n", *( header_bytes + 312 / 8 ), *( header_bytes + 320 / 8 ) ); + + BOOL bits[FEC_SECTION_LENGTH_BITS] = {0}; + + gmsk_bytesToBits( header_bytes, bits, 328 ); + BOOL encoded[RADIO_HEADER_LENGTH_BITS * 2] = {0}; + BOOL interleaved[RADIO_HEADER_LENGTH_BITS * 2] = {0}; + BOOL scrambled[RADIO_HEADER_LENGTH_BITS * 2] = {0}; + uint32 outLen = 0; + dstar_FECencode( bits, encoded, RADIO_HEADER_LENGTH_BITS, &outLen ); + //output("Encode outLen = %d\n", outLen); + + outLen = FEC_SECTION_LENGTH_BITS; + dstar_interleave( encoded, interleaved, outLen ); + + uint32 count = 0; + dstar_scramble( interleaved, scrambled, outLen, &count ); + output( "Count = %d\n", count ); + + for ( i = 0 ; i < count ; i++ ) { + gmsk_encode( gmsk_mod, scrambled[i], buf, DSTAR_RADIO_BIT_LENGTH ); + + for ( j = 0 ; j < DSTAR_RADIO_BIT_LENGTH ; j++ ) { + cbWriteFloat( tx_cb, buf[j] ); + } + } + break; + case VOICE_FRAME: + { + BOOL bits[8] = {0} ; + uint32 k = 0; + + for ( i = 0 ; i < VOICE_FRAME_LENGTH_BYTES ; i++ ) { + icom_byteToBits( mod_audio[i], bits ); + + for ( j = 0 ; j < 8 ; j++ ) { + gmsk_encode( gmsk_mod, bits[j], buf, DSTAR_RADIO_BIT_LENGTH ); + + for ( k = 0 ; k < DSTAR_RADIO_BIT_LENGTH ; k++ ) { + cbWriteFloat( tx_cb, buf[k] ); + } + } + } + break; + } + case DATA_FRAME: + break; + case DATA_SYNC_FRAME: + { + /* Sync Bits */ + unsigned char sync_bytes[3] = {0}; + float sync_buf[DATA_FRAME_LENGTH_BITS * DSTAR_RADIO_BIT_LENGTH] = {0}; + memcpy( sync_bytes, DATA_SYNC_BYTES, 3 ); + gmsk_encodeBuffer( gmsk_mod, sync_bytes, DATA_FRAME_LENGTH_BITS, sync_buf, DATA_FRAME_LENGTH_BITS * DSTAR_RADIO_BIT_LENGTH ); + + for ( i = 0 ; i < DATA_FRAME_LENGTH_BITS * DSTAR_RADIO_BIT_LENGTH ; i++ ) { + cbWriteFloat( tx_cb, sync_buf[i] ); + } + break; + } + case END_PATTERN: + { + float end_buf[END_PATTERN_LENGTH_BITS * DSTAR_RADIO_BIT_LENGTH] = {0.0}; + unsigned char end_bytes[END_PATTERN_LENGTH_BYTES] = {0}; + memcpy( end_bytes, END_PATTERN_BYTES, END_PATTERN_LENGTH_BYTES * sizeof( unsigned char ) ); + gmsk_encodeBuffer( gmsk_mod, end_bytes, END_PATTERN_LENGTH_BITS, end_buf, END_PATTERN_LENGTH_BITS * DSTAR_RADIO_BIT_LENGTH ); + + for ( i = 0 ; i < END_PATTERN_LENGTH_BITS * DSTAR_RADIO_BIT_LENGTH ; i++ ) { + cbWriteFloat( tx_cb, end_buf[i] ); + } + + for ( i = 0 ; i < 20 ; i += 2 ) { + gmsk_encode( gmsk_mod, TRUE, buf, DSTAR_RADIO_BIT_LENGTH ); + + for ( j = 0 ; j < DSTAR_RADIO_BIT_LENGTH ; j++ ) { + cbWriteFloat( tx_cb, buf[j] ); + } + + gmsk_encode( gmsk_mod, FALSE, buf, DSTAR_RADIO_BIT_LENGTH ); + + for ( j = 0 ; j < DSTAR_RADIO_BIT_LENGTH ; j++ ) { + cbWriteFloat( tx_cb, buf[j] ); + } + } + + break; + } + } +} + +BOOL dstar_rxStateMachine( DSTAR_MACHINE machine, BOOL in_bit, unsigned char * ambe_out, uint32 ambe_buf_len ) { BOOL have_audio_packet = FALSE; BOOL found_syn_bits = FALSE; BOOL found_end_bits = FALSE; @@ -644,14 +786,10 @@ BOOL dstar_stateMachine( DSTAR_MACHINE machine, BOOL in_bit, unsigned char * amb BOOL * voice_bits = machine->voice_bits; BOOL * data_bits = machine->data_bits; -// static unsigned char data_bytes[3 * 40 * 4] = {0}; -// static uint32 long_data_bytes_idx = 0; - - //unsigned char bytes[((24+72) * 50)/8 + 1]; unsigned char bytes[FEC_SECTION_LENGTH_BITS / 8 + 1]; - switch ( machine->state ) { - case BIT_FRAME_SYNC_WAIT: + switch ( machine->rx_state ) { + case BIT_FRAME_SYNC: found_syn_bits = bitPM_addBit( machine->syn_pm, in_bit ); BOOL found_data_sync = bitPM_addBit( machine->data_sync_pm, in_bit ); @@ -662,13 +800,13 @@ BOOL dstar_stateMachine( DSTAR_MACHINE machine, BOOL in_bit, unsigned char * amb output( "FOUND SYN BITS\n" ); bitPM_reset( machine->syn_pm ); bitPM_reset( machine->data_sync_pm ); - machine->state = HEADER_PROCESSING; + machine->rx_state = HEADER_PROCESSING; machine->bit_count = 0; } else if ( found_data_sync ) { output( "FOUND DATA SYNC BITS instead of header\n" ); bitPM_reset( machine->syn_pm ); bitPM_reset( machine->data_sync_pm ); - machine->state = VOICE_FRAME; + machine->rx_state = VOICE_FRAME; machine->bit_count = 0; machine->frame_count++; } @@ -726,7 +864,7 @@ BOOL dstar_stateMachine( DSTAR_MACHINE machine, BOOL in_bit, unsigned char * amb } /* STATE CHANGE */ - machine->state = VOICE_FRAME; + machine->rx_state = VOICE_FRAME; machine->bit_count = 0; machine->frame_count = 0; } @@ -739,7 +877,7 @@ BOOL dstar_stateMachine( DSTAR_MACHINE machine, BOOL in_bit, unsigned char * amb found_end_bits = bitPM_addBit( machine->end_pm, in_bit ); if ( found_end_bits ) { - machine->state = END_PATTERN_FOUND; + machine->rx_state = END_PATTERN; machine->bit_count = 0; } else if ( machine->bit_count == VOICE_FRAME_LENGTH_BITS ) { memset( bytes, 0, VOICE_FRAME_LENGTH_BYTES ); @@ -757,9 +895,9 @@ BOOL dstar_stateMachine( DSTAR_MACHINE machine, BOOL in_bit, unsigned char * amb /* STATE CHANGE */ if ( machine->frame_count % 21 == 0 ) { /* Expecting a SYNC FRAME */ - machine->state = DATA_SYNC_FRAME; + machine->rx_state = DATA_SYNC_FRAME; } else { - machine->state = DATA_FRAME; + machine->rx_state = DATA_FRAME; } machine->bit_count = 0; @@ -773,7 +911,7 @@ BOOL dstar_stateMachine( DSTAR_MACHINE machine, BOOL in_bit, unsigned char * amb found_end_bits = bitPM_addBit( machine->end_pm, in_bit ); if ( found_end_bits ) { - machine->state = END_PATTERN_FOUND; + machine->rx_state = END_PATTERN; machine->bit_count = 0; } else if ( machine->bit_count == DATA_FRAME_LENGTH_BITS ) { @@ -793,7 +931,7 @@ BOOL dstar_stateMachine( DSTAR_MACHINE machine, BOOL in_bit, unsigned char * amb machine->frame_count++; /* STATE CHANGE */ - machine->state = VOICE_FRAME; + machine->rx_state = VOICE_FRAME; machine->bit_count = 0; } @@ -813,10 +951,10 @@ BOOL dstar_stateMachine( DSTAR_MACHINE machine, BOOL in_bit, unsigned char * amb bitPM_reset( machine->data_sync_pm ); /* STATE CHANGE */ - machine->state = VOICE_FRAME; + machine->rx_state = VOICE_FRAME; machine->bit_count = 0; } else if ( found_end_bits ) { - machine->state = END_PATTERN_FOUND; + machine->rx_state = END_PATTERN; machine->bit_count = 0; } else if ( machine->bit_count > ( ( DATA_FRAME_LENGTH_BITS + VOICE_FRAME_LENGTH_BITS ) * 42 ) ) { /* Function as a timeout if we don't find the sync bits */ @@ -825,7 +963,7 @@ BOOL dstar_stateMachine( DSTAR_MACHINE machine, BOOL in_bit, unsigned char * amb bitPM_reset( machine->data_sync_pm ); /* STATE CHANGE */ - machine->state = BIT_FRAME_SYNC_WAIT; + machine->rx_state = BIT_FRAME_SYNC; machine->bit_count = 0; } @@ -834,20 +972,20 @@ BOOL dstar_stateMachine( DSTAR_MACHINE machine, BOOL in_bit, unsigned char * amb break; } - case END_PATTERN_FOUND: + case END_PATTERN: output( "Found end pattern bits\n" ); bitPM_reset( machine->end_pm ); bitPM_reset( machine->syn_pm ); /* STATE CHANGE */ - machine->state = BIT_FRAME_SYNC_WAIT; + machine->rx_state = BIT_FRAME_SYNC; machine->bit_count = 0; break; default: - output( ANSI_YELLOW "Unhandled state - dstar_stateMachine. State = 0x%08X" ANSI_WHITE, machine->state ); + output( ANSI_YELLOW "Unhandled rx_state - dstar_stateMachine. State = 0x%08X" ANSI_WHITE, machine->rx_state ); break; } diff --git a/DSP_API/ThumbDV/dstar.h b/DSP_API/ThumbDV/dstar.h index 73213d5..61a6a8d 100644 --- a/DSP_API/ThumbDV/dstar.h +++ b/DSP_API/ThumbDV/dstar.h @@ -33,6 +33,8 @@ #include "bit_pattern_matcher.h" #include "DStarDefines.h" #include "dstar.h" +#include "gmsk_modem.h" +#include "circular_buffer.h" enum _slow_data_decode_state { FIRST_FRAME = 0, @@ -54,13 +56,13 @@ typedef struct _slow_data_machine { } slow_data_machine, *SLOW_DATA_MACHINE; -enum DSTAR_STATE { - BIT_FRAME_SYNC_WAIT = 0x1, +enum DSTAR_RX_STATE { + BIT_FRAME_SYNC = 0x1, HEADER_PROCESSING, VOICE_FRAME, DATA_FRAME, DATA_SYNC_FRAME, - END_PATTERN_FOUND + END_PATTERN }; enum STATUS_TYPE { @@ -82,7 +84,8 @@ typedef struct _dstar_header { } dstar_header, * DSTAR_HEADER; typedef struct _dstar_machine { - enum DSTAR_STATE state; + enum DSTAR_RX_STATE rx_state; + enum DSTAR_RX_STATE tx_state; dstar_header incoming_header; dstar_header outgoing_header; @@ -118,10 +121,13 @@ typedef union _dstar_pfcs { uint8 crc8[2]; } dstar_pfcs, * DSTAR_PFCS; +void icom_byteToBits( unsigned char byte, BOOL * bits ); + void dstar_updateStatus( DSTAR_MACHINE machine, uint32 slice , enum STATUS_TYPE type ); DSTAR_MACHINE dstar_createMachine( void ); void dstar_destroyMachine( DSTAR_MACHINE machine ); -BOOL dstar_stateMachine( DSTAR_MACHINE machine, BOOL in_bit, unsigned char * ambe_out, uint32 ambe_buf_len ); +BOOL dstar_rxStateMachine( DSTAR_MACHINE machine, BOOL in_bit, unsigned char * ambe_out, uint32 ambe_buf_len ); +void dstar_txStateMachine( DSTAR_MACHINE machine, GMSK_MOD gmsk_mod, Circular_Float_Buffer tx_cb, unsigned char * mod_audio); void dstar_dumpHeader( DSTAR_HEADER header );