Fabio Fumi
/
send_to_sharp
Renamed
bit_send.cpp
- Committer:
- ffxx68
- Date:
- 2022-03-29
- Revision:
- 5:062962db7a48
- Parent:
- 2:dff96be9617e
File content as of revision 5:062962db7a48:
#include "mbed.h" #include "bit_send.h" DigitalOut bit_out_port(D5); DigitalOut led1(LED1); // Serial pc1(USBTX,USBRX); defined in main Ticker bit_ticker; Timer total_time1; Timer bit_time; // volatile when read & write from both interrupts and main // static is to keep value between calls volatile uint8_t bit_sync_flags; volatile uint64_t bit_buffer; // a 64-bits buffer (position-masked) volatile uint64_t bit_read_mask; // bit read position volatile uint64_t bit_write_mask; // bit write position volatile uint64_t bit_last_mask; // position of last bit sent volatile uint8_t bit_repeat_count = 0; volatile uint8_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 bit_out_port = 0; // stream closure total_time1.stop(); } 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; bit_sync_flags |= BIT_SENDING; } else { // bit-0 from buffer bit_cycle_count = BIT_TICK_0_NCYCLES; bit_repeat_count = BIT_TICK_0_REPEAT; bit_sync_flags &= ~(BIT_SENDING); } 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_sync_flags & BIT_SENDING ) // the bit being sent 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 ) { bit_time.reset(); bit_time.start(); // 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 about 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 32x2ms 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 ( 100 ); // 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(); } return bit_time.read_us(); } 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 ); } } */