// watch external clock for PWM messages // specify minimum gap to look for in us void sniff_pwm(unsigned int min) { BOOL toggle; BOOL abort= FALSE; unsigned long i, count, pulsecount= 0L, gaps[DETECT_BUFFER_SIZE], pulses[DETECT_BUFFER_SIZE]; // make sure local clock isn't running & switch to input stop_HW_clock(); COIL_MODE_READER(); READER_CLOCK_ENABLE_OFF(LOW); toggle= SNIFFER_COIL; // wait for 100 ticks to make sure we're settled toggle= SNIFFER_COIL; while(count < 100) { while(SNIFFER_COIL == toggle) // check for user abort if(get_user_abort()) return; ++count; toggle= !toggle; } // watch for gaps / pulses i= 0; GetTimer_us(RESET); while(!abort) { while(SNIFFER_COIL == toggle) // check for user abort if((abort= get_user_abort())) break; toggle= !toggle; count= GetTimer_us(RESET); // check if it was a gap if(count > min) { pulses[i]= pulsecount; gaps[i++]= count; pulsecount= 0L; } else pulsecount += count; if(i == DETECT_BUFFER_SIZE) { decode_pwm(pulses, gaps, i); i= 0; } } decode_pwm(pulses, gaps, i); }
// Reader clock ISR // also process RWD commands while we toggle clock line void __ISR(_OUTPUT_COMPARE_5_VECTOR, ipl6auto) reader_clock_tick (void) { static unsigned int count= 0; static unsigned int bcount= 0; // Clear interrupt flag mOC5ClearIntFlag(); mLED_Clock_On(); // process RWD commands (if any) switch (RWD_State) { case RWD_STATE_INACTIVE: case RWD_STATE_ACTIVE: //DEBUG_PIN_4= !DEBUG_PIN_4; break; case RWD_STATE_GO_TO_SLEEP: //DEBUG_PIN_4= !DEBUG_PIN_4; //DEBUG_PIN_4= !DEBUG_PIN_4; // initial shutdown of coil to restart tag READER_CLOCK_ENABLE_OFF(); COIL_OUT_LOW(); // time small amounts with ticks, large with uS if(RWD_Sleep_Period > MAX_TIMER5_TICKS) Delay_us(CONVERT_TICKS_TO_US(RWD_Sleep_Period)); else { WriteTimer5(0); while(GetTimer_ticks(NO_RESET) < RWD_Sleep_Period) ; } count= 0; RWD_State= RWD_STATE_WAKING; // restart clock only if we have a wake period if(RWD_Wake_Period) READER_CLOCK_ENABLE_ON(); break; case RWD_STATE_WAKING: //DEBUG_PIN_4= !DEBUG_PIN_4; // leave coil running for wakeup period if(count == RWD_Wake_Period) { count= 0; bcount = 0; if(*RWD_Command_ThisBit != '*') RWD_State= RWD_STATE_START_SEND; else RWD_State= RWD_STATE_ACTIVE; } else count++; break; case RWD_STATE_START_SEND: //DEBUG_PIN_4= !DEBUG_PIN_4; // send initial gap // stop modulation of coil and wait READER_CLOCK_ENABLE_OFF(); COIL_OUT_LOW(); count= 0; if(RWD_Barrier) RWD_State= RWD_STATE_SENDING_BARRIER_LOW; else RWD_State= RWD_STATE_SENDING_BIT_LOW; //DEBUG_PIN_4= !DEBUG_PIN_4; // restart clock //READER_CLOCK_ENABLE_ON(); break; case RWD_STATE_SENDING_BIT_HIGH: //DEBUG_PIN_4= !DEBUG_PIN_4; // clock running for bit period, then wait for gap period if((*RWD_Command_ThisBit && count == RWD_One_Period) || (!*RWD_Command_ThisBit && count == RWD_Zero_Period)) { count= 0; if(*RWD_Command_ThisBit == '*') RWD_State= RWD_STATE_POST_WAIT; else if(RWD_Barrier && bcount == 7) RWD_State= RWD_STATE_SENDING_BARRIER_LOW; else RWD_State= RWD_STATE_SENDING_BIT_LOW; READER_CLOCK_ENABLE_OFF(); COIL_OUT_LOW(); bcount++; if(bcount == 8) bcount = 0; } else count++; break; case RWD_STATE_SENDING_BIT_LOW: if((*RWD_Command_ThisBit && count == RWD_One_Gap_Period) || (!*RWD_Command_ThisBit && count == RWD_Zero_Gap_Period)) { ++RWD_Command_ThisBit; count= 0; RWD_State= RWD_STATE_SENDING_BIT_HIGH; // restart clock READER_CLOCK_ENABLE_ON(); } else count++; break; case RWD_STATE_SENDING_BARRIER_HIGH: if(count == RWD_One_Barrier_Period){ count= 0; RWD_State= RWD_STATE_SENDING_BIT_LOW; READER_CLOCK_ENABLE_OFF(); COIL_OUT_LOW(); }else count++; break; case RWD_STATE_SENDING_BARRIER_LOW: if(count == RWD_Zero_Barrier_Period){ count= 0; RWD_State= RWD_STATE_SENDING_BARRIER_HIGH; READER_CLOCK_ENABLE_ON(); }else count++; break; case RWD_STATE_POST_WAIT: //DEBUG_PIN_4= !DEBUG_PIN_4; // coil running for forced post-command wait period if(count == RWD_Post_Wait) { count= 0; RWD_State= RWD_STATE_ACTIVE; } else count++; break; default: break; } }