diff --git a/epicardium/drivers/ir.c b/epicardium/drivers/ir.c new file mode 100644 index 0000000000000000000000000000000000000000..c17922da2701b35cb4006124bfb3ab20abc04d7d --- /dev/null +++ b/epicardium/drivers/ir.c @@ -0,0 +1,80 @@ +#include "leds.h" +#include "pmic.h" +#include "FreeRTOS.h" +#include "task.h" +#include "epicardium.h" +#include "max32665.h" +#include "gpio.h" +#include "modules/modules.h" +#include "drivers/drivers.h" + +#include <stdbool.h> + +//#define KHZ38_PERIOD (340) +#define KHZ38_PERIOD (310) + +static const uint32_t NEC_LEAD_IN = 38e3 * 9e-3; +static const uint32_t NEC_SPACE = 38e3 * 4.5e-3; + +static const uint32_t NEC_ONE_T1 = 38e3 * 562.5e-6; +static const uint32_t NEC_ONE_T2 = 38e3 * 1687.5e-6; + +static const uint32_t NEC_ZERO_T1 = 38e3 * 562.5e-6; +static const uint32_t NEC_ZERO_T2 = 38e3 * 562.5e-6; + +static const uint32_t NEC_LEAD_OUT = 38e3 * 562.5e-6; + +static inline __attribute__((always_inline)) void +delay_ticks(uint32_t ticks) +{ + volatile uint32_t counter = ticks; + while (--counter) { + }; +} + +static inline __attribute__((always_inline)) void +epic_ir_transmit_wave(gpio_cfg_t *pin, uint32_t half_period, uint32_t count) +{ + while(count--) { + GPIO_OutSet(pin); + delay_ticks(half_period); + GPIO_OutClr(pin); + delay_ticks(half_period); + } +} + +static void ir_transmit_nec_bit(gpio_cfg_t *pin,uint8_t bit) +{ + if(bit) { + epic_ir_transmit_wave(pin, KHZ38_PERIOD/2, NEC_ONE_T1); + delay_ticks(NEC_ONE_T2 * KHZ38_PERIOD); + } else { + epic_ir_transmit_wave(pin, KHZ38_PERIOD/2, NEC_ZERO_T1); + delay_ticks(NEC_ZERO_T2 * KHZ38_PERIOD); + } +} + +static void ir_transmit_nec_byte(gpio_cfg_t *pin, uint8_t byte) +{ + for(uint32_t i = 0; i < 8; i++) { + ir_transmit_nec_bit(pin, byte & (1<<i)); + } +} + +void epic_ir_transmit_nec(uint8_t pin, uint8_t address, uint8_t command) +{ + gpio_cfg_t *pin_cfg = &gpio_configs[pin]; + + //if ((epic_gpio_get_pin_mode(pin) & EPIC_GPIO_MODE_OUT) == 0) { + // epic_gpio_set_pin_mode(pin, EPIC_GPIO_MODE_OUT); + //} + + epic_ir_transmit_wave(pin_cfg, KHZ38_PERIOD/2, NEC_LEAD_IN); + delay_ticks(NEC_SPACE * KHZ38_PERIOD); + ir_transmit_nec_byte(pin_cfg, address); + ir_transmit_nec_byte(pin_cfg, ~address); + ir_transmit_nec_byte(pin_cfg, command); + ir_transmit_nec_byte(pin_cfg, ~command); + epic_ir_transmit_wave(pin_cfg, KHZ38_PERIOD/2, NEC_LEAD_OUT); +} + diff --git a/epicardium/drivers/meson.build b/epicardium/drivers/meson.build index 3ad2367836a0e890cef090d507c552f260192f20..90f6216d3687cd328537245722d5230b0ebc1806 100644 --- a/epicardium/drivers/meson.build +++ b/epicardium/drivers/meson.build @@ -4,6 +4,7 @@ driver_sources = files( 'bme680.c', 'buttons.c', 'gpio.c', + 'ir.c', 'leds.c', 'light_sensor.c', 'max86150.c', diff --git a/epicardium/epicardium.h b/epicardium/epicardium.h index bc32e5cab772b6e952cecce64345c757857f3afe..0a79764a9f49efb67cf07335d7ea215cdc614d2f 100644 --- a/epicardium/epicardium.h +++ b/epicardium/epicardium.h @@ -148,6 +148,7 @@ typedef _Bool bool; #define API_USB_CDCACM 0x112 #define API_WS2812_WRITE 0x0120 +#define API_IR_TRANSMIT_NEC 0x0121 #define API_CONFIG_GET_STRING 0x130 #define API_CONFIG_GET_INTEGER 0x131 @@ -2314,7 +2315,7 @@ API(API_USB_CDCACM, int epic_usb_cdcacm(void)); * .. versionadded:: 1.10 */ API(API_WS2812_WRITE, void epic_ws2812_write(uint8_t pin, uint8_t *pixels, uint32_t n_bytes)); - +API(API_IR_TRANSMIT_NEC, void epic_ir_transmit_nec(uint8_t pin, uint8_t address, uint8_t command)); /** * Configuration diff --git a/pycardium/modules/qstrdefs.h b/pycardium/modules/qstrdefs.h index 01f32c679c012a70d4ed1db0e8711b1bc861e3b6..2edc369b68d3d6d3a9a9ba0784e3ef5137223bf9 100644 --- a/pycardium/modules/qstrdefs.h +++ b/pycardium/modules/qstrdefs.h @@ -193,6 +193,7 @@ Q(MAX86150_PROX) /* ws2812 */ Q(ws2812) Q(set_all) +Q(transmit_nec) /* config */ Q(config) diff --git a/pycardium/modules/ws2812.c b/pycardium/modules/ws2812.c index 4df1d84a047981ef28d00d3f3801d1845cd44a46..180ded36cd2f008b97a64f66de22bec104001c73 100644 --- a/pycardium/modules/ws2812.c +++ b/pycardium/modules/ws2812.c @@ -36,10 +36,25 @@ static mp_obj_t mp_ws2812_set_all(mp_obj_t pin, mp_obj_t color_in) } static MP_DEFINE_CONST_FUN_OBJ_2(ws2812_set_all_obj, mp_ws2812_set_all); +static mp_obj_t mp_ws2812_transmit_nec(mp_obj_t pin, mp_obj_t address, mp_obj_t command) +{ + mp_int_t pin_int = mp_obj_get_int(pin); + mp_int_t address_int = mp_obj_get_int(address); + mp_int_t command_int = mp_obj_get_int(command); + + /* call epicardium to be fast enough */ + epic_ir_transmit_nec(pin_int, address_int, command_int); + + return mp_const_none; +} +static MP_DEFINE_CONST_FUN_OBJ_3(ws2812_transmit_nec_obj, mp_ws2812_transmit_nec); + + /* The globals table for this module */ static const mp_rom_map_elem_t ws2812_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_ws2812) }, { MP_ROM_QSTR(MP_QSTR_set_all), MP_ROM_PTR(&ws2812_set_all_obj) }, + { MP_ROM_QSTR(MP_QSTR_transmit_nec), MP_ROM_PTR(&ws2812_transmit_nec_obj) }, }; static MP_DEFINE_CONST_DICT(ws2812_module_globals, ws2812_module_globals_table);