Renamed

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers bit_send.cpp Source File

bit_send.cpp

00001 #include "mbed.h" 
00002 #include "bit_send.h"
00003 
00004 DigitalOut bit_out_port(D5);
00005 DigitalOut led1(LED1);
00006 // Serial pc1(USBTX,USBRX); defined in main
00007 Ticker bit_ticker;
00008 Timer total_time1;
00009 Timer bit_time;
00010 
00011 // volatile when read & write from both interrupts and main
00012 // static is to keep value between calls
00013 volatile uint8_t   bit_sync_flags; 
00014 volatile uint64_t  bit_buffer; // a 64-bits buffer (position-masked)
00015 volatile uint64_t  bit_read_mask; //  bit read position  
00016 volatile uint64_t  bit_write_mask; // bit write position  
00017 volatile uint64_t  bit_last_mask; //  position of last bit sent 
00018 
00019 volatile uint8_t   bit_repeat_count = 0;
00020 volatile uint8_t   bit_cycle_count = 0;
00021 
00022 volatile uint32_t  total_switch_cnt = 0;
00023 
00024 // To be called before a new stream is sent
00025 void bitHandlerInit( void ) {
00026 
00027         debug_printf("bitHandlerInit\r\n") ;
00028        
00029         // timing ticker counters
00030         bit_repeat_count = 0;
00031         bit_cycle_count = 0;
00032 
00033         bit_sync_flags = 0; // clear all (set when needed)
00034         
00035         // buffer initial positions
00036         bit_read_mask = 1; 
00037         bit_write_mask = 1; 
00038         bit_buffer = 0;
00039 
00040         // start with a LOW level on output
00041         bit_out_port = 0; 
00042         
00043         // debugging counters
00044         total_switch_cnt = 0;
00045         
00046 }
00047 
00048 // Called after last bit to be sent has been sent
00049 void bitHandlerStop ( void ) {
00050     
00051     bit_sync_flags |= BIT_LAST_SENT; // signal for no more bits to send
00052     bit_last_mask = bit_write_mask; // for consumer, to stop here
00053     // NOTE - ticker will be disabled in the handler itself
00054     // as it has to wait for last bit to be processed, first
00055 
00056 }
00057            
00058 // A bit (x) is composed of BIT_TICK_x_NCYCLES of alternating HIGH and LOW levels,
00059 // with each level interval lasting BIT_TICK_x_REPEAT ticker repetitions.
00060 // Example for bit "0" -- BIT_TICK_0_NCYCLES = 8, BIT_TICK_0_REPEAT = 2:
00061 //           ___     ___     ___     ___   
00062 // out     _|   |___|   |___|   |___|   |_
00063 // cycle    7   6   5   4   3   2   1   0 ...
00064 // repeat   1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 ...
00065 //
00066 // the bit-handler bitTickHandler(), called every BIT_TICK_DELAY (Ticker object)
00067 // will pull a bit from the circular buffer ( bit_buffer ), 
00068 // which is populated from writer bitWaitSend().
00069 // Writer takes care of synchronization of read and write buffer pointers,
00070 // assuming writer is FASTER than consumer handler
00071 void bitTickHandler ( void )
00072 {
00073 
00074     if ( bit_cycle_count == 0 ) {
00075         // New bit to be pulled off the buffer - restart counters
00076         if ( bit_sync_flags & BIT_LAST_PROCESSING ) {
00077             // stop AFTER last bit has been pulled (see below)
00078             bit_ticker.detach ();
00079             led1 = 0; // ticker stopped
00080             bit_out_port = 0; // stream closure
00081             total_time1.stop();
00082         } else {
00083             // update read position (shift left mask)
00084             // and reset tick and cycle counters
00085             if ( ( bit_read_mask = bit_read_mask<<1 ) == 0 ) 
00086                 bit_read_mask = 1; // circular buffer
00087             if ( bit_buffer & bit_read_mask ) {
00088                 // bit-1 from buffer
00089                 bit_cycle_count = BIT_TICK_1_NCYCLES;
00090                 bit_repeat_count = BIT_TICK_1_REPEAT;
00091                 bit_sync_flags |= BIT_SENDING;
00092             } else {
00093                 // bit-0 from buffer
00094                 bit_cycle_count = BIT_TICK_0_NCYCLES;
00095                 bit_repeat_count = BIT_TICK_0_REPEAT;
00096                 bit_sync_flags &= ~(BIT_SENDING);
00097             }
00098             if ( ( bit_sync_flags & BIT_LAST_SENT ) &&
00099                  ( bit_read_mask == bit_last_mask ) ) {
00100                 // set BEFORE last bit being processed
00101                 bit_sync_flags |= BIT_LAST_PROCESSING;
00102             }
00103         }
00104     }
00105 
00106     if ( --bit_repeat_count == 0 ) {
00107         // toggle output port level
00108         total_switch_cnt += 1;
00109         bit_out_port = !bit_out_port;
00110         if ( total_switch_cnt & 0x10 ) led1 != led1; // show activity
00111         // a ticker-repeat cycle has completed
00112         bit_cycle_count --;
00113         if ( bit_sync_flags & BIT_SENDING ) // the bit being sent
00114             bit_repeat_count = BIT_TICK_1_REPEAT;
00115         else
00116             bit_repeat_count = BIT_TICK_0_REPEAT;
00117     }
00118     
00119 }
00120 
00121 // Push a bit to the buffer.
00122 // Waiting in an idle loop, though not 100% busy (wait),
00123 // as thread signals (Mbed-RTOS) are not available on the L053R8
00124 int bitWaitSend ( uint8_t bit_value, uint8_t invert ) {
00125 
00126     bit_time.reset();
00127     bit_time.start();
00128     // Both bit_read_position and bit_write_position cycle through the buffer
00129     // When they are the same, put sender on hold, for consumer to complete.
00130     // Polling regularly, then writing a new bit to buffer
00131     // when pointers are different (the slower handler has moved bit_read_mask).
00132     // Bit handler takes about 2ms to spool a single bit:
00133     //  ( BIT_TICK_x_CYCLE+1 ) * BIT_TICK_x_REPEAT * BIT_TICK_DELAY (us)
00134     // hence, as soon as writer can write new data, it has 32x2ms to write 
00135     // new bits before filling again the buffer.
00136     // Polling has to be frequent enough not to let consumer pull wrong bits...
00137     while ( ( bit_write_mask == bit_read_mask ) && ( bit_sync_flags & BIT_FIRST_SENT ) )
00138        wait_us ( 100 );
00139 
00140     // update buffer write position (shift left mask)
00141     if ( ( bit_write_mask = bit_write_mask<<1 ) == 0 )
00142         bit_write_mask = 1; // it's a circular buffer
00143 
00144     // push this bit to the buffer
00145     if ( (bit_value & 0x01) ^ (invert & 0x01) ) // ignore positions other than 1
00146         bit_buffer |= (bit_write_mask); // set
00147     else
00148         bit_buffer &= ~(bit_write_mask); // clear
00149 
00150     // on first bit only, start consumer too
00151     if ( !(bit_sync_flags & BIT_FIRST_SENT) ) {
00152         bit_ticker.attach_us ( &bitTickHandler, BIT_TICK_DELAY ); // start ticker
00153         bit_sync_flags |= BIT_FIRST_SENT; // first bit gone
00154         led1 = 1; // debugging purpose (ticker on)
00155         total_time1.reset();
00156         total_time1.start();
00157     }
00158     
00159     return bit_time.read_us();
00160 
00161 }
00162 
00163 bool bitHandlerRunning( void ) {
00164     
00165     return ( !(bit_sync_flags & BIT_LAST_PROCESSING) ) ;
00166     
00167 }
00168 
00169 ///////////////////////////////////////////////////////////////////////////////
00170 /* MAIN USED FOR A STANDALONE TEST BED
00171 int main()
00172 {
00173 
00174     int i, ii;
00175     char inVal;
00176 
00177     // flashing led1 on startup
00178     for (i=0; i<5; i+=1) {
00179         wait (0.1);
00180         led1 = !led1;
00181     }
00182     led1 = 0;
00183     
00184     pc1.baud(57600);
00185 
00186     // welcome message 
00187     pc1.printf("\n\r ** MBED ** test bit send ** \n\r");
00188     fflush(stdout);
00189 
00190     // main loop
00191     while(true) {
00192        
00193         pc1.printf("Hit a key ... \n\r");
00194         fflush(stdout);
00195         inVal=pc1.getc(); // wait for a key press (over serial)
00196 
00197         debug_printf("%.2x ", inVal);
00198         for ( ii = 0; ii < 8; ii++ )
00199             debug_printf( "%d", ((inVal & (1<<ii))!=0) );
00200         debug_printf("\n\r");
00201         
00202         ////////////////////////////////////////////////////////////
00203         // before a new bit stream to be sent
00204         bitHandlerInit();
00205         // Send bit "1" a number of times (testing)
00206         for ( i = 0; i < 10; i++ ) {
00207           for ( ii = 0; ii < 8; ii++ )
00208             bitWaitSend( ((inVal & (1<<ii))!=0), 0 ); // try to push a bit (waiting inside, on queue full)
00209         }
00210         // stop consumer after last bit
00211         bitHandlerStop();
00212         // time for handler to complete
00213         while( bitHandlerRunning() ) 
00214             wait (.1); 
00215         ////////////////////////////////////////////////////////////
00216 
00217         debug_printf("total time (us): %d \n\r", total_time1.read_us() );
00218         debug_printf("nr. of switches: %d \n\r", total_switch_cnt );
00219         debug_printf("avg time per switch (us): %d \n\r", 
00220             total_time1.read_us()/total_switch_cnt );
00221 
00222     }
00223 
00224 }
00225 */