diff --git a/src/drivers/drv_oreoled.h b/src/drivers/drv_oreoled.h index 4c749001b..0e63877c9 100644 --- a/src/drivers/drv_oreoled.h +++ b/src/drivers/drv_oreoled.h @@ -52,20 +52,23 @@ #define _OREOLEDIOCBASE (0x2d00) #define _OREOLEDIOC(_n) (_IOC(_OREOLEDIOCBASE, _n)) -/** set constant RGB values */ -#define OREOLED_SET_RGB _OREOLEDIOC(1) +/** set pattern */ +#define OREOLED_SET_PATTERN _OREOLEDIOC(1) -/** run macro */ -#define OREOLED_RUN_MACRO _OREOLEDIOC(2) +/** update pattern parameter */ +#define OREOLED_UPDATE_PARAM _OREOLEDIOC(2) + +/** set constant RGB value */ +#define OREOLED_SET_RGB _OREOLEDIOC(3) -/** send bytes */ -#define OREOLED_SEND_BYTES _OREOLEDIOC(3) +/** run macro */ +#define OREOLED_RUN_MACRO _OREOLEDIOC(4) /** send reset */ -#define OREOLED_SEND_RESET _OREOLEDIOC(4) +#define OREOLED_SEND_RESET _OREOLEDIOC(5) /** force an i2c gencall */ -#define OREOLED_FORCE_SYNC _OREOLEDIOC(5) +#define OREOLED_FORCE_SYNC _OREOLEDIOC(6) /* Oreo LED driver supports up to 4 leds */ #define OREOLED_NUM_LEDS 4 @@ -89,14 +92,17 @@ * defined by hardware */ enum oreoled_pattern { OREOLED_PATTERN_OFF = 0, - OREOLED_PATTERN_SINE = 1, + OREOLED_PATTERN_BREATHE = 1, OREOLED_PATTERN_SOLID = 2, OREOLED_PATTERN_SIREN = 3, OREOLED_PATTERN_STROBE = 4, - OREOLED_PATTERN_FADEIN = 5, - OREOLED_PATTERN_FADEOUT = 6, - OREOLED_PATTERN_PARAMUPDATE = 7, - OREOLED_PATTERN_ENUM_COUNT + OREOLED_PATTERN_AVIATION_STROBE = 5, + OREOLED_PATTERN_FADEIN = 6, + OREOLED_PATTERN_FADEOUT = 7, + OREOLED_PATTERN_PARAMUPDATE = 8, + /* OREOLED_PATTERN_FWUPDATE = 9, use OREOLED_PARAM_MACRO_FWUPDATE instead */ + OREOLED_PATTERN_ENUM_COUNT, + OREOLED_PATTERN_PING = 0xAA // Special byte sent by the oreoled master startup sequence }; /* enum passed to OREOLED_SET_MODE ioctl() @@ -121,21 +127,42 @@ enum oreoled_param { * defined by hardware */ enum oreoled_macro { OREOLED_PARAM_MACRO_RESET = 0, - OREOLED_PARAM_MACRO_COLOUR_CYCLE = 1, - OREOLED_PARAM_MACRO_BREATH = 2, - OREOLED_PARAM_MACRO_STROBE = 3, - OREOLED_PARAM_MACRO_FADEIN = 4, - OREOLED_PARAM_MACRO_FADEOUT = 5, - OREOLED_PARAM_MACRO_RED = 6, - OREOLED_PARAM_MACRO_GREEN = 7, - OREOLED_PARAM_MACRO_BLUE = 8, - OREOLED_PARAM_MACRO_YELLOW = 9, - OREOLED_PARAM_MACRO_WHITE = 10, - OREOLED_PARAM_MACRO_AUTOMOBILE = 11, - OREOLED_PARAM_MACRO_AVIATION = 12, + OREOLED_PARAM_MACRO_FWUPDATE = 1, + OREOLED_PARAM_MACRO_BREATHE = 2, + OREOLED_PARAM_MACRO_FADE_OUT = 3, + OREOLED_PARAM_MACRO_AMBER = 4, + OREOLED_PARAM_MACRO_WHITE = 5, + OREOLED_PARAM_MACRO_AUTOMOBILE = 6, + OREOLED_PARAM_MACRO_AVIATION = 7, OREOLED_PARAM_MACRO_ENUM_COUNT }; +/* + structure passed to OREOLED_SET_PATTERN ioctl() + */ +typedef struct { + uint8_t instance; + oreoled_pattern pattern; + uint8_t bias_red; + uint8_t bias_green; + uint8_t bias_blue; + uint8_t amplitude_red; + uint8_t amplitude_green; + uint8_t amplitude_blue; + uint16_t period; + int8_t repeat; + uint16_t phase_offset; +} oreoled_patternset_t; + +/* + structure passed to OREOLED_UPDATE_PARAM ioctl() + */ +typedef struct { + uint8_t instance; + oreoled_param param; + uint16_t value; +} oreoled_paramupdate_t; + /* structure passed to OREOLED_SET_RGB ioctl() Note that the driver scales the brightness to 0 to 255, regardless @@ -158,11 +185,10 @@ typedef struct { } oreoled_macrorun_t; /* - structure passed to send_bytes method (only used for testing) + structure used for storing raw commands */ typedef struct { uint8_t led_num; uint8_t num_bytes; uint8_t buff[OREOLED_CMD_LENGTH_MAX]; } oreoled_cmd_t; - diff --git a/src/drivers/oreoled/oreoled.cpp b/src/drivers/oreoled/oreoled.cpp index 3f49c3dd7..01f1bb71e 100644 --- a/src/drivers/oreoled/oreoled.cpp +++ b/src/drivers/oreoled/oreoled.cpp @@ -122,6 +122,8 @@ class OREOLED : public device::I2C uint8_t cmd_add_checksum(oreoled_cmd_t *cmd); + int queue_cmd(oreoled_cmd_t *cmd); + /* internal variables */ work_s _work; ///< work queue for scheduling reads bool _healthy[OREOLED_NUM_LEDS]; ///< health of each LED @@ -348,7 +350,7 @@ OREOLED::startup_discovery(void) /* prepare command to turn off LED */ cmd.led_num = i; - cmd.buff[0] = 0xAA; + cmd.buff[0] = OREOLED_PATTERN_PING; cmd.buff[1] = 0x55; cmd.buff[2] = OREOLED_PATTERN_OFF; cmd.num_bytes = 3; @@ -398,6 +400,33 @@ OREOLED::cmd_add_checksum(oreoled_cmd_t *cmd) return cmd->buff[checksum_idx]; } +int +OREOLED::queue_cmd(oreoled_cmd_t *cmd) +{ + int ret = -EINVAL; + + /* special handling for request to set all instances rgb values */ + if (cmd->led_num == OREOLED_ALL_INSTANCES) { + for (uint8_t i = 0; i < OREOLED_NUM_LEDS; i++) { + /* add command to queue for all healthy leds */ + if (_healthy[i]) { + cmd->led_num = i; + _cmd_queue->force(cmd); + ret = OK; + } + } + + } else if (cmd->led_num < OREOLED_NUM_LEDS) { + /* request to set individual instance's rgb value */ + if (_healthy[cmd->led_num]) { + _cmd_queue->force(cmd); + ret = OK; + } + } + + return ret; +} + int OREOLED::ioctl(struct file *filp, int cmd, unsigned long arg) { @@ -405,67 +434,84 @@ OREOLED::ioctl(struct file *filp, int cmd, unsigned long arg) oreoled_cmd_t new_cmd; switch (cmd) { - case OREOLED_SET_RGB: - /* set the specified color */ - new_cmd.led_num = ((oreoled_rgbset_t *) arg)->instance; - new_cmd.buff[0] = ((oreoled_rgbset_t *) arg)->pattern; + case OREOLED_SET_PATTERN: { + /* set the specified pattern and parameters */ + oreoled_patternset_t * pattern_args = (oreoled_patternset_t *) arg; + new_cmd.led_num = pattern_args->instance; + new_cmd.buff[0] = pattern_args->pattern; new_cmd.buff[1] = OREOLED_PARAM_BIAS_RED; - new_cmd.buff[2] = ((oreoled_rgbset_t *) arg)->red; + new_cmd.buff[2] = pattern_args->bias_red; new_cmd.buff[3] = OREOLED_PARAM_BIAS_GREEN; - new_cmd.buff[4] = ((oreoled_rgbset_t *) arg)->green; + new_cmd.buff[4] = pattern_args->bias_green; new_cmd.buff[5] = OREOLED_PARAM_BIAS_BLUE; - new_cmd.buff[6] = ((oreoled_rgbset_t *) arg)->blue; - new_cmd.num_bytes = 7; - - /* special handling for request to set all instances rgb values */ - if (new_cmd.led_num == OREOLED_ALL_INSTANCES) { - for (uint8_t i = 0; i < OREOLED_NUM_LEDS; i++) { - /* add command to queue for all healthy leds */ - if (_healthy[i]) { - new_cmd.led_num = i; - _cmd_queue->force(&new_cmd); - ret = OK; - } - } + new_cmd.buff[6] = pattern_args->bias_blue; + new_cmd.buff[7] = OREOLED_PARAM_AMPLITUDE_RED; + new_cmd.buff[8] = pattern_args->amplitude_red; + new_cmd.buff[9] = OREOLED_PARAM_AMPLITUDE_GREEN; + new_cmd.buff[10] = pattern_args->amplitude_green; + new_cmd.buff[11] = OREOLED_PARAM_AMPLITUDE_BLUE; + new_cmd.buff[12] = pattern_args->amplitude_blue; + new_cmd.buff[13] = OREOLED_PARAM_PERIOD; + new_cmd.buff[14] = pattern_args->period >> 8; + new_cmd.buff[15] = pattern_args->period & 0xFF; + new_cmd.buff[16] = OREOLED_PARAM_REPEAT; + new_cmd.buff[17] = pattern_args->repeat; + new_cmd.buff[18] = OREOLED_PARAM_PHASEOFFSET; + new_cmd.buff[19] = pattern_args->phase_offset >> 8; + new_cmd.buff[20] = pattern_args->phase_offset & 0xFF; + new_cmd.num_bytes = 21; + + return queue_cmd(&new_cmd); + } - } else if (new_cmd.led_num < OREOLED_NUM_LEDS) { - /* request to set individual instance's rgb value */ - if (_healthy[new_cmd.led_num]) { - _cmd_queue->force(&new_cmd); - ret = OK; - } + case OREOLED_UPDATE_PARAM: { + /* update the specified pattern parameter */ + oreoled_paramupdate_t * paramupdate_args = (oreoled_paramupdate_t *) arg; + new_cmd.led_num = paramupdate_args->instance; + new_cmd.buff[0] = OREOLED_PATTERN_PARAMUPDATE; + new_cmd.buff[1] = paramupdate_args->param; + + /* OREOLED_PARAM_PERIOD and OREOLED_PARAM_PHASEOFFSET values are 16bit */ + if (paramupdate_args->param == OREOLED_PARAM_PERIOD || + paramupdate_args->param == OREOLED_PARAM_PHASEOFFSET) { + new_cmd.buff[2] = paramupdate_args->value >> 8; + new_cmd.buff[3] = paramupdate_args->value & 0xFF; + new_cmd.num_bytes = 4; + } else { + new_cmd.buff[2] = paramupdate_args->value; + new_cmd.num_bytes = 3; } - return ret; + return queue_cmd(&new_cmd); + } - case OREOLED_RUN_MACRO: + case OREOLED_SET_RGB: { + /* set the specified color */ + oreoled_rgbset_t * rgb_args = (oreoled_rgbset_t *) arg; + new_cmd.led_num = rgb_args->instance; + new_cmd.buff[0] = rgb_args->pattern; + new_cmd.buff[1] = OREOLED_PARAM_BIAS_RED; + new_cmd.buff[2] = rgb_args->red; + new_cmd.buff[3] = OREOLED_PARAM_BIAS_GREEN; + new_cmd.buff[4] = rgb_args->green; + new_cmd.buff[5] = OREOLED_PARAM_BIAS_BLUE; + new_cmd.buff[6] = rgb_args->blue; + new_cmd.num_bytes = 7; + + return queue_cmd(&new_cmd); + } + + case OREOLED_RUN_MACRO: { /* run a macro */ - new_cmd.led_num = ((oreoled_macrorun_t *) arg)->instance; + oreoled_macrorun_t * macro_args = (oreoled_macrorun_t *) arg; + new_cmd.led_num = macro_args->instance; new_cmd.buff[0] = OREOLED_PATTERN_PARAMUPDATE; new_cmd.buff[1] = OREOLED_PARAM_MACRO; - new_cmd.buff[2] = ((oreoled_macrorun_t *) arg)->macro; + new_cmd.buff[2] = macro_args->macro; new_cmd.num_bytes = 3; - /* special handling for request to set all instances */ - if (new_cmd.led_num == OREOLED_ALL_INSTANCES) { - for (uint8_t i = 0; i < OREOLED_NUM_LEDS; i++) { - /* add command to queue for all healthy leds */ - if (_healthy[i]) { - new_cmd.led_num = i; - _cmd_queue->force(&new_cmd); - ret = OK; - } - } - - } else if (new_cmd.led_num < OREOLED_NUM_LEDS) { - /* request to set individual instance's rgb value */ - if (_healthy[new_cmd.led_num]) { - _cmd_queue->force(&new_cmd); - ret = OK; - } - } - - return ret; + return queue_cmd(&new_cmd); + } case OREOLED_SEND_RESET: /* send a reset */ @@ -486,31 +532,6 @@ OREOLED::ioctl(struct file *filp, int cmd, unsigned long arg) return ret; - case OREOLED_SEND_BYTES: - /* send bytes */ - new_cmd = *((oreoled_cmd_t *) arg); - - /* special handling for request to set all instances */ - if (new_cmd.led_num == OREOLED_ALL_INSTANCES) { - for (uint8_t i = 0; i < OREOLED_NUM_LEDS; i++) { - /* add command to queue for all healthy leds */ - if (_healthy[i]) { - new_cmd.led_num = i; - _cmd_queue->force(&new_cmd); - ret = OK; - } - } - - } else if (new_cmd.led_num < OREOLED_NUM_LEDS) { - /* request to set individual instance's rgb value */ - if (_healthy[new_cmd.led_num]) { - _cmd_queue->force(&new_cmd); - ret = OK; - } - } - - return ret; - case OREOLED_FORCE_SYNC: send_general_call(); break; diff --git a/src/drivers/oreoled/oreoled_bootloader/oreoled_bootloader_avr.cpp b/src/drivers/oreoled/oreoled_bootloader/oreoled_bootloader_avr.cpp index 94737a7f6..d2eb53ec0 100644 --- a/src/drivers/oreoled/oreoled_bootloader/oreoled_bootloader_avr.cpp +++ b/src/drivers/oreoled/oreoled_bootloader/oreoled_bootloader_avr.cpp @@ -277,7 +277,7 @@ OREOLED_BOOTLOADER_AVR::discover(void) { /* prepare command to turn off LED */ /* add two bytes of pre-amble to for higher signal to noise ratio */ - uint8_t msg[] = {0xAA, 0x55, OREOLED_PATTERN_OFF, 0x00}; + uint8_t msg[] = {OREOLED_PATTERN_PING, 0x55, OREOLED_PATTERN_OFF, 0x00}; /* attempt to contact each unhealthy LED */ for (uint8_t i = 0; i < OREOLED_NUM_LEDS; i++) { @@ -453,7 +453,7 @@ OREOLED_BOOTLOADER_AVR::app_ping(const int led_num) set_address(OREOLED_BASE_I2C_ADDR + boot_cmd.led_num); /* send a pattern off command */ - boot_cmd.buff[0] = 0xAA; + boot_cmd.buff[0] = OREOLED_PATTERN_PING; boot_cmd.buff[1] = 0x55; boot_cmd.buff[2] = OREOLED_PATTERN_OFF; boot_cmd.buff[3] = OREOLED_BASE_I2C_ADDR + boot_cmd.led_num; @@ -1199,4 +1199,4 @@ OREOLED_BOOTLOADER_AVR::print_response(const uint8_t* response, const uint8_t re } warnx("bl ver response XOR: 0x%x", response[checksum_idx]); -} \ No newline at end of file +}