summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLeo C2017-04-30 12:55:15 +0200
committerLeo C2017-04-30 12:55:15 +0200
commit43e6d5ec386f052ba7f2830e23fae0b4d474746b (patch)
tree842527a3a0750f69f8a5f679a2e5dec352d3e702
parentdbc48aa1421046023911f4fd12fa558becff11a5 (diff)
downloadirmp-demo-43e6d5ec386f052ba7f2830e23fae0b4d474746b.zip
Add IRSND demo program
-rw-r--r--Makefile13
-rw-r--r--irsnd-main.c249
2 files changed, 259 insertions, 3 deletions
diff --git a/Makefile b/Makefile
index 19cbdb7..038a6e8 100644
--- a/Makefile
+++ b/Makefile
@@ -19,12 +19,19 @@
DEFS += -DUSE_OPENCM3_API=0 #-DCON_BAUDRATE=38400
DEFS += -DDEBUG_IRMP_TIMER_INT=1
+CFLAGS += -save-temps
-BINARY = irmp-main
-OBJS += serial.o timer.o
+BINARY = $(BINARY_irsnd)
+OBJS = $(OBJS_irsnd)
+
+BINARY_irmp = irmp-main
+BINARY_irsnd= irsnd-main
+OBJS_irmp += serial.o timer.o
+OBJS_irsnd += timer.o
IRMP_DIR = irmp
-OBJS += $(IRMP_DIR)/irmp.o
+OBJS_irmp += $(IRMP_DIR)/irmp.o
+OBJS_irsnd += $(IRMP_DIR)/irsnd.o
DEFS += -I$(IRMP_DIR)
DEFS += -DF_INTERRUPTS=15000 -DIRMP_PROTOCOL_NAMES=1
diff --git a/irsnd-main.c b/irsnd-main.c
new file mode 100644
index 0000000..3387439
--- /dev/null
+++ b/irsnd-main.c
@@ -0,0 +1,249 @@
+/*------------------------------------------------------------------------------
+ * irsnd-main.c - demo program to test the IRSND encoder on STM32F1 whith libopencm3
+ *
+ * Copyright (c) 2017 Leo C. <erbl259-lmu@yahoo.de>
+ *
+ * This demo program is derived from irsnd-main-avr.c, which is
+ * Copyright (c) 2010-2016 Frank Meyer - frank(at)fli4l.de
+ *
+ * The program demonstrates the integration of IRSND in a libopencm3 environment,
+ * and how to use the libopencm3 api functions, or alternatively direct
+ * register access, using the macros defined by libopencm3.
+ *
+ * This demo runs on the Generic STM32F103C8T6 Development Board, aka bluepill.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *------------------------------------------------------------------------------
+ */
+
+#include "irsnd.h"
+#include "timer.h"
+#include <libopencm3/stm32/rcc.h>
+#include <libopencm3/stm32/gpio.h>
+
+
+/* The folloing macros can also be defined in the Makefile */
+/* If 0 or undefined, use direct register access where appropriate,
+ * else use the libopencm3 api functions everywhere. */
+#ifndef USE_OPENCM3_API
+#define USE_OPENCM3_API 0
+#endif
+
+/* Toggle a pin on irmp timer isr entry and exit */
+#ifndef DEBUG_IRMP_TIMER_INT
+#define DEBUG_IRMP_TIMER_INT 0
+#endif
+
+#define LED_PORT GPIOC
+#define LED_PIN GPIO13
+#define LED_PORT_RCC RCC_GPIOC
+
+#if DEBUG_IRMP_TIMER_INT
+#define DEBUG_LED_PORT GPIOA
+#define DEBUG_LED_PIN GPIO2
+#define DEBUG_LED_PORT_RCC RCC_GPIOA
+#endif
+
+/**
+ * Do all initialisations, that are not done by a specific module here.
+ */
+static void setup_clock_and_gpios(void)
+{
+ /* Clock setup */
+ /* Default clock is 8MHz HSI */
+ //rcc_clock_setup_in_hse_8mhz_out_24mhz();
+ //rcc_clock_setup_in_hse_8mhz_out_72mhz();
+
+ /* GPIO setup */
+ /* Only the on board led is configured here */
+
+ rcc_periph_clock_enable(LED_PORT_RCC);
+
+ /* Set GPIO13 (in GPIO port C) to 'output push-pull'. */
+ /* Manually: */
+ // GPIOC_CRH = (GPIO_CNF_OUTPUT_PUSHPULL << (((12 - 8) * 4) + 2));
+ // GPIOC_CRH |= (GPIO_MODE_OUTPUT_2_MHZ << ((12 - 8) * 4));
+ /* Using API functions: */
+ gpio_set(LED_PORT, LED_PIN); /* set output register high (led off) */
+ gpio_set_mode(LED_PORT, GPIO_MODE_OUTPUT_2_MHZ,
+ GPIO_CNF_OUTPUT_PUSHPULL, LED_PIN);
+}
+
+static void led_on(void)
+{
+ gpio_clear(LED_PORT, LED_PIN);
+}
+
+static void led_off(void)
+{
+ gpio_set(LED_PORT, LED_PIN);
+}
+
+static void debug_led_on(void)
+{
+#if DEBUG_IRMP_TIMER_INT
+# if USE_OPENCM3_API /* Using API functions: */
+ gpio_clear(DEBUG_LED_PORT, DEBUG_LED_PIN);
+#else
+ GPIO_BRR(GPIOA) = GPIO2;
+# endif
+#endif
+}
+
+static void debug_led_off(void)
+{
+#if DEBUG_IRMP_TIMER_INT
+# if USE_OPENCM3_API /* Using API functions: */
+ gpio_set(DEBUG_LED_PORT, DEBUG_LED_PIN);
+#else
+ GPIO_BSRR(GPIOA) = GPIO2;
+# endif
+#endif
+}
+
+/*--------------------------------------------------------------------------*/
+/* IRMP */
+/*--------------------------------------------------------------------------*/
+
+#define IRSND_TICK_TIMER_NUMBER 3
+#define IRSND_TICK_TIMER TIM3
+
+#define IRSND_TICK_TIMER_CR1 TIM_CR1(IRSND_TICK_TIMER)
+#define IRSND_TICK_TIMER_DIER TIM_DIER(IRSND_TICK_TIMER)
+#define IRSND_TICK_TIMER_SR TIM_SR(IRSND_TICK_TIMER)
+#define IRSND_TICK_TIMER_ARR TIM_ARR(IRSND_TICK_TIMER)
+#define IRSND_TICK_TIMER_RCC CONCAT(RCC_TIM, IRSND_TICK_TIMER_NUMBER)
+#define NVIC_IRSND_TICK_TIMER_IRQ CONCAT(CONCAT(NVIC_TIM, IRSND_TICK_TIMER_NUMBER), _IRQ)
+#define IRSND_TICK_TIMER_ISR CONCAT(CONCAT(tim, IRSND_TICK_TIMER_NUMBER), _isr)
+
+
+/** Retrieve the actual input clock of a timer
+
+@param[in] timer_peripheral Unsigned int32. Timer register address base
+@returns Unsigned int32. frequency value.
+*/
+uint32_t timer_internal_clock_get(uint32_t timer_peripheral)
+{
+ uint32_t timer_frequency;
+
+ /* Get preripheral bus frequency and prescaler mask */
+#ifdef STM32F0
+ timer_frequency = rcc_apb1_frequency;
+#else
+ if (timer_peripheral < PERIPH_BASE_APB2)
+ {
+ timer_frequency = rcc_apb1_frequency;
+ } else {
+ timer_frequency = rcc_apb2_frequency;
+ }
+#endif /* STM32F0 */
+ /* Timer clock is doubled, if the APB prescaler is greater than 1 */
+ if (timer_frequency != rcc_ahb_frequency)
+ timer_frequency *= 2;
+
+ return timer_frequency;
+}
+
+/**
+ * Intialize the irmp interrupt timer
+ */
+void irsnd_tick_timer_init(void)
+{
+#if DEBUG_IRMP_TIMER_INT
+ /* Output pin for debugging */
+ rcc_periph_clock_enable(DEBUG_LED_PORT_RCC);
+ gpio_set_mode(DEBUG_LED_PORT, GPIO_MODE_OUTPUT_2_MHZ,
+ GPIO_CNF_OUTPUT_PUSHPULL, DEBUG_LED_PIN);
+#endif
+ /* Enable timer clock. */
+ rcc_periph_clock_enable(IRSND_TICK_TIMER_RCC);
+ nvic_set_priority(NVIC_IRSND_TICK_TIMER_IRQ, 4*16);
+ nvic_enable_irq(NVIC_IRSND_TICK_TIMER_IRQ);
+
+#if USE_OPENCM3_API /* Using API functions: */
+
+ /* Timer global mode:
+ * - No divider
+ * - Alignment edge
+ * - Direction up
+ * (These are actually default values after reset, so this call
+ * is strictly unnecessary, but demos the api for alternative settings)
+ */
+ timer_set_mode(IRSND_TICK_TIMER, TIM_CR1_CKD_CK_INT,
+ TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP);
+ timer_set_period(IRSND_TICK_TIMER, timer_internal_clock_get(IRSND_TICK_TIMER) / F_INTERRUPTS - 1);
+ /* Enable timer update interrupt */
+ timer_enable_irq(IRSND_TICK_TIMER, TIM_DIER_UIE);
+ /* Counter enable. */
+ timer_enable_counter(IRSND_TICK_TIMER);
+
+#else /* Manually */
+
+ IRSND_TICK_TIMER_CR1 = TIM_CR1_CKD_CK_INT | TIM_CR1_CMS_EDGE | TIM_CR1_DIR_UP;
+ IRSND_TICK_TIMER_ARR = timer_internal_clock_get(IRSND_TICK_TIMER) / F_INTERRUPTS - 1;
+
+ /* Enable timer update interrupt */
+ IRSND_TICK_TIMER_DIER = TIM_DIER_UIE;
+ /* Finally enable the timer */
+ IRSND_TICK_TIMER_CR1 |= TIM_CR1_CEN;
+
+#endif
+}
+
+void IRSND_TICK_TIMER_ISR(void)
+{
+ debug_led_on();
+
+ /* Clear update interrupt flag. */
+#if USE_OPENCM3_API /* Using API functions: */
+ timer_clear_flag(IRSND_TICK_TIMER, TIM_SR_UIF);
+#else
+ IRSND_TICK_TIMER_SR = ~TIM_SR_UIF;
+#endif
+
+ (void) irsnd_ISR(); // call irmp ISR
+ // call other timer interrupt routines...
+
+ debug_led_off();
+}
+
+/*---------------------------------------------------------------------------------------------------------------------------------------------------
+ * MAIN: main routine
+ *---------------------------------------------------------------------------------------------------------------------------------------------------
+ */
+int
+main (void)
+{
+ static uint32_t ts;
+ IRMP_DATA irmp_data;
+
+ setup_clock_and_gpios();
+ systick_setup();
+ irsnd_init(); // initialize irsnd
+ irsnd_tick_timer_init(); // initialize timer
+
+ ts = get_timer(0);
+ while (get_timer(ts) < 200)
+ ;
+
+ for (;;)
+ {
+ irmp_data.protocol = IRMP_NEC_PROTOCOL; // use NEC protocol
+ irmp_data.address = 0x4eb1; // set address to 0x00FF
+ irmp_data.command = 0x001e; // set command to 0x0001
+ irmp_data.flags = 0; // don't repeat frame
+ ts = get_timer(0);
+
+ led_on();
+ irsnd_send_data (&irmp_data, TRUE); // send frame, wait for completion
+ while (irsnd_is_busy())
+ ;
+ led_off();
+
+ while (get_timer(ts) < 2000)
+ ;
+ }
+}