1 /*------------------------------------------------------------------------------
2 * irsnd-main.c - demo program to test the IRSND encoder on STM32F1 whith libopencm3
4 * Copyright (c) 2017 Leo C. <erbl259-lmu@yahoo.de>
6 * This demo program is derived from irsnd-main-avr.c, which is
7 * Copyright (c) 2010-2016 Frank Meyer - frank(at)fli4l.de
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.
13 * This demo runs on the Generic STM32F103C8T6 Development Board, aka bluepill.
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 *------------------------------------------------------------------------------
24 #include <libopencm3/stm32/rcc.h>
25 #include <libopencm3/stm32/gpio.h>
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
35 /* Toggle a pin on irmp timer isr entry and exit */
36 #ifndef DEBUG_IRMP_TIMER_INT
37 #define DEBUG_IRMP_TIMER_INT 0
40 #define LED_PORT GPIOC
41 #define LED_PIN GPIO13
42 #define LED_PORT_RCC RCC_GPIOC
44 #if DEBUG_IRMP_TIMER_INT
45 #define DEBUG_LED_PORT GPIOB
46 #define DEBUG_LED_PIN GPIO0
47 #define DEBUG_LED_PORT_RCC RCC_GPIOB
51 * Do all initialisations, that are not done by a specific module here.
53 static void setup_clock_and_gpios(void)
56 /* Default clock is 8MHz HSI */
57 //rcc_clock_setup_in_hse_8mhz_out_24mhz();
58 //rcc_clock_setup_in_hse_8mhz_out_72mhz();
61 /* Only the on board led is configured here */
63 rcc_periph_clock_enable(LED_PORT_RCC
);
65 /* Set GPIO13 (in GPIO port C) to 'output push-pull'. */
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
);
75 static void led_on(void)
77 gpio_clear(LED_PORT
, LED_PIN
);
80 static void led_off(void)
82 gpio_set(LED_PORT
, LED_PIN
);
85 static void debug_led_on(void)
87 #if DEBUG_IRMP_TIMER_INT
88 # if USE_OPENCM3_API /* Using API functions: */
89 gpio_clear(DEBUG_LED_PORT
, DEBUG_LED_PIN
);
91 GPIO_BRR(DEBUG_LED_PORT
) = DEBUG_LED_PIN
;
96 static void debug_led_off(void)
98 #if DEBUG_IRMP_TIMER_INT
99 # if USE_OPENCM3_API /* Using API functions: */
100 gpio_set(DEBUG_LED_PORT
, DEBUG_LED_PIN
);
102 GPIO_BSRR(DEBUG_LED_PORT
) = DEBUG_LED_PIN
;
107 /*--------------------------------------------------------------------------*/
109 /*--------------------------------------------------------------------------*/
111 #define IRSND_TICK_TIMER_NUMBER 3
112 #define IRSND_TICK_TIMER TIM3
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)
123 /** Retrieve the actual input clock of a timer
125 @param[in] timer_peripheral Unsigned int32. Timer register address base
126 @returns Unsigned int32. frequency value.
128 uint32_t timer_internal_clock_get(uint32_t timer_peripheral
)
130 uint32_t timer_frequency
;
132 /* Get preripheral bus frequency and prescaler mask */
134 timer_frequency
= rcc_apb1_frequency
;
136 if (timer_peripheral
< PERIPH_BASE_APB2
)
138 timer_frequency
= rcc_apb1_frequency
;
140 timer_frequency
= rcc_apb2_frequency
;
143 /* Timer clock is doubled, if the APB prescaler is greater than 1 */
144 if (timer_frequency
!= rcc_ahb_frequency
)
145 timer_frequency
*= 2;
147 return timer_frequency
;
151 * Intialize the irmp interrupt timer
153 void irsnd_tick_timer_init(void)
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
);
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
);
167 #if USE_OPENCM3_API /* Using API functions: */
169 /* Timer global mode:
173 * (These are actually default values after reset, so this call
174 * is strictly unnecessary, but demos the api for alternative settings)
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
);
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;
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
;
197 void IRSND_TICK_TIMER_ISR(void)
201 /* Clear update interrupt flag. */
202 #if USE_OPENCM3_API /* Using API functions: */
203 timer_clear_flag(IRSND_TICK_TIMER
, TIM_SR_UIF
);
205 IRSND_TICK_TIMER_SR
= ~TIM_SR_UIF
;
208 (void) irsnd_ISR(); // call irmp ISR
209 // call other timer interrupt routines...
214 /*---------------------------------------------------------------------------------------------------------------------------------------------------
216 *---------------------------------------------------------------------------------------------------------------------------------------------------
224 setup_clock_and_gpios();
226 irsnd_init(); // initialize irsnd
227 irsnd_tick_timer_init(); // initialize timer
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
238 irsnd_send_data (&irmp_data
, TRUE
); // send frame, wait for completion
239 while (irsnd_is_busy()) // wait till frame is
243 while (get_timer(ts
) < 1000)