#include "i2c.h"
/* TODO
- * IR decoding, connected to PCINT0
+ * IR decoding, connected to PD2
* enable/disable with switch on PCINT1
* some of the buttons multiplexed on ADC0
*/
+#define PD_IR 2
+#define PD_ENSW 3
#define EVQ_SIZE 64
uint16_t evq[EVQ_SIZE];
static int dump_count;
static int dbgmode;
+static volatile unsigned char pending;
+static volatile unsigned char enable, prev_enable;
+static volatile uint16_t ir_input;
+
static void proc_cmd(char *input);
static void printstat(void);
static void printdump(void);
int main(void)
{
- uint16_t val;
+ unsigned char pend;
/* tri-state everything and disable pullups */
DDRB = 1; /* B0: activity LED */
DDRD = 0;
PORTB = 0;
PORTC = 0;
- PORTD = 0;
+ PORTD = 1 << PD_ENSW;
+
+ /* setup external interrupts */
+ EICRA = 0x6; /* INT0 falling edge, INT1 both */
+ EIMSK = 3; /* enable INT0 and INT1 */
+
+ /* we'll use the timer 0 compare interrupt for sampling the IR input pulses
+ * we need to sample every 889us or 1124.86 Hz
+ * interrupt frequency = F_CPU / (prescaler * (1 - OCRnx))
+ * 14745600 / (64.0 * (1.0 + 204)) -> 1123.9 Hz
+ */
+ TCCR0A = 2; /* clear on compare match */
+ TCCR0B = 3; /* clock select: ioclock / 64 <- prescaler */
+ OCR0A = 192; /* count top */
+
+ /* read initial enable switch state */
+ enable = (~PIND >> PD_ENSW) & 1;
i2c_init();
for(;;) {
i2c_check_async();
+ cli();
+ pend = pending;
+ pending = 0;
+ sei();
+ if(pend & 1) {
+ printf("IR: %04x (%s)\n", (unsigned int)ir_input & 0x7fff, ir_input & 0x8000 ? "err" : "ok");
+ }
+ if(pend & 2 && enable != prev_enable) {
+ printf("enable: %d\n", enable);
+ prev_enable = enable;
+ }
+
if(have_input()) {
int c = getchar();
putchar(c);
}
/* read from queue and send over the serial port */
+ /*
+ uint16_t val;
val = 0xffff;
cli();
if(evq_wr != evq_rd) {
unsigned char ev = val >> 8;
printf("%02x: %02x\n", ev, val & 0xff);
}
+ */
}
return 0;
}
putchar('\n');
}
}
+
+static unsigned char nsamples;
+static uint32_t samples;
+
+ISR(INT0_vect)
+{
+ /* ignore interrupts while a previous input is pending */
+ if(pending & 1) return;
+
+ /* IR going low */
+ ir_input = 0;
+ nsamples = 1; /* we're starting in the middle of the first bit which should be 01 (=1) */
+ samples = 0;
+ EIMSK &= 0xfe; /* disable further interrupts while decoding IR code */
+
+ TCNT0 = 96; /* reset the counter to half the range so it'll trigger in the middle of the current pulse */
+ TIFR0 |= 1 << OCF0A; /* clear pending interrupts */
+ TIMSK0 = 1 << OCIE0A; /* enable output compare interrupt */
+
+ //PORTB ^= 1;
+}
+
+ISR(TIMER0_COMPA_vect)
+{
+ static unsigned char err;
+
+ PORTB ^= 1;
+
+ samples = (samples << 1) | (~(PIND >> PD_IR) & 1);
+ if((++nsamples & 1) == 0) {
+ if((samples & 3) == 0 || (samples & 3) == 3) {
+ /* 00 or 11 are invalid sequences, we lost sync */
+ err = 1;
+ }
+
+ /* 01->1, 10->0 */
+ ir_input = (ir_input << 1) | (samples & 1);
+ }
+
+ if(nsamples >= 28) {
+ if(err) {
+ ir_input |= 0x8000;
+ }
+ pending |= 1;
+ err = 0;
+ TIMSK0 &= ~(1 << OCIE0A); /* disable the sampling interrupt */
+ EIMSK |= 1; /* re-enable the edge-detect interrupt for the next input */
+ }
+}
+
+ISR(INT1_vect)
+{
+ enable = (~PIND >> PD_ENSW) & 1;
+ pending |= 2;
+}