]> cloudbase.mooo.com Git - irmp-demo.git/blame - irsnd-main.c
Change port pin for debug led to enable logging on usart2.
[irmp-demo.git] / irsnd-main.c
CommitLineData
43e6d5ec
L
1/*------------------------------------------------------------------------------\r
2 * irsnd-main.c - demo program to test the IRSND encoder on STM32F1 whith libopencm3\r
3 *\r
4 * Copyright (c) 2017 Leo C. <erbl259-lmu@yahoo.de>\r
5 *\r
6 * This demo program is derived from irsnd-main-avr.c, which is\r
7 * Copyright (c) 2010-2016 Frank Meyer - frank(at)fli4l.de\r
8 *\r
9 * The program demonstrates the integration of IRSND in a libopencm3 environment,\r
10 * and how to use the libopencm3 api functions, or alternatively direct\r
11 * register access, using the macros defined by libopencm3.\r
12 *\r
13 * This demo runs on the Generic STM32F103C8T6 Development Board, aka bluepill.\r
14 *\r
15 * This program is free software; you can redistribute it and/or modify\r
16 * it under the terms of the GNU General Public License as published by\r
17 * the Free Software Foundation; either version 2 of the License, or\r
18 * (at your option) any later version.\r
19 *------------------------------------------------------------------------------\r
20 */\r
21\r
22#include "irsnd.h"\r
23#include "timer.h"\r
24#include <libopencm3/stm32/rcc.h>\r
25#include <libopencm3/stm32/gpio.h>\r
26\r
27\r
28/* The folloing macros can also be defined in the Makefile */\r
29/* If 0 or undefined, use direct register access where appropriate,\r
30 * else use the libopencm3 api functions everywhere. */\r
31#ifndef USE_OPENCM3_API\r
32#define USE_OPENCM3_API 0\r
33#endif\r
34\r
35/* Toggle a pin on irmp timer isr entry and exit */\r
36#ifndef DEBUG_IRMP_TIMER_INT\r
37#define DEBUG_IRMP_TIMER_INT 0\r
38#endif\r
39\r
40#define LED_PORT GPIOC\r
41#define LED_PIN GPIO13\r
42#define LED_PORT_RCC RCC_GPIOC\r
43\r
44#if DEBUG_IRMP_TIMER_INT\r
1cb9eb42
L
45#define DEBUG_LED_PORT GPIOB\r
46#define DEBUG_LED_PIN GPIO0\r
47#define DEBUG_LED_PORT_RCC RCC_GPIOB\r
43e6d5ec
L
48#endif\r
49\r
50/**\r
51 * Do all initialisations, that are not done by a specific module here.\r
52 */\r
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
58 //rcc_clock_setup_in_hse_8mhz_out_72mhz();\r
59\r
60 /* GPIO setup */\r
61 /* Only the on board led is configured here */\r
62\r
63 rcc_periph_clock_enable(LED_PORT_RCC);\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
75static void led_on(void)\r
76{\r
77 gpio_clear(LED_PORT, LED_PIN);\r
78}\r
79\r
80static void led_off(void)\r
81{\r
82 gpio_set(LED_PORT, LED_PIN);\r
83}\r
84\r
85static void debug_led_on(void)\r
86{\r
87#if DEBUG_IRMP_TIMER_INT\r
8dec0d95 88# if USE_OPENCM3_API /* Using API functions: */\r
43e6d5ec
L
89 gpio_clear(DEBUG_LED_PORT, DEBUG_LED_PIN);\r
90#else\r
1cb9eb42 91 GPIO_BRR(DEBUG_LED_PORT) = DEBUG_LED_PIN;\r
43e6d5ec
L
92# endif\r
93#endif\r
94}\r
95\r
96static void debug_led_off(void)\r
97{\r
98#if DEBUG_IRMP_TIMER_INT\r
8dec0d95 99# if USE_OPENCM3_API /* Using API functions: */\r
43e6d5ec
L
100 gpio_set(DEBUG_LED_PORT, DEBUG_LED_PIN);\r
101#else\r
1cb9eb42 102 GPIO_BSRR(DEBUG_LED_PORT) = DEBUG_LED_PIN;\r
43e6d5ec
L
103# endif\r
104#endif\r
105}\r
106\r
107/*--------------------------------------------------------------------------*/\r
108/* IRMP */\r
109/*--------------------------------------------------------------------------*/\r
110\r
111#define IRSND_TICK_TIMER_NUMBER 3\r
112#define IRSND_TICK_TIMER TIM3\r
113\r
114#define IRSND_TICK_TIMER_CR1 TIM_CR1(IRSND_TICK_TIMER)\r
115#define IRSND_TICK_TIMER_DIER TIM_DIER(IRSND_TICK_TIMER)\r
116#define IRSND_TICK_TIMER_SR TIM_SR(IRSND_TICK_TIMER)\r
117#define IRSND_TICK_TIMER_ARR TIM_ARR(IRSND_TICK_TIMER)\r
118#define IRSND_TICK_TIMER_RCC CONCAT(RCC_TIM, IRSND_TICK_TIMER_NUMBER)\r
119#define NVIC_IRSND_TICK_TIMER_IRQ CONCAT(CONCAT(NVIC_TIM, IRSND_TICK_TIMER_NUMBER), _IRQ)\r
120#define IRSND_TICK_TIMER_ISR CONCAT(CONCAT(tim, IRSND_TICK_TIMER_NUMBER), _isr)\r
121\r
122\r
123/** Retrieve the actual input clock of a timer\r
124\r
125@param[in] timer_peripheral Unsigned int32. Timer register address base\r
126@returns Unsigned int32. frequency value.\r
127*/\r
128uint32_t timer_internal_clock_get(uint32_t timer_peripheral)\r
129{\r
130 uint32_t timer_frequency;\r
131\r
132 /* Get preripheral bus frequency and prescaler mask */\r
133#ifdef STM32F0\r
134 timer_frequency = rcc_apb1_frequency;\r
135#else\r
8dec0d95 136 if (timer_peripheral < PERIPH_BASE_APB2)\r
43e6d5ec
L
137 {\r
138 timer_frequency = rcc_apb1_frequency;\r
8dec0d95 139 } else {\r
43e6d5ec
L
140 timer_frequency = rcc_apb2_frequency;\r
141 }\r
142#endif /* STM32F0 */\r
143 /* Timer clock is doubled, if the APB prescaler is greater than 1 */\r
144 if (timer_frequency != rcc_ahb_frequency)\r
145 timer_frequency *= 2;\r
146\r
8dec0d95 147 return timer_frequency;\r
43e6d5ec
L
148}\r
149\r
150/**\r
151 * Intialize the irmp interrupt timer\r
152 */\r
153void irsnd_tick_timer_init(void)\r
154{\r
155#if DEBUG_IRMP_TIMER_INT\r
156 /* Output pin for debugging */\r
157 rcc_periph_clock_enable(DEBUG_LED_PORT_RCC);\r
8dec0d95 158 gpio_set(DEBUG_LED_PORT, DEBUG_LED_PIN);\r
43e6d5ec
L
159 gpio_set_mode(DEBUG_LED_PORT, GPIO_MODE_OUTPUT_2_MHZ,\r
160 GPIO_CNF_OUTPUT_PUSHPULL, DEBUG_LED_PIN);\r
161#endif\r
8dec0d95 162 /* Enable timer clock. */\r
43e6d5ec
L
163 rcc_periph_clock_enable(IRSND_TICK_TIMER_RCC);\r
164 nvic_set_priority(NVIC_IRSND_TICK_TIMER_IRQ, 4*16);\r
8dec0d95
L
165 nvic_enable_irq(NVIC_IRSND_TICK_TIMER_IRQ);\r
166\r
167#if USE_OPENCM3_API /* Using API functions: */\r
168\r
169 /* Timer global mode:\r
170 * - No divider\r
171 * - Alignment edge\r
172 * - Direction up\r
173 * (These are actually default values after reset, so this call\r
174 * is strictly unnecessary, but demos the api for alternative settings)\r
175 */\r
176 timer_set_mode(IRSND_TICK_TIMER, TIM_CR1_CKD_CK_INT,\r
43e6d5ec 177 TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP);\r
8dec0d95 178 timer_set_period(IRSND_TICK_TIMER, timer_internal_clock_get(IRSND_TICK_TIMER) / F_INTERRUPTS - 1);\r
43e6d5ec 179 /* Enable timer update interrupt */\r
8dec0d95
L
180 timer_enable_irq(IRSND_TICK_TIMER, TIM_DIER_UIE);\r
181 /* Counter enable. */\r
182 timer_enable_counter(IRSND_TICK_TIMER);\r
43e6d5ec
L
183\r
184#else /* Manually */\r
185\r
186 IRSND_TICK_TIMER_CR1 = TIM_CR1_CKD_CK_INT | TIM_CR1_CMS_EDGE | TIM_CR1_DIR_UP;\r
187 IRSND_TICK_TIMER_ARR = timer_internal_clock_get(IRSND_TICK_TIMER) / F_INTERRUPTS - 1;\r
188\r
189 /* Enable timer update interrupt */\r
190 IRSND_TICK_TIMER_DIER = TIM_DIER_UIE;\r
191 /* Finally enable the timer */\r
192 IRSND_TICK_TIMER_CR1 |= TIM_CR1_CEN;\r
193\r
194#endif\r
195}\r
196\r
197void IRSND_TICK_TIMER_ISR(void)\r
198{\r
199 debug_led_on();\r
200\r
201 /* Clear update interrupt flag. */\r
8dec0d95 202#if USE_OPENCM3_API /* Using API functions: */\r
43e6d5ec
L
203 timer_clear_flag(IRSND_TICK_TIMER, TIM_SR_UIF);\r
204#else\r
205 IRSND_TICK_TIMER_SR = ~TIM_SR_UIF;\r
206#endif\r
207\r
208 (void) irsnd_ISR(); // call irmp ISR\r
209 // call other timer interrupt routines...\r
210\r
211 debug_led_off();\r
212}\r
213\r
214/*---------------------------------------------------------------------------------------------------------------------------------------------------\r
215 * MAIN: main routine\r
216 *---------------------------------------------------------------------------------------------------------------------------------------------------\r
217 */\r
218int\r
219main (void)\r
220{\r
221 static uint32_t ts;\r
222 IRMP_DATA irmp_data;\r
223\r
224 setup_clock_and_gpios();\r
225 systick_setup();\r
226 irsnd_init(); // initialize irsnd\r
227 irsnd_tick_timer_init(); // initialize timer\r
228\r
43e6d5ec
L
229 for (;;)\r
230 {\r
231 irmp_data.protocol = IRMP_NEC_PROTOCOL; // use NEC protocol\r
8dec0d95
L
232 irmp_data.address = 0x4eb1; // Marantz RMC-12\r
233 irmp_data.command = 0x001e; // SYSTEM 1 POWER\r
43e6d5ec
L
234 irmp_data.flags = 0; // don't repeat frame\r
235 ts = get_timer(0);\r
236\r
237 led_on();\r
238 irsnd_send_data (&irmp_data, TRUE); // send frame, wait for completion\r
8dec0d95
L
239 while (irsnd_is_busy()) // wait till frame is\r
240 ; // completely sent\r
43e6d5ec
L
241 led_off();\r
242\r
8dec0d95 243 while (get_timer(ts) < 1000)\r
43e6d5ec
L
244 ;\r
245 }\r
246}\r