]> cloudbase.mooo.com Git - irmp-demo.git/blob - irmp-main.c
Update submodules
[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 /**
45 * Do all initialisations, that are not done by a specific module here.
46 */
47 static void setup_clock_and_gpios(void)
48 {
49 /* Clock setup */
50 /* Default clock is 8MHz HSI */
51 //rcc_clock_setup_in_hse_8mhz_out_24mhz();
52 //rcc_clock_setup_in_hse_8mhz_out_72mhz();
53
54 /* GPIO setup */
55 /* Only the on board led is configured here */
56
57 rcc_periph_clock_enable(RCC_LED_PORT);
58
59 /* Set GPIO13 (in GPIO port C) to 'output push-pull'. */
60 /* Manually: */
61 // GPIOC_CRH = (GPIO_CNF_OUTPUT_PUSHPULL << (((12 - 8) * 4) + 2));
62 // GPIOC_CRH |= (GPIO_MODE_OUTPUT_2_MHZ << ((12 - 8) * 4));
63 /* Using API functions: */
64 gpio_set(LED_PORT, LED_PIN); /* set output register high (led off) */
65 gpio_set_mode(LED_PORT, GPIO_MODE_OUTPUT_2_MHZ,
66 GPIO_CNF_OUTPUT_PUSHPULL, LED_PIN);
67 }
68
69 /*--------------------------------------------------------------------------*/
70 /* IRMP */
71 /*--------------------------------------------------------------------------*/
72
73 #define IRMP_TIMER_NUMBER 3
74 #define IRMP_TIMER CONCAT(TIM, IRMP_TIMER_NUMBER)
75
76 #define IRMP_TIMER_CR1 TIM_CR1(IRMP_TIMER)
77 #define IRMP_TIMER_DIER TIM_DIER(IRMP_TIMER)
78 #define IRMP_TIMER_SR TIM_SR(IRMP_TIMER)
79 #define IRMP_TIMER_ARR TIM_ARR(IRMP_TIMER)
80 #define IRMP_TIMER_RCC CONCAT(RCC_TIM, IRMP_TIMER_NUMBER)
81 #define NVIC_IRMP_TIMER_IRQ CONCAT(CONCAT(NVIC_TIM, IRMP_TIMER_NUMBER), _IRQ)
82 #define IRMP_TIMER_ISR CONCAT(CONCAT(tim, IRMP_TIMER_NUMBER), _isr)
83
84
85 /** Retrieve the actual input clock of a timer
86
87 @param[in] timer_peripheral Unsigned int32. Timer register address base
88 @returns Unsigned int32. frequency value.
89 */
90 uint32_t timer_internal_clock_get(uint32_t timer_peripheral)
91 {
92 uint32_t timer_frequency;
93
94 /* Get preripheral bus frequency and prescaler mask */
95 if ((timer_peripheral >= TIM2 && timer_peripheral <= TIM5)
96 || (timer_peripheral >= TIM12 && timer_peripheral <= TIM14))
97 {
98 timer_frequency = rcc_apb1_frequency;
99 } else {
100 timer_frequency = rcc_apb2_frequency;
101 }
102 /* Timer clock is doubled, if the APB prescaler is greater than 1 */
103 if (timer_frequency != rcc_ahb_frequency)
104 timer_frequency *= 2;
105
106 return timer_frequency;
107 }
108
109 /**
110 * Intialize the irmp interrupt timer
111 */
112 void irmp_timer_init (void)
113 {
114 #if DEBUG_IRMP_TIMER_INT
115 /* Output pin for debugging */
116 rcc_periph_clock_enable(RCC_GPIOA);
117 gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ,
118 GPIO_CNF_OUTPUT_PUSHPULL, GPIO2);
119 #endif
120 /* Enable timer clock. */
121 rcc_periph_clock_enable(IRMP_TIMER_RCC);
122 nvic_set_priority(NVIC_IRMP_TIMER_IRQ, 4*16);
123 nvic_enable_irq(NVIC_IRMP_TIMER_IRQ);
124
125 #if USE_OPENCM3_API /* Using API functions: */
126
127 /* Timer global mode:
128 * - No divider
129 * - Alignment edge
130 * - Direction up
131 * (These are actually default values after reset, so this call
132 * is strictly unnecessary, but demos the api for alternative settings)
133 */
134 timer_set_mode(IRMP_TIMER, TIM_CR1_CKD_CK_INT,
135 TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP);
136 timer_set_period(IRMP_TIMER, timer_internal_clock_get(IRMP_TIMER) / F_INTERRUPTS - 1);
137 /* Enable Channel 1 compare interrupt to recalculate compare values */
138 timer_enable_irq(IRMP_TIMER, TIM_DIER_UIE);
139 /* Counter enable. */
140 timer_enable_counter(IRMP_TIMER);
141
142 #else /* Manually */
143
144 IRMP_TIMER_CR1 = TIM_CR1_CKD_CK_INT | TIM_CR1_CMS_EDGE | TIM_CR1_DIR_UP;
145 IRMP_TIMER_ARR = timer_internal_clock_get(IRMP_TIMER) / F_INTERRUPTS - 1;
146
147 /* Enable Timer interrupt and timer */
148 IRMP_TIMER_DIER = TIM_DIER_UIE;
149 IRMP_TIMER_CR1 |= TIM_CR1_CEN;
150
151 #endif
152 }
153
154 void IRMP_TIMER_ISR(void)
155 {
156 #if DEBUG_IRMP_TIMER_INT
157 # if USE_OPENCM3_API /* Using API functions: */
158
159 gpio_clear(GPIOA, GPIO2);
160 /* Clear update interrupt flag. */
161 timer_clear_flag(IRMP_TIMER, TIM_SR_UIF);
162 # else /* Manually */
163 GPIO_BRR(GPIOA) = GPIO2;
164 # endif
165 #endif
166 /* Clear update interrupt flag. */
167 IRMP_TIMER_SR = ~TIM_SR_UIF;
168
169 (void) irmp_ISR(); // call irmp ISR
170
171 // call other timer interrupt routines...
172
173 #if DEBUG_IRMP_TIMER_INT
174 # if USE_OPENCM3_API /* Using API functions: */
175 gpio_set(GPIOA, GPIO2);
176 # else /* Manually */
177 GPIO_BSRR(GPIOA) = GPIO2;
178 # endif
179 #endif
180 }
181
182 /*--------------------------------------------------------------------------*/
183
184 /** Test if a IR protocol is supported
185 *
186 * Return true, if proto is valid protocol number and the protocol
187 * is enabled in irmpconfig.h
188 */
189 int irmp_protocol_is_supported(int proto)
190 {
191 #if IRMP_SUPPORT_SIRCS_PROTOCOL
192 if (proto == IRMP_SIRCS_PROTOCOL) return 1;
193 #endif
194 #if IRMP_SUPPORT_NEC_PROTOCOL
195 if (proto == IRMP_NEC_PROTOCOL) return 1;
196 #endif
197 #if IRMP_SUPPORT_SAMSUNG_PROTOCOL
198 if (proto == IRMP_SAMSUNG_PROTOCOL) return 1;
199 #endif
200 #if IRMP_SUPPORT_KASEIKYO_PROTOCOL
201 if (proto == IRMP_KASEIKYO_PROTOCOL) return 1;
202 #endif
203 #if IRMP_SUPPORT_JVC_PROTOCOL
204 if (proto == IRMP_JVC_PROTOCOL) return 1;
205 #endif
206 #if IRMP_SUPPORT_NEC16_PROTOCOL
207 if (proto == IRMP_NEC16_PROTOCOL) return 1;
208 #endif
209 #if IRMP_SUPPORT_NEC42_PROTOCOL
210 if (proto == IRMP_NEC42_PROTOCOL) return 1;
211 #endif
212 #if IRMP_SUPPORT_MATSUSHITA_PROTOCOL
213 if (proto == IRMP_MATSUSHITA_PROTOCOL) return 1;
214 #endif
215 #if IRMP_SUPPORT_DENON_PROTOCOL
216 if (proto == IRMP_DENON_PROTOCOL) return 1;
217 #endif
218 #if IRMP_SUPPORT_RC5_PROTOCOL
219 if (proto == IRMP_RC5_PROTOCOL) return 1;
220 #endif
221 #if IRMP_SUPPORT_RC6_PROTOCOL
222 if (proto == IRMP_RC6_PROTOCOL) return 1;
223 #endif
224 #if IRMP_SUPPORT_IR60_PROTOCOL
225 if (proto == IRMP_IR60_PROTOCOL) return 1;
226 #endif
227 #if IRMP_SUPPORT_GRUNDIG_PROTOCOL
228 if (proto == IRMP_GRUNDIG_PROTOCOL) return 1;
229 #endif
230 #if IRMP_SUPPORT_SIEMENS_PROTOCOL
231 if (proto == IRMP_SIEMENS_PROTOCOL) return 1;
232 #endif
233 #if IRMP_SUPPORT_NOKIA_PROTOCOL
234 if (proto == IRMP_NOKIA_PROTOCOL) return 1;
235 #endif
236 #if IRMP_SUPPORT_BOSE_PROTOCOL
237 if (proto == IRMP_BOSE_PROTOCOL) return 1;
238 #endif
239 #if IRMP_SUPPORT_KATHREIN_PROTOCOL
240 if (proto == IRMP_KATHREIN_PROTOCOL) return 1;
241 #endif
242 #if IRMP_SUPPORT_NUBERT_PROTOCOL
243 if (proto == IRMP_NUBERT_PROTOCOL) return 1;
244 #endif
245 #if IRMP_SUPPORT_FAN_PROTOCOL
246 if (proto == IRMP_FAN_PROTOCOL) return 1;
247 #endif
248 #if IRMP_SUPPORT_SPEAKER_PROTOCOL
249 if (proto == IRMP_SPEAKER_PROTOCOL) return 1;
250 #endif
251 #if IRMP_SUPPORT_BANG_OLUFSEN_PROTOCOL
252 if (proto == IRMP_BANG_OLUFSEN_PROTOCOL) return 1;
253 #endif
254 #if IRMP_SUPPORT_RECS80_PROTOCOL
255 if (proto == IRMP_RECS80_PROTOCOL) return 1;
256 #endif
257 #if IRMP_SUPPORT_RECS80EXT_PROTOCOL
258 if (proto == IRMP_RECS80EXT_PROTOCOL) return 1;
259 #endif
260 #if IRMP_SUPPORT_THOMSON_PROTOCOL
261 if (proto == IRMP_THOMSON_PROTOCOL) return 1;
262 #endif
263 #if IRMP_SUPPORT_NIKON_PROTOCOL
264 if (proto == IRMP_NIKON_PROTOCOL) return 1;
265 #endif
266 #if IRMP_SUPPORT_NETBOX_PROTOCOL
267 if (proto == IRMP_NETBOX_PROTOCOL) return 1;
268 #endif
269 #if IRMP_SUPPORT_ORTEK_PROTOCOL
270 if (proto == IRMP_ORTEK_PROTOCOL) return 1;
271 #endif
272 #if IRMP_SUPPORT_TELEFUNKEN_PROTOCOL
273 if (proto == IRMP_TELEFUNKEN_PROTOCOL) return 1;
274 #endif
275 #if IRMP_SUPPORT_FDC_PROTOCOL
276 if (proto == IRMP_FDC_PROTOCOL) return 1;
277 #endif
278 #if IRMP_SUPPORT_RCCAR_PROTOCOL
279 if (proto == IRMP_RCCAR_PROTOCOL) return 1;
280 #endif
281 #if IRMP_SUPPORT_ROOMBA_PROTOCOL
282 if (proto == IRMP_ROOMBA_PROTOCOL) return 1;
283 #endif
284 #if IRMP_SUPPORT_RUWIDO_PROTOCOL
285 if (proto == IRMP_RUWIDO_PROTOCOL) return 1;
286 #endif
287 #if IRMP_SUPPORT_A1TVBOX_PROTOCOL
288 if (proto == IRMP_A1TVBOX_PROTOCOL) return 1;
289 #endif
290 #if IRMP_SUPPORT_LEGO_PROTOCOL
291 if (proto == IRMP_LEGO_PROTOCOL) return 1;
292 #endif
293 #if IRMP_SUPPORT_RCMM_PROTOCOL
294 if (proto == IRMP_RCMM_PROTOCOL) return 1;
295 #endif
296 #if IRMP_SUPPORT_LGAIR_PROTOCOL
297 if (proto == IRMP_LGAIR_PROTOCOL) return 1;
298 #endif
299 #if IRMP_SUPPORT_SAMSUNG48_PROTOCOL
300 if (proto == IRMP_SAMSUNG48_PROTOCOL) return 1;
301 #endif
302 #if IRMP_SUPPORT_MERLIN_PROTOCOL
303 if (proto == IRMP_MERLIN_PROTOCOL) return 1;
304 #endif
305 #if IRMP_SUPPORT_PENTAX_PROTOCOL
306 if (proto == IRMP_PENTAX_PROTOCOL) return 1;
307 #endif
308 #if IRMP_SUPPORT_S100_PROTOCOL
309 if (proto == IRMP_S100_PROTOCOL) return 1;
310 #endif
311 #if IRMP_SUPPORT_ACP24_PROTOCOL
312 if (proto == IRMP_ACP24_PROTOCOL) return 1;
313 #endif
314 #if IRMP_SUPPORT_TECHNICS_PROTOCOL
315 if (proto == IRMP_TECHNICS_PROTOCOL) return 1;
316 #endif
317 #if IRMP_SUPPORT_PANASONIC_PROTOCOL
318 if (proto == IRMP_PANASONIC_PROTOCOL) return 1;
319 #endif
320 #if IRMP_SUPPORT_MITSU_HEAVY_PROTOCOL
321 if (proto == IRMP_MITSU_HEAVY_PROTOCOL) return 1;
322 #endif
323 #if IRMP_SUPPORT_VINCENT_PROTOCOL
324 if (proto == IRMP_VINCENT_PROTOCOL) return 1;
325 #endif
326 #if IRMP_SUPPORT_SAMSUNGAH_PROTOCOL
327 if (proto == IRMP_SAMSUNGAH_PROTOCOL) return 1;
328 #endif
329 #if IRMP_SUPPORT_RADIO1_PROTOCOL
330 if (proto == IRMP_RADIO1_PROTOCOL) return 1;
331 #endif
332
333 return 0;
334 }
335
336 /**
337 * Print the names of all supported protocols, or the supported protocol
338 * numbers, if names are not enabled.
339 */
340 void print_supported_protocols(void)
341 {
342 printf("Supported IR protocols:");
343 for (int i = 0; i <= IRMP_N_PROTOCOLS; i++) {
344 if (irmp_protocol_is_supported(i)) {
345 #if IRMP_PROTOCOL_NAMES == 1
346 printf(" %s", irmp_protocol_names[i]);
347 #else
348 printf(" %d", i);
349 #endif
350 }
351 }
352 printf("\n");
353 }
354
355 /*--------------------------------------------------------------------------*/
356
357 /** Let the board led do something
358 *
359 * The led should blink with 1 Hz
360 */
361 void led_blink(void)
362 {
363 static uint32_t ts;
364
365 if (get_timer(ts) >= 500) {
366 ts = get_timer(0);
367 gpio_toggle(LED_PORT, LED_PIN);
368 }
369 }
370
371 int main (void)
372 {
373 IRMP_DATA irmp_data;
374
375 setup_clock_and_gpios();
376 setvbuf(stdout, NULL, _IONBF, 0);
377 serial_setup(CON_BAUDRATE);
378
379 printf("\nIRMP on STM32F103 with libopencm3 demo\n"
380 " System frequency: %luHz\n"
381 "IRMP timer input frequency (CK_INT): %luHz\n"
382 " IRMP interrupt frequency: %uHz\n",
383 rcc_ahb_frequency, timer_internal_clock_get(IRMP_TIMER), F_INTERRUPTS);
384
385 systick_setup();
386 irmp_timer_init(); // initialize timer for irmp
387 irmp_init(); // initialize irmp
388
389 print_supported_protocols();
390 for (;;)
391 {
392 led_blink();
393 if (irmp_get_data (&irmp_data))
394 {
395 printf("protocol: 0x%.2x", irmp_data.protocol);
396 #if IRMP_PROTOCOL_NAMES == 1
397 printf(" %-11s", irmp_protocol_names[irmp_data.protocol]);
398 #endif
399 printf(" adress: 0x%.4x command: 0x%.4x flags: 0x%.2x\n",
400 irmp_data.address, irmp_data.command, irmp_data.flags);
401 }
402 }
403 }