I have tracked the problem down to this function call and the ISR which it starts:
Code: Select all
void enableIRIn() {
// setup pulse clock timer interrupt
//Prescale /8 (16M/8 = 0.5 microseconds per tick)
// Therefore, the timer interval can range from 0.5 to 128 microseconds
// depending on the reset value (255 to 0)
TCCR1A = 0;
TCCR1B = _BV(WGM12) | _BV(CS10);
OCR1A = F_CPU * USECPERTICK / 1000000;
TCNT1 = 0;
//Timer1 Overflow Interrupt Enable
TIMSK1 = _BV(OCIE1A);
// initialize state machine variables
irparams.rcvstate = STATE_IDLE;
irparams.rawlen = 0;
// set pin modes
IRREAD_DDR &= ~(1 << IRREAD_POS);
}
Code: Select all
ISR(TIM1_COMPA_vect)
{
irparams.timer++; // One more 50us tick
if (irparams.rawlen >= RAWBUF) {
// Buffer overflow
irparams.rcvstate = STATE_STOP;
}
switch(irparams.rcvstate) {
case STATE_IDLE: // In the middle of a gap
if (bit_is_clear(IRREAD_PIN, IRREAD_POS)) {
if (irparams.timer < GAP_TICKS) {
// Not big enough to be a gap.
irparams.timer = 0;
}
else {
// gap just ended, record duration and start recording transmission
irparams.rawlen = 0;
irparams.rawbuf[irparams.rawlen++] = irparams.timer;
irparams.timer = 0;
irparams.rcvstate = STATE_MARK;
}
}
break;
case STATE_MARK: // timing MARK
if (bit_is_set(IRREAD_PIN, IRREAD_POS)) { // MARK ended, record time
irparams.rawbuf[irparams.rawlen++] = irparams.timer;
irparams.timer = 0;
irparams.rcvstate = STATE_SPACE;
}
break;
case STATE_SPACE: // timing SPACE
if (bit_is_clear(IRREAD_PIN, IRREAD_POS)) { // SPACE just ended, record it
irparams.rawbuf[irparams.rawlen++] = irparams.timer;
irparams.timer = 0;
irparams.rcvstate = STATE_MARK;
}
else { // SPACE
if (irparams.timer > GAP_TICKS) {
// big SPACE, indicates gap between codes
// Mark current code as ready for processing
// Switch to STOP
// Don't reset timer; keep counting space width
irparams.rcvstate = STATE_STOP;
}
}
break;
case STATE_STOP: // waiting, measuring gap
if (bit_is_clear(IRREAD_PIN, IRREAD_POS)) { // reset gap timer
irparams.timer = 0;
}
break;
}
}
I was presuming that perhaps the host computer was waiting too long, but then thinking about it, the InraRed ISR is triggering every 50us, while the usb polling only runs every 4ms, so in theory the IR receiver shouldn't be causing any issues. I also call usbPoll twice in the main loop.
If I clear the contents of ISR(TIM1_COMPA_vect), leaving just an empty function block then the device is recognized correctly.