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