1 /*---------------------------------------------------------------------------------------------------------------------------------------------------
2 * irmp-main-stm32.c - demo main module to test IRMP decoder on STM32
4 * Copyright (c) 2009-2016 Frank Meyer - frank(at)fli4l.de
6 * $Id: irmp-main-stm32.c,v 1.2 2016/01/12 21:15:16 fm Exp $
8 * This demo module is runnable on STM32
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *---------------------------------------------------------------------------------------------------------------------------------------------------
21 #include <libopencm3/stm32/rcc.h>
22 #include <libopencm3/stm32/gpio.h>
25 #ifndef USE_OPENCM3_API
26 #define USE_OPENCM3_API 1
29 #ifndef DEBUG_IRMP_TIMER_INT
30 #define DEBUG_IRMP_TIMER_INT 0
33 static void setup_clock_and_gpios(void)
36 /* Default clock is 8MHz HSI */
37 //rcc_clock_setup_in_hse_8mhz_out_24mhz();
38 rcc_clock_setup_in_hse_8mhz_out_72mhz();
41 /* Only the on board led is configured here */
43 rcc_periph_clock_enable(RCC_LED_PORT
);
45 /* Set GPIO13 (in GPIO port C) to 'output push-pull'. */
47 // GPIOC_CRH = (GPIO_CNF_OUTPUT_PUSHPULL << (((12 - 8) * 4) + 2));
48 // GPIOC_CRH |= (GPIO_MODE_OUTPUT_2_MHZ << ((12 - 8) * 4));
49 /* Using API functions: */
50 gpio_set(LED_PORT
, LED_PIN
); /* set output register high (led off) */
51 gpio_set_mode(LED_PORT
, GPIO_MODE_OUTPUT_2_MHZ
,
52 GPIO_CNF_OUTPUT_PUSHPULL
, LED_PIN
);
55 /*--------------------------------------------------------------------------*/
57 /*--------------------------------------------------------------------------*/
59 #define TIM_IRMP_CR1 TIM_CR1(TIM_IRMP)
60 #define TIM_IRMP_DIER TIM_DIER(TIM_IRMP)
61 #define TIM_IRMP_SR TIM_SR(TIM_IRMP)
62 #define TIM_IRMP_ARR TIM_ARR(TIM_IRMP)
63 #define RCC_TIM_IRMP CONCAT(RCC_TIM, IRMP_TIMER)
64 #define NVIC_TIM_IRMP_IRQ CONCAT(CONCAT(NVIC_TIM, IRMP_TIMER), _IRQ)
65 #define IRMP_TIMER_ISR CONCAT(CONCAT(tim, IRMP_TIMER), _isr)
68 uint32_t timer_internal_clock_get(uint32_t timer_peripheral
)
70 uint32_t timer_frequency
;
73 /* Get preripheral bus frequency and prescaler mask */
74 if (timer_peripheral
== TIM1
|| timer_peripheral
== TIM8
) {
75 /* Advanced timers TIM1 and TIM8 are on APB2 */
76 ppre
= RCC_CFGR_PPRE2
;
77 timer_frequency
= rcc_apb2_frequency
;
79 /* Other timers are on APB1 */
80 ppre
= RCC_CFGR_PPRE1
;
81 timer_frequency
= rcc_apb1_frequency
;
83 /* Timer clock is doubled, if the APB prescaler is greater than 1 */
84 if ((RCC_CFGR
& ppre
) != 0)
87 return timer_frequency
;
90 void irmp_timer_init (void)
92 #if DEBUG_IRMP_TIMER_INT
93 /* Output pin for debugging */
94 rcc_periph_clock_enable(RCC_GPIOA
);
95 gpio_set_mode(GPIOA
, GPIO_MODE_OUTPUT_2_MHZ
,
96 GPIO_CNF_OUTPUT_PUSHPULL
, GPIO2
);
98 /* Enable timer clock. */
99 rcc_periph_clock_enable(RCC_TIM_IRMP
);
100 nvic_set_priority(NVIC_TIM_IRMP_IRQ
, 4*16);
101 nvic_enable_irq(NVIC_TIM_IRMP_IRQ
);
103 #if USE_OPENCM3_API /* Using API functions: */
105 /* Timer global mode:
109 * (These are actually default values after reset, so this call
110 * is strictly unnecessary, but demos the api for alternative settings)
112 timer_set_mode(TIM_IRMP
, TIM_CR1_CKD_CK_INT
,
113 TIM_CR1_CMS_EDGE
, TIM_CR1_DIR_UP
);
114 timer_set_period(TIM_IRMP
, timer_internal_clock_get(TIM_IRMP
) / F_INTERRUPTS
);
115 /* Enable Channel 1 compare interrupt to recalculate compare values */
116 timer_enable_irq(TIM_IRMP
, TIM_DIER_UIE
);
117 /* Counter enable. */
118 timer_enable_counter(TIM_IRMP
);
122 TIM_IRMP_CR1
= TIM_CR1_CKD_CK_INT
| TIM_CR1_CMS_EDGE
| TIM_CR1_DIR_UP
;
123 TIM_IRMP_ARR
= timer_internal_clock_get(TIM_IRMP
) / F_INTERRUPTS
;
125 /* Enable Timer interrupt and timer */
126 TIM_IRMP_DIER
= TIM_DIER_UIE
;
127 TIM_IRMP_CR1
|= TIM_CR1_CEN
;
132 void IRMP_TIMER_ISR(void)
134 #if DEBUG_IRMP_TIMER_INT
135 # if USE_OPENCM3_API /* Using API functions: */
137 gpio_clear(GPIOA
, GPIO2
);
138 /* Clear update interrupt flag. */
139 timer_clear_flag(TIM_IRMP
, TIM_SR_UIF
);
140 # else /* Manually */
141 GPIO_BRR(GPIOA
) = GPIO2
;
144 /* Clear update interrupt flag. */
145 TIM_IRMP_SR
= ~TIM_SR_UIF
;
147 (void) irmp_ISR(); // call irmp ISR
149 // call other timer interrupt routines...
151 #if DEBUG_IRMP_TIMER_INT
152 # if USE_OPENCM3_API /* Using API functions: */
153 gpio_set(GPIOA
, GPIO2
);
154 # else /* Manually */
155 GPIO_BSRR(GPIOA
) = GPIO2
;
160 /*--------------------------------------------------------------------------*/
162 int irmp_protocol_is_supported(int proto
)
164 #if IRMP_SUPPORT_SIRCS_PROTOCOL
165 if (proto
== IRMP_SIRCS_PROTOCOL
) return 1;
167 #if IRMP_SUPPORT_NEC_PROTOCOL
168 if (proto
== IRMP_NEC_PROTOCOL
) return 1;
170 #if IRMP_SUPPORT_SAMSUNG_PROTOCOL
171 if (proto
== IRMP_SAMSUNG_PROTOCOL
) return 1;
173 #if IRMP_SUPPORT_KASEIKYO_PROTOCOL
174 if (proto
== IRMP_KASEIKYO_PROTOCOL
) return 1;
176 #if IRMP_SUPPORT_JVC_PROTOCOL
177 if (proto
== IRMP_JVC_PROTOCOL
) return 1;
179 #if IRMP_SUPPORT_NEC16_PROTOCOL
180 if (proto
== IRMP_NEC16_PROTOCOL
) return 1;
182 #if IRMP_SUPPORT_NEC42_PROTOCOL
183 if (proto
== IRMP_NEC42_PROTOCOL
) return 1;
185 #if IRMP_SUPPORT_MATSUSHITA_PROTOCOL
186 if (proto
== IRMP_MATSUSHITA_PROTOCOL
) return 1;
188 #if IRMP_SUPPORT_DENON_PROTOCOL
189 if (proto
== IRMP_DENON_PROTOCOL
) return 1;
191 #if IRMP_SUPPORT_RC5_PROTOCOL
192 if (proto
== IRMP_RC5_PROTOCOL
) return 1;
194 #if IRMP_SUPPORT_RC6_PROTOCOL
195 if (proto
== IRMP_RC6_PROTOCOL
) return 1;
197 #if IRMP_SUPPORT_IR60_PROTOCOL
198 if (proto
== IRMP_IR60_PROTOCOL
) return 1;
200 #if IRMP_SUPPORT_GRUNDIG_PROTOCOL
201 if (proto
== IRMP_GRUNDIG_PROTOCOL
) return 1;
203 #if IRMP_SUPPORT_SIEMENS_PROTOCOL
204 if (proto
== IRMP_SIEMENS_PROTOCOL
) return 1;
206 #if IRMP_SUPPORT_NOKIA_PROTOCOL
207 if (proto
== IRMP_NOKIA_PROTOCOL
) return 1;
209 #if IRMP_SUPPORT_BOSE_PROTOCOL
210 if (proto
== IRMP_BOSE_PROTOCOL
) return 1;
212 #if IRMP_SUPPORT_KATHREIN_PROTOCOL
213 if (proto
== IRMP_KATHREIN_PROTOCOL
) return 1;
215 #if IRMP_SUPPORT_NUBERT_PROTOCOL
216 if (proto
== IRMP_NUBERT_PROTOCOL
) return 1;
218 #if IRMP_SUPPORT_FAN_PROTOCOL
219 if (proto
== IRMP_FAN_PROTOCOL
) return 1;
221 #if IRMP_SUPPORT_SPEAKER_PROTOCOL
222 if (proto
== IRMP_SPEAKER_PROTOCOL
) return 1;
224 #if IRMP_SUPPORT_BANG_OLUFSEN_PROTOCOL
225 if (proto
== IRMP_BANG_OLUFSEN_PROTOCOL
) return 1;
227 #if IRMP_SUPPORT_RECS80_PROTOCOL
228 if (proto
== IRMP_RECS80_PROTOCOL
) return 1;
230 #if IRMP_SUPPORT_RECS80EXT_PROTOCOL
231 if (proto
== IRMP_RECS80EXT_PROTOCOL
) return 1;
233 #if IRMP_SUPPORT_THOMSON_PROTOCOL
234 if (proto
== IRMP_THOMSON_PROTOCOL
) return 1;
236 #if IRMP_SUPPORT_NIKON_PROTOCOL
237 if (proto
== IRMP_NIKON_PROTOCOL
) return 1;
239 #if IRMP_SUPPORT_NETBOX_PROTOCOL
240 if (proto
== IRMP_NETBOX_PROTOCOL
) return 1;
242 #if IRMP_SUPPORT_ORTEK_PROTOCOL
243 if (proto
== IRMP_ORTEK_PROTOCOL
) return 1;
245 #if IRMP_SUPPORT_TELEFUNKEN_PROTOCOL
246 if (proto
== IRMP_TELEFUNKEN_PROTOCOL
) return 1;
248 #if IRMP_SUPPORT_FDC_PROTOCOL
249 if (proto
== IRMP_FDC_PROTOCOL
) return 1;
251 #if IRMP_SUPPORT_RCCAR_PROTOCOL
252 if (proto
== IRMP_RCCAR_PROTOCOL
) return 1;
254 #if IRMP_SUPPORT_ROOMBA_PROTOCOL
255 if (proto
== IRMP_ROOMBA_PROTOCOL
) return 1;
257 #if IRMP_SUPPORT_RUWIDO_PROTOCOL
258 if (proto
== IRMP_RUWIDO_PROTOCOL
) return 1;
260 #if IRMP_SUPPORT_A1TVBOX_PROTOCOL
261 if (proto
== IRMP_A1TVBOX_PROTOCOL
) return 1;
263 #if IRMP_SUPPORT_LEGO_PROTOCOL
264 if (proto
== IRMP_LEGO_PROTOCOL
) return 1;
266 #if IRMP_SUPPORT_RCMM_PROTOCOL
267 if (proto
== IRMP_RCMM_PROTOCOL
) return 1;
269 #if IRMP_SUPPORT_LGAIR_PROTOCOL
270 if (proto
== IRMP_LGAIR_PROTOCOL
) return 1;
272 #if IRMP_SUPPORT_SAMSUNG48_PROTOCOL
273 if (proto
== IRMP_SAMSUNG48_PROTOCOL
) return 1;
275 #if IRMP_SUPPORT_MERLIN_PROTOCOL
276 if (proto
== IRMP_MERLIN_PROTOCOL
) return 1;
278 #if IRMP_SUPPORT_PENTAX_PROTOCOL
279 if (proto
== IRMP_PENTAX_PROTOCOL
) return 1;
281 #if IRMP_SUPPORT_S100_PROTOCOL
282 if (proto
== IRMP_S100_PROTOCOL
) return 1;
284 #if IRMP_SUPPORT_ACP24_PROTOCOL
285 if (proto
== IRMP_ACP24_PROTOCOL
) return 1;
287 #if IRMP_SUPPORT_TECHNICS_PROTOCOL
288 if (proto
== IRMP_TECHNICS_PROTOCOL
) return 1;
290 #if IRMP_SUPPORT_PANASONIC_PROTOCOL
291 if (proto
== IRMP_PANASONIC_PROTOCOL
) return 1;
293 #if IRMP_SUPPORT_MITSU_HEAVY_PROTOCOL
294 if (proto
== IRMP_MITSU_HEAVY_PROTOCOL
) return 1;
296 #if IRMP_SUPPORT_VINCENT_PROTOCOL
297 if (proto
== IRMP_VINCENT_PROTOCOL
) return 1;
299 #if IRMP_SUPPORT_SAMSUNGAH_PROTOCOL
300 if (proto
== IRMP_SAMSUNGAH_PROTOCOL
) return 1;
302 #if IRMP_SUPPORT_RADIO1_PROTOCOL
303 if (proto
== IRMP_RADIO1_PROTOCOL
) return 1;
309 void print_supported_protocols(void)
311 printf("Supported IR protocols:");
312 for (int i
= 0; i
<= IRMP_N_PROTOCOLS
; i
++) {
313 if (irmp_protocol_is_supported(i
)) {
314 #if IRMP_PROTOCOL_NAMES == 1
315 printf(" %s", irmp_protocol_names
[i
]);
324 /*--------------------------------------------------------------------------*/
330 if (get_timer(ts
) >= 500) {
332 gpio_toggle(LED_PORT
, LED_PIN
);
340 setup_clock_and_gpios();
341 setvbuf(stdout
, NULL
, _IONBF
, 0);
342 serial_setup(CON_BAUDRATE
);
344 printf("\nIRMP on STM32F103 with libopencm3 demo\n"
345 " System frequency: %luHz\n"
346 "IRMP timer input frequency (CK_INT): %luHz\n"
347 " IRMP interrupt frequency: %uHz\n",
348 rcc_ahb_frequency
, timer_internal_clock_get(TIM_IRMP
), F_INTERRUPTS
);
351 irmp_timer_init(); // initialize timer for irmp
352 irmp_init(); // initialize irmp
354 print_supported_protocols();
358 if (irmp_get_data (&irmp_data
))
360 printf("protocol: 0x%.2x", irmp_data
.protocol
);
361 #if IRMP_PROTOCOL_NAMES == 1
362 printf(" %-11s", irmp_protocol_names
[irmp_data
.protocol
]);
364 printf(" adress: 0x%.4x command: 0x%.4x flags: 0x%.2x\n",
365 irmp_data
.address
, irmp_data
.command
, irmp_data
.flags
);