From c54477ec6d09b94fd682dfe75aadc9a574a80791 Mon Sep 17 00:00:00 2001 From: Martin Mares Date: Sun, 14 May 2023 01:07:51 +0200 Subject: [PATCH] test-display2: More IR decoding --- test-display2/main.c | 129 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 104 insertions(+), 25 deletions(-) diff --git a/test-display2/main.c b/test-display2/main.c index 3c80498..57c52d6 100644 --- a/test-display2/main.c +++ b/test-display2/main.c @@ -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(); } -- 2.39.2