ardupilot/libraries/AP_Notify/OreoLED_I2C.h
Andrew Tridgell 891447d798 AP_Notify: fixed LED sync for OreoLED
the NuttX driver tries to send a sync every 4s, but actually ends up
sending at around 4.1s due to poor scheduling. Rather strangely, the
oreoled firmware seems to rely on this inaccuracy, and doesn't work
with exactly 4s under ChibiOS
2018-11-26 13:29:40 +11:00

199 lines
7.2 KiB
C++

/*
OreoLED I2C driver
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 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <AP_HAL/AP_HAL.h>
#include "NotifyDevice.h"
#define OREOLED_NUM_LEDS 4 // maximum number of individual LEDs connected to the oreo led cpu
#define OREOLED_INSTANCE_ALL 0xff // instance number to indicate all LEDs (used for set_rgb and set_macro)
#define OREOLED_BRIGHT 0xff // maximum brightness when flying (disconnected from usb)
#define CUSTOM_HEADER_LENGTH 4 // number of bytes in the custom LED buffer that are used to identify the command
class OreoLED_I2C : public NotifyDevice {
public:
// constuctor
OreoLED_I2C(uint8_t bus, uint8_t theme);
// init - initialised the device
bool init(void) override;
// update - updates device according to timed_updated. Should be
// called at 50Hz
void update() override;
// handle a LED_CONTROL message, by default device ignore message
void handle_led_control(mavlink_message_t *msg) override;
private:
enum oreoled_pattern {
OREOLED_PATTERN_OFF = 0,
OREOLED_PATTERN_SINE = 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
};
/* enum of available macros 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_ENUM_COUNT
};
/* enum passed to OREOLED_SET_MODE defined by hardware */
enum oreoled_param {
OREOLED_PARAM_BIAS_RED = 0,
OREOLED_PARAM_BIAS_GREEN = 1,
OREOLED_PARAM_BIAS_BLUE = 2,
OREOLED_PARAM_AMPLITUDE_RED = 3,
OREOLED_PARAM_AMPLITUDE_GREEN = 4,
OREOLED_PARAM_AMPLITUDE_BLUE = 5,
OREOLED_PARAM_PERIOD = 6,
OREOLED_PARAM_REPEAT = 7,
OREOLED_PARAM_PHASEOFFSET = 8,
OREOLED_PARAM_MACRO = 9,
OREOLED_PARAM_RESET = 10,
OREOLED_PARAM_APP_CHECKSUM = 11,
OREOLED_PARAM_ENUM_COUNT
};
// update_timer - called by scheduler and updates PX4 driver with commands
void update_timer(void);
// set_rgb - set color as a combination of red, green and blue values for one or all LEDs, pattern defaults to solid color
void set_rgb(uint8_t instance, uint8_t red, uint8_t green, uint8_t blue);
// set_rgb - set color as a combination of red, green and blue values for one or all LEDs, using the specified pattern
void set_rgb(uint8_t instance, enum oreoled_pattern pattern, uint8_t red, uint8_t green, uint8_t blue);
// set_rgb - set color as a combination of red, green and blue values for one or all LEDs, using the specified pattern and other parameters
void set_rgb(uint8_t instance, oreoled_pattern pattern, uint8_t red, uint8_t green, uint8_t blue,
uint8_t amplitude_red, uint8_t amplitude_green, uint8_t amplitude_blue,
uint16_t period, uint16_t phase_offset);
// set_macro - set macro for one or all LEDs
void set_macro(uint8_t instance, enum oreoled_macro macro);
// send_sync - force a syncronisation of the all LED's
void send_sync();
// functions to set LEDs to specific patterns. These functions return true if no further updates should be made to LEDs this iteration
bool slow_counter(void);
bool mode_firmware_update(void);
bool mode_init(void);
bool mode_failsafe_radio(void);
bool set_standard_colors(void);
bool mode_failsafe_batt(void);
bool mode_auto_flight(void);
bool mode_pilot_flight(void);
// Clear the desired state
void clear_state(void);
// oreo led modes (pattern, macro or rgb)
enum oreoled_mode {
OREOLED_MODE_NONE=0,
OREOLED_MODE_MACRO,
OREOLED_MODE_RGB,
OREOLED_MODE_RGB_EXTENDED,
};
// Oreo LED modes
enum Oreo_LED_Theme {
OreoLED_Disabled = 0,
OreoLED_Aircraft = 1,
OreoLED_Automobile = 2,
};
// oreo_state structure holds possible state of an led
struct oreo_state {
enum oreoled_mode mode;
enum oreoled_pattern pattern;
enum oreoled_macro macro;
uint8_t red;
uint8_t green;
uint8_t blue;
uint8_t amplitude_red;
uint8_t amplitude_green;
uint8_t amplitude_blue;
uint16_t period;
int8_t repeat;
uint16_t phase_offset;
oreo_state();
void clear_state();
void set_macro(oreoled_macro new_macro);
void set_rgb(enum oreoled_pattern new_pattern, uint8_t new_red, uint8_t new_green, uint8_t new_blue);
void set_rgb(enum oreoled_pattern new_pattern, uint8_t new_red, uint8_t new_green,
uint8_t new_blue, uint8_t new_amplitude_red, uint8_t new_amplitude_green, uint8_t new_amplitude_blue,
uint16_t new_period, uint16_t new_phase_offset);
bool operator==(const oreo_state &os);
};
typedef struct {
uint8_t led_num;
uint8_t num_bytes;
uint8_t buff[32];
} oreoled_cmd_t;
// send a I2C command
bool command_send(oreoled_cmd_t &cmd);
void boot_leds(void);
// private members
uint8_t _bus;
HAL_Semaphore_Recursive _sem;
AP_HAL::OwnPtr<AP_HAL::I2CDevice> _dev;
bool _send_required; // true when we need to send an update to at least one led
oreo_state _state_desired[OREOLED_NUM_LEDS]; // desired state
oreo_state _state_sent[OREOLED_NUM_LEDS]; // last state sent to led
uint8_t _pattern_override; // holds last processed pattern override, 0 if we are not overriding a pattern
uint8_t _oreo_theme; // theme (1=AirCraft, 2=Ground Vehicle)
uint8_t _rear_color_r = 255; // the rear LED red value
uint8_t _rear_color_g = 255; // the rear LED green value
uint8_t _rear_color_b = 255; // the rear LED blue value
uint8_t _slow_count;
uint8_t _boot_count;
uint32_t _last_boot_ms;
uint32_t _last_sync_ms;
};