X-Git-Url: http://mj.ucw.cz/gitweb/?a=blobdiff_plain;f=ir-send%2Ftest.c;h=defdd22d9427271da1cd3360c4ace61ef318601d;hb=228f98a7bea12a3cc18aab18f50951d3256bc5fe;hp=db52d8cc87b70fca8fbb1f7dc5ae6d4418132dfa;hpb=7e8d09b9e8bac83964dc8ddffa084cbc025d60cb;p=home-hw.git diff --git a/ir-send/test.c b/ir-send/test.c index db52d8c..defdd22 100644 --- a/ir-send/test.c +++ b/ir-send/test.c @@ -8,6 +8,8 @@ #include #include +#include + static void clock_setup(void) { rcc_clock_setup_in_hse_8mhz_out_72mhz(); @@ -16,14 +18,16 @@ static void clock_setup(void) rcc_periph_clock_enable(RCC_GPIOB); rcc_periph_clock_enable(RCC_GPIOC); rcc_periph_clock_enable(RCC_USART1); - rcc_periph_clock_enable(RCC_TIM2); + rcc_periph_clock_enable(RCC_TIM1); + rcc_periph_clock_enable(RCC_TIM4); rcc_periph_clock_enable(RCC_AFIO); rcc_periph_reset_pulse(RST_GPIOA); rcc_periph_reset_pulse(RST_GPIOB); rcc_periph_reset_pulse(RST_GPIOC); rcc_periph_reset_pulse(RST_USART1); - rcc_periph_reset_pulse(RST_TIM2); + rcc_periph_reset_pulse(RST_TIM1); + rcc_periph_reset_pulse(RST_TIM4); } static void gpio_setup(void) @@ -32,9 +36,18 @@ static void gpio_setup(void) gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO13); gpio_clear(GPIOC, GPIO13); - // Remap TIM2 + // Switch JTAG off to free up pins + gpio_primary_remap(AFIO_MAPR_SWJ_CFG_JTAG_OFF_SW_ON, 0); // gpio_primary_remap(AFIO_MAPR_SWJ_CFG_JTAG_OFF_SW_ON, AFIO_MAPR_TIM2_REMAP_FULL_REMAP); - AFIO_MAPR = 0x04000300; + + // TIM2_CH3 on PB3 (remapped) + // gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO10); + + // TIM4_CH1 on PB6: PWM for fan control + gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO6); + + // TIM4_CH2 on PB7: PWM for IR LED + gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO7); } static volatile u32 ms_ticks; @@ -51,7 +64,7 @@ static void tick_setup(void) systick_interrupt_enable(); } -static void delay_ms(uint ms) +static void UNUSED delay_ms(uint ms) { u32 start_ticks = ms_ticks; while (ms_ticks - start_ticks < ms) @@ -61,6 +74,7 @@ static void delay_ms(uint ms) static void usart_setup(void) { gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO_USART1_TX); + gpio_set_mode(GPIOA, GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, GPIO_USART1_RX); usart_set_baudrate(USART1, 115200); usart_set_databits(USART1, 8); @@ -72,40 +86,167 @@ static void usart_setup(void) usart_enable(USART1); } +enum rc_keys { + RC_AUTO, + RC_TEMP_UP, + RC_FUNC, + RC_HI, + RC_TIMER, + RC_MID, + RC_TEMP_DOWN, + RC_SLEEP, + RC_LOW, + RC_POWER, + RC_XXX_A, + RC_XXX_B, + RC_MAX +}; + +static const char * const rc_patterns[RC_MAX] = { + [RC_AUTO] = "^#*A*A*A*A*A*A*A*B*B*B*B*B*B*B*B*A*A*B*B*A*B*A*A*B*B*A*A*B*A*B*B*A*", + [RC_TEMP_UP] = "^#*A*A*A*A*A*A*A*B*B*B*B*B*B*B*B*A*A*A*B*A*B*A*A*B*B*B*A*B*A*B*B*A*", + [RC_FUNC] = "^#*A*A*A*A*A*A*A*B*B*B*B*B*B*B*B*A*B*A*B*B*B*A*A*B*A*B*A*A*A*B*B*A*", + [RC_HI] = "^#*A*A*A*A*A*A*A*B*B*B*B*B*B*B*B*A*B*A*A*B*B*A*A*B*A*B*B*A*A*B*B*A*", + [RC_TIMER] = "^#*A*A*A*A*A*A*A*B*B*B*B*B*B*B*B*A*A*B*B*B*B*A*A*B*B*A*A*A*A*B*B*A*", + [RC_MID] = "^#*A*A*A*A*A*A*A*B*B*B*B*B*B*B*B*A*B*B*A*B*B*A*A*B*A*A*B*A*A*B*B*A*", + [RC_TEMP_DOWN] = "^#*A*A*A*A*A*A*A*B*B*B*B*B*B*B*B*A*B*A*B*A*B*A*A*B*A*B*A*B*A*B*B*A*", + [RC_SLEEP] = "^#*A*A*A*A*A*A*A*B*B*B*B*B*B*B*B*A*B*B*B*B*B*A*A*B*A*A*A*A*A*B*B*A*", + [RC_LOW] = "^#*A*A*A*A*A*A*A*B*B*B*B*B*B*B*B*A*A*B*A*B*B*A*A*B*B*A*B*A*A*B*B*A*", + [RC_POWER] = "^#*A*A*A*A*A*A*A*B*B*B*B*B*B*B*B*A*A*A*B*B*B*A*A*B*B*B*A*A*A*B*B*A*", + [RC_XXX_A] = "^#*A*B*A*A*B*A*B*B*A*A*B*A*A*A*A*A*A*B*B*B*B*A*A*A*B*A*A*A*A*B*B*B*", + [RC_XXX_B] = "^#*A*B*A*A*B*A*B*B*A*A*B*A*A*A*A*A*B*B*B*B*B*A*A*A*A*A*A*A*A*B*B*B*", +}; + +// FIXME +static const char rc_keys[] = "aufhtmdslp12"; + +// TIM4 will run on CPU clock, it will overflow with frequency 38 kHz (IR modulation frequency) +#define T4_CYCLE ((CPU_CLOCK_MHZ * 1000000 + 37999) / 38000) + +static void rc_setup(void) +{ + timer_set_prescaler(TIM4, 0); + timer_set_mode(TIM4, TIM_CR1_CKD_CK_INT, TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP); + timer_disable_preload(TIM4); + timer_set_period(TIM4, T4_CYCLE - 1); + + // 50% PWM for the IR LED + timer_set_oc_mode(TIM4, TIM_OC2, TIM_OCM_PWM1); + timer_set_oc_value(TIM4, TIM_OC2, T4_CYCLE / 2); + timer_set_oc_polarity_high(TIM4, TIM_OC2); + timer_enable_oc_output(TIM4, TIM_OC2); + + // PWM for controlling fan + timer_set_oc_mode(TIM4, TIM_OC1, TIM_OCM_PWM1); + timer_set_oc_value(TIM4, TIM_OC1, T4_CYCLE / 4); + timer_set_oc_polarity_high(TIM4, TIM_OC1); + timer_enable_oc_output(TIM4, TIM_OC1); + + timer_enable_counter(TIM4); + + // TIM1 runs at 1 MHz and it is used for timing of RC pulses + timer_set_prescaler(TIM1, CPU_CLOCK_MHZ - 1); + timer_set_mode(TIM1, TIM_CR1_CKD_CK_INT, TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP); + timer_update_on_overflow(TIM1); + timer_disable_preload(TIM1); + timer_one_shot_mode(TIM1); + timer_enable_irq(TIM1, TIM_DIER_UIE); + nvic_enable_irq(NVIC_TIM1_UP_IRQ); +} + +static const char *rc_pattern_pos; + +void tim1_up_isr(void) +{ + if (TIM_SR(TIM1) & TIM_SR_UIF) { + TIM_SR(TIM1) &= ~TIM_SR_UIF; + + if (!rc_pattern_pos) // Just to be sure + return; + + bool val; // 1=pulse, 0=break + uint duration; // in μs + + switch (*rc_pattern_pos++) { + case '^': + val = 1; + duration = 9032; + break; + case '#': + val = 0; + duration = 4457; + break; + case '*': + val = 1; + duration = 619; + break; + case 'A': + val = 0; + duration = 514; + break; + case 'B': + val = 0; + duration = 1617; + break; + default: + // End of transmission + gpio_set(GPIOC, GPIO13); // FIXME + rc_pattern_pos = NULL; + val = 0; + duration = 10000; + } + + if (val) + timer_set_oc_mode(TIM4, TIM_OC2, TIM_OCM_PWM1); + else + timer_set_oc_mode(TIM4, TIM_OC2, TIM_OCM_FORCE_HIGH); + + timer_set_period(TIM1, duration - 1); + timer_generate_event(TIM1, TIM_EGR_UG); + timer_enable_counter(TIM1); + } +} + +static void rc_send(uint key) +{ + rc_pattern_pos = rc_patterns[key]; + + gpio_clear(GPIOC, GPIO13); + + timer_set_period(TIM1, 1); + timer_generate_event(TIM1, TIM_EGR_UG); + timer_enable_counter(TIM1); +} + int main(void) { clock_setup(); gpio_setup(); tick_setup(); usart_setup(); + rc_setup(); - // cm_enable_interrupts(); - debug_puts("Hello!\n"); - -#if 1 - timer_set_prescaler(TIM2, 3); - timer_set_mode(TIM2, TIM_CR1_CKD_CK_INT, TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP); - timer_disable_preload(TIM2); - timer_set_period(TIM2, 65535); - timer_set_oc_mode(TIM2, TIM_OC3, TIM_OCM_PWM1); - timer_set_oc_value(TIM2, TIM_OC3, 32768); - timer_set_oc_polarity_high(TIM2, TIM_OC3); - timer_enable_counter(TIM2); - timer_enable_oc_output(TIM2, TIM_OC3); -#endif - - gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO10); - // gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO10); - gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO15); + debug_puts("Hello world!\n"); + gpio_set(GPIOC, GPIO13); for (;;) { +#if 0 gpio_toggle(GPIOC, GPIO13); - delay_ms(20); - gpio_toggle(GPIOA, GPIO15); - debug_putc('.'); - timer_set_oc_mode(TIM2, TIM_OC3, TIM_OCM_FORCE_LOW); - delay_ms(20); - timer_set_oc_mode(TIM2, TIM_OC3, TIM_OCM_FORCE_HIGH); + delay_ms(1); + timer_set_oc_mode(TIM4, TIM_OC2, TIM_OCM_FORCE_HIGH); + gpio_toggle(GPIOC, GPIO13); + delay_ms(1); + timer_set_oc_mode(TIM4, TIM_OC2, TIM_OCM_PWM1); +#else + if (usart_get_flag(USART1, USART_SR_RXNE)) { + uint ch = usart_recv(USART1); + const char *key = strchr(rc_keys, ch); + if (key) { + debug_putc(ch); + rc_send(key - rc_keys); + } + } +#endif } return 0;