1 /*------------------------------------------------------------------------------
2 * irmp-main.c - demo program to test the IRMP decoder on STM32F1 whith libopencm3
4 * Copyright (c) 2017 Leo C. <erbl259-lmu@yahoo.de>
6 * This demo program is essentially a combination of some libopencm3 examples
7 * from https://github.com/libopencm3/libopencm3-examples
8 * and irmp-main-stm32.c from the IRMP distribution, which is
9 * Copyright (c) 2009-2016 Frank Meyer - frank(at)fli4l.de
11 * The program demonstrates the integration of IRMP in a libopencm3 environment,
12 * and how to use the libopencm3 api functions, or alternatively direct
13 * register access, using the macros defined by libopencm3.
15 * This demo runs on the Generic STM32F103C8T6 Development Board, aka bluepill.
17 * This program is free software; you can redistribute it and/or modify
18 * it under the terms of the GNU General Public License as published by
19 * the Free Software Foundation; either version 2 of the License, or
20 * (at your option) any later version.
21 *------------------------------------------------------------------------------
28 #include <libopencm3/stm32/rcc.h>
29 #include <libopencm3/stm32/gpio.h>
32 /* The folloing macros can also be defined in the Makefile */
33 /* If 0 or undefined, use direct register access where appropriate,
34 * else use the libopencm3 api functions everywhere. */
35 #ifndef USE_OPENCM3_API
36 #define USE_OPENCM3_API 0
39 /* Toggle a pin on irmp timer isr entry and exit */
40 #ifndef DEBUG_IRMP_TIMER_INT
41 #define DEBUG_IRMP_TIMER_INT 0
44 #if DEBUG_IRMP_TIMER_INT
45 #define DEBUG_LED_PORT GPIOB
46 #define DEBUG_LED_PIN GPIO0
47 #define DEBUG_LED_PORT_RCC RCC_GPIOB
51 * Do all initialisations, that are not done by a specific module here.
53 static void setup_clock_and_gpios(void)
56 /* Default clock is 8MHz HSI */
57 //rcc_clock_setup_in_hse_8mhz_out_24mhz();
58 //rcc_clock_setup_in_hse_8mhz_out_72mhz();
61 /* Only the on board led is configured here */
63 rcc_periph_clock_enable(RCC_LED_PORT
);
65 /* Set GPIO13 (in GPIO port C) to 'output push-pull'. */
67 // GPIOC_CRH = (GPIO_CNF_OUTPUT_PUSHPULL << (((12 - 8) * 4) + 2));
68 // GPIOC_CRH |= (GPIO_MODE_OUTPUT_2_MHZ << ((12 - 8) * 4));
69 /* Using API functions: */
70 gpio_set(LED_PORT
, LED_PIN
); /* set output register high (led off) */
71 gpio_set_mode(LED_PORT
, GPIO_MODE_OUTPUT_2_MHZ
,
72 GPIO_CNF_OUTPUT_PUSHPULL
, LED_PIN
);
75 /*--------------------------------------------------------------------------*/
77 /*--------------------------------------------------------------------------*/
79 #define IRMP_TIMER_NUMBER 3
80 #define IRMP_TIMER CONCAT(TIM, IRMP_TIMER_NUMBER)
82 #define IRMP_TIMER_CR1 TIM_CR1(IRMP_TIMER)
83 #define IRMP_TIMER_DIER TIM_DIER(IRMP_TIMER)
84 #define IRMP_TIMER_SR TIM_SR(IRMP_TIMER)
85 #define IRMP_TIMER_ARR TIM_ARR(IRMP_TIMER)
86 #define IRMP_TIMER_RCC CONCAT(RCC_TIM, IRMP_TIMER_NUMBER)
87 #define NVIC_IRMP_TIMER_IRQ CONCAT(CONCAT(NVIC_TIM, IRMP_TIMER_NUMBER), _IRQ)
88 #define IRMP_TIMER_ISR CONCAT(CONCAT(tim, IRMP_TIMER_NUMBER), _isr)
91 /** Retrieve the actual input clock of a timer
93 @param[in] timer_peripheral Unsigned int32. Timer register address base
94 @returns Unsigned int32. frequency value.
96 uint32_t timer_internal_clock_get(uint32_t timer_peripheral
)
98 uint32_t timer_frequency
;
100 /* Get preripheral bus frequency and prescaler mask */
101 if ((timer_peripheral
>= TIM2
&& timer_peripheral
<= TIM5
)
102 || (timer_peripheral
>= TIM12
&& timer_peripheral
<= TIM14
))
104 timer_frequency
= rcc_apb1_frequency
;
106 timer_frequency
= rcc_apb2_frequency
;
108 /* Timer clock is doubled, if the APB prescaler is greater than 1 */
109 if (timer_frequency
!= rcc_ahb_frequency
)
110 timer_frequency
*= 2;
112 return timer_frequency
;
116 * Intialize the irmp interrupt timer
118 void irmp_timer_init (void)
120 #if DEBUG_IRMP_TIMER_INT
121 /* Output pin for debugging */
122 rcc_periph_clock_enable(DEBUG_LED_PORT_RCC
);
123 gpio_set_mode(DEBUG_LED_PORT
, GPIO_MODE_OUTPUT_2_MHZ
,
124 GPIO_CNF_OUTPUT_PUSHPULL
, DEBUG_LED_PIN
);
126 /* Enable timer clock. */
127 rcc_periph_clock_enable(IRMP_TIMER_RCC
);
128 nvic_set_priority(NVIC_IRMP_TIMER_IRQ
, 4*16);
129 nvic_enable_irq(NVIC_IRMP_TIMER_IRQ
);
131 #if USE_OPENCM3_API /* Using API functions: */
133 /* Timer global mode:
137 * (These are actually default values after reset, so this call
138 * is strictly unnecessary, but demos the api for alternative settings)
140 timer_set_mode(IRMP_TIMER
, TIM_CR1_CKD_CK_INT
,
141 TIM_CR1_CMS_EDGE
, TIM_CR1_DIR_UP
);
142 timer_set_period(IRMP_TIMER
, timer_internal_clock_get(IRMP_TIMER
) / F_INTERRUPTS
- 1);
143 /* Enable Channel 1 compare interrupt to recalculate compare values */
144 timer_enable_irq(IRMP_TIMER
, TIM_DIER_UIE
);
145 /* Counter enable. */
146 timer_enable_counter(IRMP_TIMER
);
150 IRMP_TIMER_CR1
= TIM_CR1_CKD_CK_INT
| TIM_CR1_CMS_EDGE
| TIM_CR1_DIR_UP
;
151 IRMP_TIMER_ARR
= timer_internal_clock_get(IRMP_TIMER
) / F_INTERRUPTS
- 1;
153 /* Enable Timer interrupt and timer */
154 IRMP_TIMER_DIER
= TIM_DIER_UIE
;
155 IRMP_TIMER_CR1
|= TIM_CR1_CEN
;
160 void IRMP_TIMER_ISR(void)
162 #if DEBUG_IRMP_TIMER_INT
163 # if USE_OPENCM3_API /* Using API functions: */
165 gpio_clear(DEBUG_LED_PORT
, DEBUG_LED_PIN
);
166 /* Clear update interrupt flag. */
167 timer_clear_flag(IRMP_TIMER
, TIM_SR_UIF
);
168 # else /* Manually */
169 GPIO_BRR(DEBUG_LED_PORT
) = DEBUG_LED_PIN
;
172 /* Clear update interrupt flag. */
173 IRMP_TIMER_SR
= ~TIM_SR_UIF
;
175 (void) irmp_ISR(); // call irmp ISR
177 // call other timer interrupt routines...
179 #if DEBUG_IRMP_TIMER_INT
180 # if USE_OPENCM3_API /* Using API functions: */
181 gpio_set(DEBUG_LED_PORT
, DEBUG_LED_PIN
);
182 # else /* Manually */
183 GPIO_BSRR(DEBUG_LED_PORT
) = DEBUG_LED_PIN
;
188 /*--------------------------------------------------------------------------*/
190 /** Test if a IR protocol is supported
192 * Return true, if proto is valid protocol number and the protocol
193 * is enabled in irmpconfig.h
195 int irmp_protocol_is_supported(int proto
)
197 #if IRMP_SUPPORT_SIRCS_PROTOCOL
198 if (proto
== IRMP_SIRCS_PROTOCOL
) return 1;
200 #if IRMP_SUPPORT_NEC_PROTOCOL
201 if (proto
== IRMP_NEC_PROTOCOL
) return 1;
203 #if IRMP_SUPPORT_SAMSUNG_PROTOCOL
204 if (proto
== IRMP_SAMSUNG_PROTOCOL
) return 1;
206 #if IRMP_SUPPORT_KASEIKYO_PROTOCOL
207 if (proto
== IRMP_KASEIKYO_PROTOCOL
) return 1;
209 #if IRMP_SUPPORT_JVC_PROTOCOL
210 if (proto
== IRMP_JVC_PROTOCOL
) return 1;
212 #if IRMP_SUPPORT_NEC16_PROTOCOL
213 if (proto
== IRMP_NEC16_PROTOCOL
) return 1;
215 #if IRMP_SUPPORT_NEC42_PROTOCOL
216 if (proto
== IRMP_NEC42_PROTOCOL
) return 1;
218 #if IRMP_SUPPORT_MATSUSHITA_PROTOCOL
219 if (proto
== IRMP_MATSUSHITA_PROTOCOL
) return 1;
221 #if IRMP_SUPPORT_DENON_PROTOCOL
222 if (proto
== IRMP_DENON_PROTOCOL
) return 1;
224 #if IRMP_SUPPORT_RC5_PROTOCOL
225 if (proto
== IRMP_RC5_PROTOCOL
) return 1;
227 #if IRMP_SUPPORT_RC6_PROTOCOL
228 if (proto
== IRMP_RC6_PROTOCOL
) return 1;
230 #if IRMP_SUPPORT_IR60_PROTOCOL
231 if (proto
== IRMP_IR60_PROTOCOL
) return 1;
233 #if IRMP_SUPPORT_GRUNDIG_PROTOCOL
234 if (proto
== IRMP_GRUNDIG_PROTOCOL
) return 1;
236 #if IRMP_SUPPORT_SIEMENS_PROTOCOL
237 if (proto
== IRMP_SIEMENS_PROTOCOL
) return 1;
239 #if IRMP_SUPPORT_NOKIA_PROTOCOL
240 if (proto
== IRMP_NOKIA_PROTOCOL
) return 1;
242 #if IRMP_SUPPORT_BOSE_PROTOCOL
243 if (proto
== IRMP_BOSE_PROTOCOL
) return 1;
245 #if IRMP_SUPPORT_KATHREIN_PROTOCOL
246 if (proto
== IRMP_KATHREIN_PROTOCOL
) return 1;
248 #if IRMP_SUPPORT_NUBERT_PROTOCOL
249 if (proto
== IRMP_NUBERT_PROTOCOL
) return 1;
251 #if IRMP_SUPPORT_FAN_PROTOCOL
252 if (proto
== IRMP_FAN_PROTOCOL
) return 1;
254 #if IRMP_SUPPORT_SPEAKER_PROTOCOL
255 if (proto
== IRMP_SPEAKER_PROTOCOL
) return 1;
257 #if IRMP_SUPPORT_BANG_OLUFSEN_PROTOCOL
258 if (proto
== IRMP_BANG_OLUFSEN_PROTOCOL
) return 1;
260 #if IRMP_SUPPORT_RECS80_PROTOCOL
261 if (proto
== IRMP_RECS80_PROTOCOL
) return 1;
263 #if IRMP_SUPPORT_RECS80EXT_PROTOCOL
264 if (proto
== IRMP_RECS80EXT_PROTOCOL
) return 1;
266 #if IRMP_SUPPORT_THOMSON_PROTOCOL
267 if (proto
== IRMP_THOMSON_PROTOCOL
) return 1;
269 #if IRMP_SUPPORT_NIKON_PROTOCOL
270 if (proto
== IRMP_NIKON_PROTOCOL
) return 1;
272 #if IRMP_SUPPORT_NETBOX_PROTOCOL
273 if (proto
== IRMP_NETBOX_PROTOCOL
) return 1;
275 #if IRMP_SUPPORT_ORTEK_PROTOCOL
276 if (proto
== IRMP_ORTEK_PROTOCOL
) return 1;
278 #if IRMP_SUPPORT_TELEFUNKEN_PROTOCOL
279 if (proto
== IRMP_TELEFUNKEN_PROTOCOL
) return 1;
281 #if IRMP_SUPPORT_FDC_PROTOCOL
282 if (proto
== IRMP_FDC_PROTOCOL
) return 1;
284 #if IRMP_SUPPORT_RCCAR_PROTOCOL
285 if (proto
== IRMP_RCCAR_PROTOCOL
) return 1;
287 #if IRMP_SUPPORT_ROOMBA_PROTOCOL
288 if (proto
== IRMP_ROOMBA_PROTOCOL
) return 1;
290 #if IRMP_SUPPORT_RUWIDO_PROTOCOL
291 if (proto
== IRMP_RUWIDO_PROTOCOL
) return 1;
293 #if IRMP_SUPPORT_A1TVBOX_PROTOCOL
294 if (proto
== IRMP_A1TVBOX_PROTOCOL
) return 1;
296 #if IRMP_SUPPORT_LEGO_PROTOCOL
297 if (proto
== IRMP_LEGO_PROTOCOL
) return 1;
299 #if IRMP_SUPPORT_RCMM_PROTOCOL
300 if (proto
== IRMP_RCMM_PROTOCOL
) return 1;
302 #if IRMP_SUPPORT_LGAIR_PROTOCOL
303 if (proto
== IRMP_LGAIR_PROTOCOL
) return 1;
305 #if IRMP_SUPPORT_SAMSUNG48_PROTOCOL
306 if (proto
== IRMP_SAMSUNG48_PROTOCOL
) return 1;
308 #if IRMP_SUPPORT_MERLIN_PROTOCOL
309 if (proto
== IRMP_MERLIN_PROTOCOL
) return 1;
311 #if IRMP_SUPPORT_PENTAX_PROTOCOL
312 if (proto
== IRMP_PENTAX_PROTOCOL
) return 1;
314 #if IRMP_SUPPORT_S100_PROTOCOL
315 if (proto
== IRMP_S100_PROTOCOL
) return 1;
317 #if IRMP_SUPPORT_ACP24_PROTOCOL
318 if (proto
== IRMP_ACP24_PROTOCOL
) return 1;
320 #if IRMP_SUPPORT_TECHNICS_PROTOCOL
321 if (proto
== IRMP_TECHNICS_PROTOCOL
) return 1;
323 #if IRMP_SUPPORT_PANASONIC_PROTOCOL
324 if (proto
== IRMP_PANASONIC_PROTOCOL
) return 1;
326 #if IRMP_SUPPORT_MITSU_HEAVY_PROTOCOL
327 if (proto
== IRMP_MITSU_HEAVY_PROTOCOL
) return 1;
329 #if IRMP_SUPPORT_VINCENT_PROTOCOL
330 if (proto
== IRMP_VINCENT_PROTOCOL
) return 1;
332 #if IRMP_SUPPORT_SAMSUNGAH_PROTOCOL
333 if (proto
== IRMP_SAMSUNGAH_PROTOCOL
) return 1;
335 #if IRMP_SUPPORT_RADIO1_PROTOCOL
336 if (proto
== IRMP_RADIO1_PROTOCOL
) return 1;
343 * Print the names of all supported protocols, or the supported protocol
344 * numbers, if names are not enabled.
346 void print_supported_protocols(void)
348 printf("Supported IR protocols:");
349 for (int i
= 0; i
<= IRMP_N_PROTOCOLS
; i
++) {
350 if (irmp_protocol_is_supported(i
)) {
351 #if IRMP_PROTOCOL_NAMES == 1
352 printf(" %s", irmp_protocol_names
[i
]);
361 /*--------------------------------------------------------------------------*/
363 /** Let the board led do something
365 * The led should blink with 1 Hz
371 if (get_timer(ts
) >= 500) {
373 gpio_toggle(LED_PORT
, LED_PIN
);
381 setup_clock_and_gpios();
382 setvbuf(stdout
, NULL
, _IONBF
, 0);
383 serial_setup(CON_BAUDRATE
);
385 printf("\nIRMP on STM32F103 with libopencm3 demo\n"
386 " System frequency: %luHz\n"
387 "IRMP timer input frequency (CK_INT): %luHz\n"
388 " IRMP interrupt frequency: %uHz\n",
389 rcc_ahb_frequency
, timer_internal_clock_get(IRMP_TIMER
), F_INTERRUPTS
);
392 irmp_timer_init(); // initialize timer for irmp
393 irmp_init(); // initialize irmp
395 print_supported_protocols();
399 if (irmp_get_data (&irmp_data
))
401 printf("protocol: 0x%.2x", irmp_data
.protocol
);
402 #if IRMP_PROTOCOL_NAMES == 1
403 printf(" %-11s", irmp_protocol_names
[irmp_data
.protocol
]);
405 printf(" adress: 0x%.4x command: 0x%.4x flags: 0x%.2x\n",
406 irmp_data
.address
, irmp_data
.command
, irmp_data
.flags
);