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