]> mj.ucw.cz Git - home-hw.git/commitdiff
test-display2: More IR decoding
authorMartin Mares <mj@ucw.cz>
Sat, 13 May 2023 23:07:51 +0000 (01:07 +0200)
committerMartin Mares <mj@ucw.cz>
Sat, 13 May 2023 23:07:51 +0000 (01:07 +0200)
test-display2/main.c

index 3c8049869c7abefc182d595129327af8507d7f2c..57c52d68e018fee37c39ce8374f1eb1613f3dc82 100644 (file)
@@ -203,6 +203,7 @@ static void ir_init(void)
 {
        debug_puts("IR init\n");
 
+       // TIM1 will measure pulses and spaces between them with 1μs resolution
        timer_set_prescaler(TIM1, 71);          // 72 MHz / 72 = 1 MHz
        timer_set_mode(TIM1, TIM_CR1_CKD_CK_INT, TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP);
        timer_set_period(TIM1, 65535);
@@ -217,7 +218,7 @@ static void ir_init(void)
        timer_ic_set_input(TIM1, TIM_IC2, TIM_IC_IN_TI1);
        timer_set_oc_polarity_high(TIM1, TIM_OC2);
 
-       // CH3 will trigger on a break longer than 50 ms
+       // OC3 will trigger on a break longer than 50 ms
        timer_set_oc_mode(TIM1, TIM_OC3, TIM_OCM_ACTIVE);
        timer_set_oc_value(TIM1, TIM_OC3, 30000);
 
@@ -237,10 +238,33 @@ static void ir_init(void)
        timer_enable_counter(TIM1);
 }
 
-#define IR_MAX_PULSES 64
-static u16 ir_pulses[IR_MAX_PULSES];
-static uint ir_num_pulses;
+// Circular queue of pulse durations
+#define IR_MAX_PULSES 32
+static u32 ir_pulses[IR_MAX_PULSES];   // Top 16 bits = mark, bottom 16 bits = space
 static u16 ir_last_pulse;
+static uint ir_pulses_rx, ir_pulses_tx;
+
+#define IR_INF 0xffff
+
+#define IR_MARK(x) (uint)((x) >> 16)
+#define IR_SPACE(x) (uint)((x) & 0xffff)
+
+static inline bool between(uint x, uint min, uint max)
+{
+       return x >= min && x <= max;
+}
+
+static void ir_record_pulse(uint mark, uint space)
+{
+       uint i = ir_pulses_tx;
+       ir_pulses_tx = (i + 1) % IR_MAX_PULSES;
+       if (ir_pulses_tx != ir_pulses_rx) {
+               ir_pulses[i] = (mark << 16) | space;
+       } else {
+               // Overflow detected
+               ir_pulses[i] = (IR_INF << 16) | IR_INF;
+       }
+}
 
 void tim1_cc_isr(void)
 {
@@ -248,8 +272,7 @@ void tim1_cc_isr(void)
                TIM_SR(TIM1) &= ~TIM_SR_CC1IF;
                u16 now = TIM_CCR1(TIM1);
                if (ir_last_pulse) {
-                       ir_pulses[ir_num_pulses++] = ir_last_pulse;
-                       ir_pulses[ir_num_pulses++] = now - ir_last_pulse;
+                       ir_record_pulse(ir_last_pulse, now - ir_last_pulse);
                        ir_last_pulse = 0;
                }
        }
@@ -260,10 +283,80 @@ void tim1_cc_isr(void)
        if (TIM_SR(TIM1) & TIM_SR_CC3IF) {
                TIM_SR(TIM1) &= ~TIM_SR_CC3IF;
                if (ir_last_pulse) {
-                       ir_pulses[ir_num_pulses++] = ir_last_pulse;
-                       ir_pulses[ir_num_pulses++] = 0xffff;
+                       ir_record_pulse(ir_last_pulse, IR_INF);
+                       ir_last_pulse = 0;
+               }
+       }
+}
+
+static u32 ir_get_pulse(void)
+{
+       u32 out = 0;
+
+       cm_disable_interrupts();
+       if (ir_pulses_rx != ir_pulses_tx) {
+               out = ir_pulses[ir_pulses_rx];
+               ir_pulses_rx = (ir_pulses_rx + 1) % IR_MAX_PULSES;
+       }
+       cm_enable_interrupts();
+       return out;
+}
+
+// Decoder for Onkyo RC-748S
+
+static void ir_decode(void)
+{
+       u32 pulse = ir_get_pulse();
+       if (!pulse)
+               return;
+
+       uint mark = IR_MARK(pulse);
+       uint space = IR_SPACE(pulse);
+
+#ifdef IR_TEST
+       debug_printf("IR: %d %d\n", mark, space);
+       return;
+#endif
+
+       static u16 ir_bits;
+       static u32 ir_code;
+#define IR_ERR 0xff
+
+       debug_printf("IR(%d): %d %d\n", ir_bits, mark, space);
+
+       if (space == IR_INF) {
+               ir_bits = 0;
+       } else if (ir_bits == IR_ERR) {
+               // Error state
+       } else if (ir_bits == 0) {
+               // Start?
+               if (between(mark, 8900, 9200)) {
+                       if (between(space, 4200, 4600)) {
+                               ir_bits = 1;
+                               ir_code = 0;
+                       } else if (between(space, 2000, 2300)) {
+                               debug_printf("==> REP\n");
+                               ir_bits = IR_ERR;
+                       }
+               }
+       } else {
+               if (between(mark, 500, 700)) {
+                       ir_bits++;
+                       if (between(space, 400, 700)) {
+                               // 0
+                       } else if (between(space, 1500, 1800)) {
+                               // 1
+                               ir_code |= 1U << (33 - ir_bits);
+                       } else {
+                               ir_bits = IR_ERR;
+                       }
+                       if (ir_bits == 33) {
+                               debug_printf("==> %08x\n", (uint)ir_code);
+                               ir_bits = IR_ERR;
+                       }
+               } else {
+                       ir_bits = IR_ERR;
                }
-               ir_last_pulse = 0;
        }
 }
 
@@ -492,6 +585,8 @@ int main(void)
                        display_test();
                }
 
+               ir_decode();
+
                if (usb_event_pending) {
                        usbd_poll(usbd_dev);
                        usb_event_pending = 0;
@@ -499,22 +594,6 @@ int main(void)
                        nvic_enable_irq(NVIC_USB_LP_CAN_RX0_IRQ);
                }
 
-               static u16 pulses[IR_MAX_PULSES];
-               uint np;
-
-               cm_disable_interrupts();
-               np = ir_num_pulses;
-               memcpy(pulses, ir_pulses, 2*np);
-               ir_num_pulses = 0;
-               cm_enable_interrupts();
-
-               if (np) {
-                       debug_printf("IR:");
-                       for (uint i=0; i < np; i++)
-                               debug_printf(" %u", pulses[i]);
-                       debug_putc('\n');
-               }
-
                wait_for_interrupt();
        }