Renamed

Dependencies:   mbed

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