]> cloudbase.mooo.com Git - irmp-demo.git/blob - irmp-main.c
Change port pin for debug led to enable logging on usart2.
[irmp-demo.git] / irmp-main.c
1 /*------------------------------------------------------------------------------
2 * irmp-main.c - demo program to test the IRMP decoder on STM32F1 whith libopencm3
3 *
4 * Copyright (c) 2017 Leo C. <erbl259-lmu@yahoo.de>
5 *
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
10 *
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.
14 *
15 * This demo runs on the Generic STM32F103C8T6 Development Board, aka bluepill.
16 *
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 *------------------------------------------------------------------------------
22 */
23
24 #include "config.h"
25 #include "timer.h"
26 #include "serial.h"
27 #include "irmp.h"
28 #include <libopencm3/stm32/rcc.h>
29 #include <libopencm3/stm32/gpio.h>
30 #include <stdio.h>
31
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
37 #endif
38
39 /* Toggle a pin on irmp timer isr entry and exit */
40 #ifndef DEBUG_IRMP_TIMER_INT
41 #define DEBUG_IRMP_TIMER_INT 0
42 #endif
43
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
48 #endif
49
50 /**
51 * Do all initialisations, that are not done by a specific module here.
52 */
53 static void setup_clock_and_gpios(void)
54 {
55 /* Clock setup */
56 /* Default clock is 8MHz HSI */
57 //rcc_clock_setup_in_hse_8mhz_out_24mhz();
58 //rcc_clock_setup_in_hse_8mhz_out_72mhz();
59
60 /* GPIO setup */
61 /* Only the on board led is configured here */
62
63 rcc_periph_clock_enable(RCC_LED_PORT);
64
65 /* Set GPIO13 (in GPIO port C) to 'output push-pull'. */
66 /* Manually: */
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);
73 }
74
75 /*--------------------------------------------------------------------------*/
76 /* IRMP */
77 /*--------------------------------------------------------------------------*/
78
79 #define IRMP_TIMER_NUMBER 3
80 #define IRMP_TIMER CONCAT(TIM, IRMP_TIMER_NUMBER)
81
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)
89
90
91 /** Retrieve the actual input clock of a timer
92
93 @param[in] timer_peripheral Unsigned int32. Timer register address base
94 @returns Unsigned int32. frequency value.
95 */
96 uint32_t timer_internal_clock_get(uint32_t timer_peripheral)
97 {
98 uint32_t timer_frequency;
99
100 /* Get preripheral bus frequency and prescaler mask */
101 if ((timer_peripheral >= TIM2 && timer_peripheral <= TIM5)
102 || (timer_peripheral >= TIM12 && timer_peripheral <= TIM14))
103 {
104 timer_frequency = rcc_apb1_frequency;
105 } else {
106 timer_frequency = rcc_apb2_frequency;
107 }
108 /* Timer clock is doubled, if the APB prescaler is greater than 1 */
109 if (timer_frequency != rcc_ahb_frequency)
110 timer_frequency *= 2;
111
112 return timer_frequency;
113 }
114
115 /**
116 * Intialize the irmp interrupt timer
117 */
118 void irmp_timer_init (void)
119 {
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);
125 #endif
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);
130
131 #if USE_OPENCM3_API /* Using API functions: */
132
133 /* Timer global mode:
134 * - No divider
135 * - Alignment edge
136 * - Direction up
137 * (These are actually default values after reset, so this call
138 * is strictly unnecessary, but demos the api for alternative settings)
139 */
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);
147
148 #else /* Manually */
149
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;
152
153 /* Enable Timer interrupt and timer */
154 IRMP_TIMER_DIER = TIM_DIER_UIE;
155 IRMP_TIMER_CR1 |= TIM_CR1_CEN;
156
157 #endif
158 }
159
160 void IRMP_TIMER_ISR(void)
161 {
162 #if DEBUG_IRMP_TIMER_INT
163 # if USE_OPENCM3_API /* Using API functions: */
164
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;
170 # endif
171 #endif
172 /* Clear update interrupt flag. */
173 IRMP_TIMER_SR = ~TIM_SR_UIF;
174
175 (void) irmp_ISR(); // call irmp ISR
176
177 // call other timer interrupt routines...
178
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;
184 # endif
185 #endif
186 }
187
188 /*--------------------------------------------------------------------------*/
189
190 /** Test if a IR protocol is supported
191 *
192 * Return true, if proto is valid protocol number and the protocol
193 * is enabled in irmpconfig.h
194 */
195 int irmp_protocol_is_supported(int proto)
196 {
197 #if IRMP_SUPPORT_SIRCS_PROTOCOL
198 if (proto == IRMP_SIRCS_PROTOCOL) return 1;
199 #endif
200 #if IRMP_SUPPORT_NEC_PROTOCOL
201 if (proto == IRMP_NEC_PROTOCOL) return 1;
202 #endif
203 #if IRMP_SUPPORT_SAMSUNG_PROTOCOL
204 if (proto == IRMP_SAMSUNG_PROTOCOL) return 1;
205 #endif
206 #if IRMP_SUPPORT_KASEIKYO_PROTOCOL
207 if (proto == IRMP_KASEIKYO_PROTOCOL) return 1;
208 #endif
209 #if IRMP_SUPPORT_JVC_PROTOCOL
210 if (proto == IRMP_JVC_PROTOCOL) return 1;
211 #endif
212 #if IRMP_SUPPORT_NEC16_PROTOCOL
213 if (proto == IRMP_NEC16_PROTOCOL) return 1;
214 #endif
215 #if IRMP_SUPPORT_NEC42_PROTOCOL
216 if (proto == IRMP_NEC42_PROTOCOL) return 1;
217 #endif
218 #if IRMP_SUPPORT_MATSUSHITA_PROTOCOL
219 if (proto == IRMP_MATSUSHITA_PROTOCOL) return 1;
220 #endif
221 #if IRMP_SUPPORT_DENON_PROTOCOL
222 if (proto == IRMP_DENON_PROTOCOL) return 1;
223 #endif
224 #if IRMP_SUPPORT_RC5_PROTOCOL
225 if (proto == IRMP_RC5_PROTOCOL) return 1;
226 #endif
227 #if IRMP_SUPPORT_RC6_PROTOCOL
228 if (proto == IRMP_RC6_PROTOCOL) return 1;
229 #endif
230 #if IRMP_SUPPORT_IR60_PROTOCOL
231 if (proto == IRMP_IR60_PROTOCOL) return 1;
232 #endif
233 #if IRMP_SUPPORT_GRUNDIG_PROTOCOL
234 if (proto == IRMP_GRUNDIG_PROTOCOL) return 1;
235 #endif
236 #if IRMP_SUPPORT_SIEMENS_PROTOCOL
237 if (proto == IRMP_SIEMENS_PROTOCOL) return 1;
238 #endif
239 #if IRMP_SUPPORT_NOKIA_PROTOCOL
240 if (proto == IRMP_NOKIA_PROTOCOL) return 1;
241 #endif
242 #if IRMP_SUPPORT_BOSE_PROTOCOL
243 if (proto == IRMP_BOSE_PROTOCOL) return 1;
244 #endif
245 #if IRMP_SUPPORT_KATHREIN_PROTOCOL
246 if (proto == IRMP_KATHREIN_PROTOCOL) return 1;
247 #endif
248 #if IRMP_SUPPORT_NUBERT_PROTOCOL
249 if (proto == IRMP_NUBERT_PROTOCOL) return 1;
250 #endif
251 #if IRMP_SUPPORT_FAN_PROTOCOL
252 if (proto == IRMP_FAN_PROTOCOL) return 1;
253 #endif
254 #if IRMP_SUPPORT_SPEAKER_PROTOCOL
255 if (proto == IRMP_SPEAKER_PROTOCOL) return 1;
256 #endif
257 #if IRMP_SUPPORT_BANG_OLUFSEN_PROTOCOL
258 if (proto == IRMP_BANG_OLUFSEN_PROTOCOL) return 1;
259 #endif
260 #if IRMP_SUPPORT_RECS80_PROTOCOL
261 if (proto == IRMP_RECS80_PROTOCOL) return 1;
262 #endif
263 #if IRMP_SUPPORT_RECS80EXT_PROTOCOL
264 if (proto == IRMP_RECS80EXT_PROTOCOL) return 1;
265 #endif
266 #if IRMP_SUPPORT_THOMSON_PROTOCOL
267 if (proto == IRMP_THOMSON_PROTOCOL) return 1;
268 #endif
269 #if IRMP_SUPPORT_NIKON_PROTOCOL
270 if (proto == IRMP_NIKON_PROTOCOL) return 1;
271 #endif
272 #if IRMP_SUPPORT_NETBOX_PROTOCOL
273 if (proto == IRMP_NETBOX_PROTOCOL) return 1;
274 #endif
275 #if IRMP_SUPPORT_ORTEK_PROTOCOL
276 if (proto == IRMP_ORTEK_PROTOCOL) return 1;
277 #endif
278 #if IRMP_SUPPORT_TELEFUNKEN_PROTOCOL
279 if (proto == IRMP_TELEFUNKEN_PROTOCOL) return 1;
280 #endif
281 #if IRMP_SUPPORT_FDC_PROTOCOL
282 if (proto == IRMP_FDC_PROTOCOL) return 1;
283 #endif
284 #if IRMP_SUPPORT_RCCAR_PROTOCOL
285 if (proto == IRMP_RCCAR_PROTOCOL) return 1;
286 #endif
287 #if IRMP_SUPPORT_ROOMBA_PROTOCOL
288 if (proto == IRMP_ROOMBA_PROTOCOL) return 1;
289 #endif
290 #if IRMP_SUPPORT_RUWIDO_PROTOCOL
291 if (proto == IRMP_RUWIDO_PROTOCOL) return 1;
292 #endif
293 #if IRMP_SUPPORT_A1TVBOX_PROTOCOL
294 if (proto == IRMP_A1TVBOX_PROTOCOL) return 1;
295 #endif
296 #if IRMP_SUPPORT_LEGO_PROTOCOL
297 if (proto == IRMP_LEGO_PROTOCOL) return 1;
298 #endif
299 #if IRMP_SUPPORT_RCMM_PROTOCOL
300 if (proto == IRMP_RCMM_PROTOCOL) return 1;
301 #endif
302 #if IRMP_SUPPORT_LGAIR_PROTOCOL
303 if (proto == IRMP_LGAIR_PROTOCOL) return 1;
304 #endif
305 #if IRMP_SUPPORT_SAMSUNG48_PROTOCOL
306 if (proto == IRMP_SAMSUNG48_PROTOCOL) return 1;
307 #endif
308 #if IRMP_SUPPORT_MERLIN_PROTOCOL
309 if (proto == IRMP_MERLIN_PROTOCOL) return 1;
310 #endif
311 #if IRMP_SUPPORT_PENTAX_PROTOCOL
312 if (proto == IRMP_PENTAX_PROTOCOL) return 1;
313 #endif
314 #if IRMP_SUPPORT_S100_PROTOCOL
315 if (proto == IRMP_S100_PROTOCOL) return 1;
316 #endif
317 #if IRMP_SUPPORT_ACP24_PROTOCOL
318 if (proto == IRMP_ACP24_PROTOCOL) return 1;
319 #endif
320 #if IRMP_SUPPORT_TECHNICS_PROTOCOL
321 if (proto == IRMP_TECHNICS_PROTOCOL) return 1;
322 #endif
323 #if IRMP_SUPPORT_PANASONIC_PROTOCOL
324 if (proto == IRMP_PANASONIC_PROTOCOL) return 1;
325 #endif
326 #if IRMP_SUPPORT_MITSU_HEAVY_PROTOCOL
327 if (proto == IRMP_MITSU_HEAVY_PROTOCOL) return 1;
328 #endif
329 #if IRMP_SUPPORT_VINCENT_PROTOCOL
330 if (proto == IRMP_VINCENT_PROTOCOL) return 1;
331 #endif
332 #if IRMP_SUPPORT_SAMSUNGAH_PROTOCOL
333 if (proto == IRMP_SAMSUNGAH_PROTOCOL) return 1;
334 #endif
335 #if IRMP_SUPPORT_RADIO1_PROTOCOL
336 if (proto == IRMP_RADIO1_PROTOCOL) return 1;
337 #endif
338
339 return 0;
340 }
341
342 /**
343 * Print the names of all supported protocols, or the supported protocol
344 * numbers, if names are not enabled.
345 */
346 void print_supported_protocols(void)
347 {
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]);
353 #else
354 printf(" %d", i);
355 #endif
356 }
357 }
358 printf("\n");
359 }
360
361 /*--------------------------------------------------------------------------*/
362
363 /** Let the board led do something
364 *
365 * The led should blink with 1 Hz
366 */
367 void led_blink(void)
368 {
369 static uint32_t ts;
370
371 if (get_timer(ts) >= 500) {
372 ts = get_timer(0);
373 gpio_toggle(LED_PORT, LED_PIN);
374 }
375 }
376
377 int main (void)
378 {
379 IRMP_DATA irmp_data;
380
381 setup_clock_and_gpios();
382 setvbuf(stdout, NULL, _IONBF, 0);
383 serial_setup(CON_BAUDRATE);
384
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);
390
391 systick_setup();
392 irmp_timer_init(); // initialize timer for irmp
393 irmp_init(); // initialize irmp
394
395 print_supported_protocols();
396 for (;;)
397 {
398 led_blink();
399 if (irmp_get_data (&irmp_data))
400 {
401 printf("protocol: 0x%.2x", irmp_data.protocol);
402 #if IRMP_PROTOCOL_NAMES == 1
403 printf(" %-11s", irmp_protocol_names[irmp_data.protocol]);
404 #endif
405 printf(" adress: 0x%.4x command: 0x%.4x flags: 0x%.2x\n",
406 irmp_data.address, irmp_data.command, irmp_data.flags);
407 }
408 }
409 }