Fabio Fumi
/
send_to_sharp
Renamed
Diff: bit_send.cpp
- Revision:
- 0:07819bc70660
- Child:
- 1:9289febf4ae9
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bit_send.cpp Tue Feb 15 15:37:06 2022 +0000 @@ -0,0 +1,219 @@ +#include "mbed.h" +#include "bit_send.h" + +DigitalOut bit_out_port(D5); +DigitalOut led1(LED1); +Serial pc1(USBTX,USBRX); +Ticker bit_ticker; +Timer total_time1; + +// volatile when read & write from both interrupts and main +// static is to keep value between calls +volatile uint32_t bit_sync_flags; +volatile uint32_t bit_buffer; // 32-bits buffer (position-masked) +volatile uint32_t bit_read_mask; // bit read position +volatile uint32_t bit_write_mask; // bit write position +volatile uint32_t bit_last_mask; // position of last bit sent + +volatile uint32_t bit_repeat_count = 0; +volatile uint32_t bit_cycle_count = 0; + +volatile uint32_t total_switch_cnt = 0; + +// To be called before a new stream is sent +void bitHandlerInit( void ) { + + debug_printf("bitHandlerInit\r\n") ; + + // timing ticker counters + bit_repeat_count = 0; + bit_cycle_count = 0; + + bit_sync_flags = 0; // clear all (set when needed) + + // buffer initial positions + bit_read_mask = 1; + bit_write_mask = 1; + bit_buffer = 0; + + // start with a LOW level on output + bit_out_port = 0; + + // debugging counters + total_switch_cnt = 0; + +} + +// Called after last bit to be sent has been sent +void bitHandlerStop ( void ) { + + bit_sync_flags |= BIT_LAST_SENT; // signal for no more bits to send + bit_last_mask = bit_write_mask; // for consumer, to stop here + // NOTE - ticker will be disabled in the handler itself + // as it has to wait for last bit to be processed, first + +} + +// A bit (x) is composed of BIT_TICK_x_NCYCLES of alternating HIGH and LOW levels, +// with each level interval lasting BIT_TICK_x_REPEAT ticker repetitions. +// Example for bit "0" -- BIT_TICK_0_NCYCLES = 8, BIT_TICK_0_REPEAT = 2: +// ___ ___ ___ ___ +// out _| |___| |___| |___| |_ +// cycle 7 6 5 4 3 2 1 0 ... +// repeat 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 ... +// +// the bit-handler bitTickHandler(), called every BIT_TICK_DELAY (Ticker object) +// will pull a bit from the circular buffer ( bit_buffer ), +// which is populated from writer bitWaitSend(). +// Writer takes care of synchronization of read and write buffer pointers, +// assuming writer is FASTER than consumer handler +void bitTickHandler ( void ) +{ + + if ( bit_cycle_count == 0 ) { + // New bit to be pulled off the buffer - restart counters + if ( bit_sync_flags & BIT_LAST_PROCESSING ) { + // stop AFTER last bit has been pulled (see below) + bit_ticker.detach (); + led1 = 0; // ticker stopped + + total_time1.stop(); + debug_printf("BIT_LAST_PROCESSING time(us): %d\r\n", total_time1.read_us()); + } else { + // update read position (shift left mask) + // and reset tick and cycle counters + if ( ( bit_read_mask = bit_read_mask<<1 ) == 0 ) + bit_read_mask = 1; // circular buffer + if ( bit_buffer & bit_read_mask ) { + // bit-1 from buffer + bit_cycle_count = BIT_TICK_1_NCYCLES; + bit_repeat_count = BIT_TICK_1_REPEAT; + } else { + // bit-0 from buffer + bit_cycle_count = BIT_TICK_0_NCYCLES; + bit_repeat_count = BIT_TICK_0_REPEAT; + } + if ( ( bit_sync_flags & BIT_LAST_SENT ) && + ( bit_read_mask == bit_last_mask ) ) { + // set BEFORE last bit being processed + bit_sync_flags |= BIT_LAST_PROCESSING; + } + } + } + + if ( --bit_repeat_count == 0 ) { + // toggle output port level + total_switch_cnt += 1; + bit_out_port = !bit_out_port; + if ( total_switch_cnt & 0x10 ) led1 != led1; // show activity + // a ticker-repeat cycle has completed + bit_cycle_count --; + if ( bit_buffer & bit_read_mask ) // this bit is 1 + bit_repeat_count = BIT_TICK_1_REPEAT; + else + bit_repeat_count = BIT_TICK_0_REPEAT; + } + +} + +// Push a bit to the buffer. +// Waiting in an idle loop, though not 100% busy (wait), +// as thread signals (Mbed-RTOS) are not available on the L053R8 +int bitWaitSend ( uint8_t bit_value, uint8_t invert ) { + + // Both bit_read_position and bit_write_position cycle through the buffer + // When they are the same, put sender on hold, for consumer to complete. + // Polling regularly, then writing a new bit to buffer + // when pointers are different (the slower handler has moved bit_read_mask). + // Bit handler takes 2ms to spool a single bit: + // ( BIT_TICK_x_CYCLE+1 ) * BIT_TICK_x_REPEAT * BIT_TICK_DELAY (us) + // hence, as soon as writer can write new data, it has 2x32ms to write + // new bits before filling again the buffer. + // Polling has to be frequent enough not to let consumer pull wrong bits... + while ( ( bit_write_mask == bit_read_mask ) && ( bit_sync_flags & BIT_FIRST_SENT ) ) + wait_us ( 1000 ); + + // update buffer write position (shift left mask) + if ( ( bit_write_mask = bit_write_mask<<1 ) == 0 ) + bit_write_mask = 1; // it's a circular buffer + + // push this bit to the buffer + if ( (bit_value & 0x01) ^ (invert & 0x01) ) // ignore positions other than 1 + bit_buffer |= (bit_write_mask); // set + else + bit_buffer &= ~(bit_write_mask); // clear + + // on first bit only, start consumer too + if ( !(bit_sync_flags & BIT_FIRST_SENT) ) { + bit_ticker.attach_us ( &bitTickHandler, BIT_TICK_DELAY ); // start ticker + bit_sync_flags |= BIT_FIRST_SENT; // first bit gone + led1 = 1; // debugging purpose (ticker on) + total_time1.reset(); + total_time1.start(); + } + +} + +bool bitHandlerRunning( void ) { + + return ( !(bit_sync_flags & BIT_LAST_PROCESSING) ) ; + +} + +/////////////////////////////////////////////////////////////////////////////// +/* MAIN USED FOR A STANDALONE TEST BED +int main() +{ + + int i, ii; + char inVal; + + // flashing led1 on startup + for (i=0; i<5; i+=1) { + wait (0.1); + led1 = !led1; + } + led1 = 0; + + pc1.baud(57600); + + // welcome message + pc1.printf("\n\r ** MBED ** test bit send ** \n\r"); + fflush(stdout); + + // main loop + while(true) { + + pc1.printf("Hit a key ... \n\r"); + fflush(stdout); + inVal=pc1.getc(); // wait for a key press (over serial) + + debug_printf("%.2x ", inVal); + for ( ii = 0; ii < 8; ii++ ) + debug_printf( "%d", ((inVal & (1<<ii))!=0) ); + debug_printf("\n\r"); + + //////////////////////////////////////////////////////////// + // before a new bit stream to be sent + bitHandlerInit(); + // Send bit "1" a number of times (testing) + for ( i = 0; i < 10; i++ ) { + for ( ii = 0; ii < 8; ii++ ) + bitWaitSend( ((inVal & (1<<ii))!=0), 0 ); // try to push a bit (waiting inside, on queue full) + } + // stop consumer after last bit + bitHandlerStop(); + // time for handler to complete + while( bitHandlerRunning() ) + wait (.1); + //////////////////////////////////////////////////////////// + + debug_printf("total time (us): %d \n\r", total_time1.read_us() ); + debug_printf("nr. of switches: %d \n\r", total_switch_cnt ); + debug_printf("avg time per switch (us): %d \n\r", + total_time1.read_us()/total_switch_cnt ); + + } + +} +*/ \ No newline at end of file