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