mirror of https://github.com/ArduPilot/ardupilot
AP_Notify: OreoLED rework
Reworked the process flow. Created the aviation vs rover themes. Created visual operator feedback for prearm checks, GPS, EKF, gyro init, radio failsafe, and low battery. This also includes work by Hugh Eaves to open up the full extended properties of the Oreo LEDs. Not only are far more functions available, but you can override and do custom things via mavlink.
This commit is contained in:
parent
ddd327e365
commit
fc3406d07f
|
@ -21,33 +21,35 @@
|
||||||
#if CONFIG_HAL_BOARD == HAL_BOARD_PX4
|
#if CONFIG_HAL_BOARD == HAL_BOARD_PX4
|
||||||
#include <AP_BoardConfig/AP_BoardConfig.h>
|
#include <AP_BoardConfig/AP_BoardConfig.h>
|
||||||
#include "OreoLED_PX4.h"
|
#include "OreoLED_PX4.h"
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include <drivers/drv_oreoled.h>
|
#include <drivers/drv_oreoled.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
#include "AP_Notify.h"
|
#include "AP_Notify.h"
|
||||||
|
|
||||||
extern const AP_HAL::HAL& hal;
|
|
||||||
|
|
||||||
#define OREOLED_BACKLEFT 0 // back left led instance number
|
#define OREOLED_BACKLEFT 0 // back left led instance number
|
||||||
#define OREOLED_BACKRIGHT 1 // back right led instance number
|
#define OREOLED_BACKRIGHT 1 // back right led instance number
|
||||||
#define OREOLED_FRONTRIGHT 2 // front right led instance number
|
#define OREOLED_FRONTRIGHT 2 // front right led instance number
|
||||||
#define OREOLED_FRONTLEFT 3 // front left led instance number
|
#define OREOLED_FRONTLEFT 3 // front left led instance number
|
||||||
|
#define PERIOD_SLOW 800 // slow flash rate
|
||||||
|
#define PERIOD_FAST 500 // fast flash rate
|
||||||
|
#define PERIOD_SUPER 150 // super fast rate
|
||||||
|
#define PO_ALTERNATE 180 // 180 degree phase offset
|
||||||
|
|
||||||
|
extern const AP_HAL::HAL& hal;
|
||||||
|
|
||||||
// constructor
|
// constructor
|
||||||
OreoLED_PX4::OreoLED_PX4() : NotifyDevice(),
|
OreoLED_PX4::OreoLED_PX4(uint8_t theme): NotifyDevice(),
|
||||||
_overall_health(false),
|
_overall_health(false),
|
||||||
_oreoled_fd(-1),
|
_oreoled_fd(-1),
|
||||||
_send_required(false),
|
_send_required(false),
|
||||||
_state_desired_semaphore(false),
|
_state_desired_semaphore(false),
|
||||||
_pattern_override(0)
|
_pattern_override(0),
|
||||||
|
_oreo_theme(theme)
|
||||||
{
|
{
|
||||||
// initialise desired and sent state
|
// initialise desired and sent state
|
||||||
memset(_state_desired,0,sizeof(_state_desired));
|
memset(_state_desired,0,sizeof(_state_desired));
|
||||||
|
@ -56,9 +58,13 @@ OreoLED_PX4::OreoLED_PX4() : NotifyDevice(),
|
||||||
|
|
||||||
extern "C" int oreoled_main(int, char **);
|
extern "C" int oreoled_main(int, char **);
|
||||||
|
|
||||||
// init - initialised the device
|
|
||||||
|
//
|
||||||
|
// Initialize the LEDs
|
||||||
|
//
|
||||||
bool OreoLED_PX4::init()
|
bool OreoLED_PX4::init()
|
||||||
{
|
{
|
||||||
|
|
||||||
#if defined(CONFIG_ARCH_BOARD_PX4FMU_V2)
|
#if defined(CONFIG_ARCH_BOARD_PX4FMU_V2)
|
||||||
if (!AP_BoardConfig::px4_start_driver(oreoled_main, "oreoled", "start autoupdate")) {
|
if (!AP_BoardConfig::px4_start_driver(oreoled_main, "oreoled", "start autoupdate")) {
|
||||||
hal.console->printf("Unable to start oreoled driver\n");
|
hal.console->printf("Unable to start oreoled driver\n");
|
||||||
|
@ -67,7 +73,7 @@ bool OreoLED_PX4::init()
|
||||||
hal.scheduler->delay(500);
|
hal.scheduler->delay(500);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// open the device
|
// open the device
|
||||||
_oreoled_fd = open(OREOLED0_DEVICE_PATH, O_RDWR);
|
_oreoled_fd = open(OREOLED0_DEVICE_PATH, O_RDWR);
|
||||||
if (_oreoled_fd == -1) {
|
if (_oreoled_fd == -1) {
|
||||||
|
@ -84,163 +90,270 @@ bool OreoLED_PX4::init()
|
||||||
return _overall_health;
|
return _overall_health;
|
||||||
}
|
}
|
||||||
|
|
||||||
// update - updates device according to timed_updated. Should be
|
|
||||||
// called at 50Hz
|
// UPDATE device according to timed_updated. Called at 50Hz
|
||||||
void OreoLED_PX4::update()
|
void OreoLED_PX4::update()
|
||||||
{
|
{
|
||||||
static uint8_t counter = 0; // counter to reduce rate from 50hz to 10hz
|
|
||||||
static uint8_t step = 0; // step to control pattern
|
|
||||||
static uint8_t last_stage = 0; // unique id of the last messages sent to the LED, used to reduce resends which disrupt some patterns
|
|
||||||
static uint8_t initialization_done = 0; // Keep track if initialization has begun. There is a period when the driver
|
|
||||||
// is running but initialization has not yet begun -- this prevents post-initialization
|
|
||||||
// LED patterns from displaying before initialization has completed.
|
|
||||||
|
|
||||||
// return immediately if not healthy
|
if (!_overall_health) { return; } // don't go any further if LED driver reports unhealthy
|
||||||
if (!_overall_health) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// handle firmware update event
|
if (slow_counter()) { return; } // slow rate from 50hz to 10hz
|
||||||
if (AP_Notify::flags.firmware_update) {
|
|
||||||
// Force a syncronisation before setting the free-running colour cycle macro
|
|
||||||
send_sync();
|
|
||||||
set_macro(OREOLED_INSTANCE_ALL, OREOLED_PARAM_MACRO_COLOUR_CYCLE);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// return immediately if custom pattern has been sent
|
sync_counter(); // syncronizes LEDs every 10 seconds
|
||||||
if (OreoLED_PX4::_pattern_override != 0) {
|
|
||||||
// reset stage so patterns will be resent once override clears
|
|
||||||
last_stage = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// slow rate from 50Hz to 10hz
|
if (mode_firmware_update()) { return; } // don't go any further if the Pixhawk is in firmware update
|
||||||
counter++;
|
|
||||||
if (counter < 5) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
counter = 0;
|
|
||||||
|
|
||||||
// move forward one step
|
if (mode_init()) { return; } // don't go any further if the Pixhawk is initializing
|
||||||
step++;
|
|
||||||
if (step >= 10) {
|
|
||||||
step = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pre-initialization pattern is all solid green
|
if (mode_failsafe_radio()) { return; } // don't go any further if the Pixhawk is is in radio failsafe
|
||||||
if (!initialization_done) {
|
|
||||||
set_rgb(OREOLED_ALL_INSTANCES, 0, OREOLED_BRIGHT, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// initialising pattern
|
set_standard_colors(); // set the rear LED standard colors as described above
|
||||||
if (AP_Notify::flags.initialising) {
|
|
||||||
initialization_done = 1; // Record initialization has begun
|
|
||||||
last_stage = 1; // record stage
|
|
||||||
|
|
||||||
// exit so no other status modify this pattern
|
if (mode_failsafe_batt()) { return; } // stop here if the battery is low.
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// save trim and esc calibration pattern
|
if (_pattern_override) { return; } // stop here if in mavlink LED control override.
|
||||||
if (AP_Notify::flags.save_trim || AP_Notify::flags.esc_calibration) {
|
|
||||||
switch(step) {
|
|
||||||
case 0:
|
|
||||||
case 3:
|
|
||||||
case 6:
|
|
||||||
// red
|
|
||||||
set_rgb(OREOLED_INSTANCE_ALL, OREOLED_BRIGHT, 0, 0);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 1:
|
if (mode_auto_flight()) { return; } // stop here if in an autopilot mode.
|
||||||
case 4:
|
|
||||||
case 7:
|
|
||||||
// blue
|
|
||||||
set_rgb(OREOLED_INSTANCE_ALL, 0, 0, OREOLED_BRIGHT);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 2:
|
mode_pilot_flight(); // stop here if in an pilot controlled mode.
|
||||||
case 5:
|
}
|
||||||
case 8:
|
|
||||||
// green on
|
|
||||||
set_rgb(OREOLED_INSTANCE_ALL, 0, OREOLED_BRIGHT, 0);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 9:
|
// Slow the update rate from 50hz to 10hz
|
||||||
// all off
|
// Returns true if counting up
|
||||||
set_rgb(OREOLED_INSTANCE_ALL, 0, 0, 0);
|
// Returns false and resets one counter hits 5
|
||||||
break;
|
bool OreoLED_PX4::slow_counter()
|
||||||
}
|
{
|
||||||
// record stage
|
static uint8_t update_counter;
|
||||||
last_stage = 2;
|
|
||||||
// exit so no other status modify this pattern
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// radio failsafe pattern: Alternate between front red/rear black and front black/rear red
|
update_counter++;
|
||||||
if (AP_Notify::flags.failsafe_radio) {
|
if (update_counter < 5) {
|
||||||
switch(step) {
|
return 1;
|
||||||
case 0:
|
} else {
|
||||||
case 1:
|
update_counter = 0;
|
||||||
case 2:
|
return 0;
|
||||||
case 3:
|
|
||||||
case 4:
|
|
||||||
// Front red/rear black
|
|
||||||
set_rgb(OREOLED_FRONTLEFT, OREOLED_BRIGHT, 0, 0);
|
|
||||||
set_rgb(OREOLED_FRONTRIGHT, OREOLED_BRIGHT, 0, 0);
|
|
||||||
set_rgb(OREOLED_BACKLEFT, 0, 0, 0);
|
|
||||||
set_rgb(OREOLED_BACKRIGHT, 0, 0, 0);
|
|
||||||
break;
|
|
||||||
case 5:
|
|
||||||
case 6:
|
|
||||||
case 7:
|
|
||||||
case 8:
|
|
||||||
case 9:
|
|
||||||
// Front black/rear red
|
|
||||||
set_rgb(OREOLED_FRONTLEFT, 0, 0, 0);
|
|
||||||
set_rgb(OREOLED_FRONTRIGHT, 0, 0, 0);
|
|
||||||
set_rgb(OREOLED_BACKLEFT, OREOLED_BRIGHT, 0, 0);
|
|
||||||
set_rgb(OREOLED_BACKRIGHT, OREOLED_BRIGHT, 0, 0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// record stage
|
|
||||||
last_stage = 3;
|
|
||||||
// exit so no other status modify this pattern
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// send colours (later we will set macro if required)
|
|
||||||
if (last_stage < 10 && initialization_done) {
|
|
||||||
set_macro(OREOLED_INSTANCE_ALL, OREOLED_PARAM_MACRO_AUTOMOBILE);
|
|
||||||
last_stage = 10;
|
|
||||||
} else if (last_stage >= 10) {
|
|
||||||
static uint8_t previous_autopilot_mode = -1;
|
|
||||||
if (previous_autopilot_mode != AP_Notify::flags.autopilot_mode) {
|
|
||||||
|
|
||||||
if (AP_Notify::flags.autopilot_mode) {
|
|
||||||
// autopilot flight modes start breathing macro
|
|
||||||
set_macro(OREOLED_INSTANCE_ALL, OREOLED_PARAM_MACRO_AUTOMOBILE);
|
|
||||||
set_macro(OREOLED_INSTANCE_ALL, OREOLED_PARAM_MACRO_BREATH);
|
|
||||||
} else {
|
|
||||||
// manual flight modes stop breathing -- solid color
|
|
||||||
set_macro(OREOLED_INSTANCE_ALL, OREOLED_PARAM_MACRO_AUTOMOBILE);
|
|
||||||
}
|
|
||||||
|
|
||||||
// record we have processed this change
|
|
||||||
previous_autopilot_mode = AP_Notify::flags.autopilot_mode;
|
|
||||||
}
|
|
||||||
last_stage = 11;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// set_rgb - set color as a combination of red, green and blue values for one or all LEDs
|
|
||||||
void OreoLED_PX4::set_rgb(uint8_t instance, uint8_t red, uint8_t green, uint8_t blue)
|
// Calls resyncing the LEDs every 10 seconds
|
||||||
|
// Always returns false, no action needed.
|
||||||
|
void OreoLED_PX4::sync_counter()
|
||||||
{
|
{
|
||||||
// return immediately if no healty leds
|
static uint8_t counter = 80;
|
||||||
if (!_overall_health) {
|
|
||||||
return;
|
counter++;
|
||||||
|
if (counter > 100) {
|
||||||
|
counter = 0;
|
||||||
|
send_sync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Procedure for when Pixhawk is in FW update / bootloader
|
||||||
|
// Makes all LEDs go into color cycle mode
|
||||||
|
// Returns true if firmware update in progress. False if not
|
||||||
|
bool OreoLED_PX4::mode_firmware_update()
|
||||||
|
{
|
||||||
|
if (AP_Notify::flags.firmware_update) {
|
||||||
|
set_macro(OREOLED_INSTANCE_ALL, OREOLED_PARAM_MACRO_COLOUR_CYCLE);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Procedure for when Pixhawk is booting up and initializing
|
||||||
|
// Makes all LEDs rapidly strobe blue. Returns LED_INIT_STAGE
|
||||||
|
// 1 = Default, initialization has not yet begun
|
||||||
|
// 2 = Initialization flag found, initialization in progress
|
||||||
|
// 3 = Initialization flag no longer found, initialization complete
|
||||||
|
bool OreoLED_PX4::mode_init()
|
||||||
|
{
|
||||||
|
static uint16_t stage = 1;
|
||||||
|
|
||||||
|
// Pixhawk has not begun initializing yet. Strobe all blue
|
||||||
|
if ((!AP_Notify::flags.initialising) && ((stage == 1))) {
|
||||||
|
set_rgb(OREOLED_INSTANCE_ALL, OREOLED_PATTERN_STROBE, 0, 0, 255,0,0,0,PERIOD_SUPER,0);
|
||||||
|
|
||||||
|
// Pixhawk has begun initializing
|
||||||
|
} else if ((AP_Notify::flags.initialising) && ((stage == 1))) {
|
||||||
|
stage = 2;
|
||||||
|
set_rgb(OREOLED_INSTANCE_ALL, OREOLED_PATTERN_STROBE, 0, 0, 255,0,0,0,PERIOD_SUPER,0);
|
||||||
|
|
||||||
|
// Pixhawk still initializing
|
||||||
|
} else if ((AP_Notify::flags.initialising) && ((stage == 2))) {
|
||||||
|
set_rgb(OREOLED_INSTANCE_ALL, OREOLED_PATTERN_STROBE, 0, 0, 255,0,0,0,PERIOD_SUPER,0);
|
||||||
|
|
||||||
|
// Pixhawk has completed initialization
|
||||||
|
} else if((!AP_Notify::flags.initialising) && ((stage == 2))) {
|
||||||
|
stage = 0;
|
||||||
|
set_rgb(OREOLED_INSTANCE_ALL, OREOLED_PATTERN_SOLID, 0, 0, 255);
|
||||||
|
|
||||||
|
} else { stage = 0; }
|
||||||
|
|
||||||
|
return stage;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Procedure for when Pixhawk is in radio failsafe
|
||||||
|
// LEDs perform alternating Red X pattern
|
||||||
|
bool OreoLED_PX4::mode_failsafe_radio()
|
||||||
|
{
|
||||||
|
if (AP_Notify::flags.failsafe_radio) {
|
||||||
|
set_rgb(OREOLED_FRONTLEFT, OREOLED_PATTERN_STROBE, 255, 0, 0,0,0,0,PERIOD_SLOW,0);
|
||||||
|
set_rgb(OREOLED_FRONTRIGHT, OREOLED_PATTERN_STROBE, 255, 0, 0,0,0,0,PERIOD_SLOW,PO_ALTERNATE);
|
||||||
|
set_rgb(OREOLED_BACKLEFT, OREOLED_PATTERN_STROBE, 255, 0, 0,0,0,0,PERIOD_SLOW,PO_ALTERNATE);
|
||||||
|
set_rgb(OREOLED_BACKRIGHT, OREOLED_PATTERN_STROBE, 255, 0, 0,0,0,0,PERIOD_SLOW,0);
|
||||||
|
}
|
||||||
|
return AP_Notify::flags.failsafe_radio;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Procedure to set standard rear LED colors in aviation theme
|
||||||
|
// Back LEDS White for normal, yellow for GPS not usable, purple for EKF bad]
|
||||||
|
// Returns true GPS or EKF problem, returns false if all ok
|
||||||
|
bool OreoLED_PX4::set_standard_colors()
|
||||||
|
{
|
||||||
|
if (!(AP_Notify::flags.gps_fusion)) {
|
||||||
|
_rear_color_r = 255;
|
||||||
|
_rear_color_g = 50;
|
||||||
|
_rear_color_b = 0;
|
||||||
|
return true;
|
||||||
|
|
||||||
|
} else if (AP_Notify::flags.ekf_bad){
|
||||||
|
_rear_color_r = 255;
|
||||||
|
_rear_color_g = 0;
|
||||||
|
_rear_color_b = 255;
|
||||||
|
return true;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
_rear_color_r = 255;
|
||||||
|
_rear_color_g = 255;
|
||||||
|
_rear_color_b = 255;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Procedure to set low battery LED output
|
||||||
|
// Colors standard
|
||||||
|
// Fast strobe alternating front/back
|
||||||
|
bool OreoLED_PX4::mode_failsafe_batt()
|
||||||
|
{
|
||||||
|
if (AP_Notify::flags.failsafe_battery){
|
||||||
|
|
||||||
|
switch (_oreo_theme) {
|
||||||
|
case OreoLED_Aircraft:
|
||||||
|
set_rgb(OREOLED_FRONTLEFT, OREOLED_PATTERN_STROBE, 255, 0, 0,0,0,0,PERIOD_FAST,0);
|
||||||
|
set_rgb(OREOLED_FRONTRIGHT, OREOLED_PATTERN_STROBE, 0, 255, 0,0,0,0,PERIOD_FAST,0);
|
||||||
|
set_rgb(OREOLED_BACKLEFT, OREOLED_PATTERN_STROBE, _rear_color_r, _rear_color_g, _rear_color_b,0,0,0,PERIOD_FAST,PO_ALTERNATE);
|
||||||
|
set_rgb(OREOLED_BACKRIGHT, OREOLED_PATTERN_STROBE, _rear_color_r, _rear_color_g, _rear_color_b,0,0,0,PERIOD_FAST,PO_ALTERNATE);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case OreoLED_Automobile:
|
||||||
|
set_rgb(OREOLED_FRONTLEFT, OREOLED_PATTERN_STROBE, 255, 255, 255,0,0,0,PERIOD_FAST,0);
|
||||||
|
set_rgb(OREOLED_FRONTRIGHT, OREOLED_PATTERN_STROBE, 255, 255, 255,0,0,0,PERIOD_FAST,0);
|
||||||
|
set_rgb(OREOLED_BACKLEFT, OREOLED_PATTERN_STROBE, 255, 0, 0,0,0,0,PERIOD_FAST,PO_ALTERNATE);
|
||||||
|
set_rgb(OREOLED_BACKRIGHT, OREOLED_PATTERN_STROBE, 255, 0, 0,0,0,0,PERIOD_FAST,PO_ALTERNATE);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
set_rgb(OREOLED_FRONTLEFT, OREOLED_PATTERN_STROBE, 255, 255, 255,0,0,0,PERIOD_FAST,0);
|
||||||
|
set_rgb(OREOLED_FRONTRIGHT, OREOLED_PATTERN_STROBE, 255, 255, 255,0,0,0,PERIOD_FAST,0);
|
||||||
|
set_rgb(OREOLED_BACKLEFT, OREOLED_PATTERN_STROBE, 255, 0, 0,0,0,0,PERIOD_FAST,PO_ALTERNATE);
|
||||||
|
set_rgb(OREOLED_BACKRIGHT, OREOLED_PATTERN_STROBE, 255, 0, 0,0,0,0,PERIOD_FAST,PO_ALTERNATE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return AP_Notify::flags.failsafe_battery;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Procedure for when Pixhawk is in an autopilot mode
|
||||||
|
// Makes all LEDs strobe super fast using standard colors
|
||||||
|
bool OreoLED_PX4::mode_auto_flight()
|
||||||
|
{
|
||||||
|
switch (_oreo_theme) {
|
||||||
|
|
||||||
|
case OreoLED_Aircraft:
|
||||||
|
set_rgb(OREOLED_FRONTLEFT, OREOLED_PATTERN_STROBE, 255, 0, 0,0,0,0,PERIOD_SUPER,0);
|
||||||
|
set_rgb(OREOLED_FRONTRIGHT, OREOLED_PATTERN_STROBE, 0, 255, 0,0,0,0,PERIOD_SUPER,0);
|
||||||
|
if ((AP_Notify::flags.pre_arm_check && AP_Notify::flags.pre_arm_gps_check) || AP_Notify::flags.armed) {
|
||||||
|
set_rgb(OREOLED_BACKLEFT, OREOLED_PATTERN_STROBE, _rear_color_r, _rear_color_g, _rear_color_b,0,0,0,PERIOD_SUPER,PO_ALTERNATE);
|
||||||
|
set_rgb(OREOLED_BACKRIGHT, OREOLED_PATTERN_STROBE, _rear_color_r, _rear_color_g, _rear_color_b,0,0,0,PERIOD_SUPER,PO_ALTERNATE);
|
||||||
|
} else {
|
||||||
|
set_rgb(OREOLED_BACKLEFT, OREOLED_PATTERN_SOLID, _rear_color_r, _rear_color_g, _rear_color_b);
|
||||||
|
set_rgb(OREOLED_BACKRIGHT, OREOLED_PATTERN_SOLID, _rear_color_r, _rear_color_g, _rear_color_b);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case OreoLED_Automobile:
|
||||||
|
set_rgb(OREOLED_FRONTLEFT, OREOLED_PATTERN_STROBE, 255, 255, 255,0,0,0,PERIOD_SUPER,0);
|
||||||
|
set_rgb(OREOLED_FRONTRIGHT, OREOLED_PATTERN_STROBE, 255, 255, 255,0,0,0,PERIOD_SUPER,0);
|
||||||
|
set_rgb(OREOLED_BACKLEFT, OREOLED_PATTERN_STROBE, 255, 0, 0,0,0,0,PERIOD_SUPER,PO_ALTERNATE);
|
||||||
|
set_rgb(OREOLED_BACKRIGHT, OREOLED_PATTERN_STROBE, 255, 0, 0,0,0,0,PERIOD_SUPER,PO_ALTERNATE);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
set_rgb(OREOLED_FRONTLEFT, OREOLED_PATTERN_STROBE, 255, 255, 255,0,0,0,PERIOD_SUPER,0);
|
||||||
|
set_rgb(OREOLED_FRONTRIGHT, OREOLED_PATTERN_STROBE, 255, 255, 255,0,0,0,PERIOD_SUPER,0);
|
||||||
|
set_rgb(OREOLED_BACKLEFT, OREOLED_PATTERN_STROBE, 255, 0, 0,0,0,0,PERIOD_SUPER,PO_ALTERNATE);
|
||||||
|
set_rgb(OREOLED_BACKRIGHT, OREOLED_PATTERN_STROBE, 255, 0, 0,0,0,0,PERIOD_SUPER,PO_ALTERNATE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return AP_Notify::flags.autopilot_mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Procedure for when Pixhawk is in a pilot controlled mode
|
||||||
|
// All LEDs use standard pattern and colors
|
||||||
|
bool OreoLED_PX4::mode_pilot_flight()
|
||||||
|
{
|
||||||
|
switch (_oreo_theme) {
|
||||||
|
|
||||||
|
case OreoLED_Aircraft:
|
||||||
|
set_rgb(OREOLED_FRONTLEFT, OREOLED_PATTERN_SOLID, 255, 0, 0);
|
||||||
|
set_rgb(OREOLED_FRONTRIGHT, OREOLED_PATTERN_SOLID, 0, 255, 0);
|
||||||
|
if ((AP_Notify::flags.pre_arm_check && AP_Notify::flags.pre_arm_gps_check) || AP_Notify::flags.armed) {
|
||||||
|
set_rgb(OREOLED_BACKLEFT, OREOLED_PATTERN_STROBE, _rear_color_r, _rear_color_g, _rear_color_b,0,0,0,PERIOD_FAST,0);
|
||||||
|
set_rgb(OREOLED_BACKRIGHT, OREOLED_PATTERN_STROBE, _rear_color_r, _rear_color_g, _rear_color_b,0,0,0,PERIOD_FAST,PO_ALTERNATE);
|
||||||
|
} else {
|
||||||
|
set_rgb(OREOLED_BACKLEFT, OREOLED_PATTERN_SOLID, _rear_color_r, _rear_color_g, _rear_color_b);
|
||||||
|
set_rgb(OREOLED_BACKRIGHT, OREOLED_PATTERN_SOLID, _rear_color_r, _rear_color_g, _rear_color_b);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case OreoLED_Automobile:
|
||||||
|
set_rgb(OREOLED_FRONTLEFT, OREOLED_PATTERN_SOLID, 255, 255, 255);
|
||||||
|
set_rgb(OREOLED_FRONTRIGHT, OREOLED_PATTERN_SOLID, 255, 255, 255);
|
||||||
|
set_rgb(OREOLED_BACKLEFT, OREOLED_PATTERN_SOLID, 255, 0, 0);
|
||||||
|
set_rgb(OREOLED_BACKRIGHT, OREOLED_PATTERN_SOLID, 255, 0, 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
set_rgb(OREOLED_FRONTLEFT, OREOLED_PATTERN_SOLID, 255, 255, 255);
|
||||||
|
set_rgb(OREOLED_FRONTRIGHT, OREOLED_PATTERN_SOLID, 255, 255, 255);
|
||||||
|
set_rgb(OREOLED_BACKLEFT, OREOLED_PATTERN_SOLID, 255, 0, 0);
|
||||||
|
set_rgb(OREOLED_BACKRIGHT, OREOLED_PATTERN_SOLID, 255, 0, 0);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// set_rgb - Solid color settings only
|
||||||
|
void OreoLED_PX4::set_rgb(uint8_t instance, uint8_t red, uint8_t green, uint8_t blue)
|
||||||
|
{
|
||||||
|
set_rgb(instance, OREOLED_PATTERN_SOLID, red, green, blue);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// set_rgb - Set a color and selected pattern.
|
||||||
|
void OreoLED_PX4::set_rgb(uint8_t instance, oreoled_pattern pattern, uint8_t red, uint8_t green, uint8_t blue)
|
||||||
|
{
|
||||||
// get semaphore
|
// get semaphore
|
||||||
_state_desired_semaphore = true;
|
_state_desired_semaphore = true;
|
||||||
|
|
||||||
|
@ -248,21 +361,15 @@ void OreoLED_PX4::set_rgb(uint8_t instance, uint8_t red, uint8_t green, uint8_t
|
||||||
if (instance == OREOLED_INSTANCE_ALL) {
|
if (instance == OREOLED_INSTANCE_ALL) {
|
||||||
// store desired rgb for all LEDs
|
// store desired rgb for all LEDs
|
||||||
for (uint8_t i=0; i<OREOLED_NUM_LEDS; i++) {
|
for (uint8_t i=0; i<OREOLED_NUM_LEDS; i++) {
|
||||||
if (_state_desired[i].mode != OREOLED_MODE_RGB || _state_desired[i].red != red || _state_desired[i].green != green || _state_desired[i].blue != blue) {
|
_state_desired[i].set_rgb(pattern, red, green, blue);
|
||||||
_state_desired[i].mode = OREOLED_MODE_RGB;
|
if (!(_state_desired[i] == _state_sent[i])) {
|
||||||
_state_desired[i].red = red;
|
|
||||||
_state_desired[i].green = green;
|
|
||||||
_state_desired[i].blue = blue;
|
|
||||||
_send_required = true;
|
_send_required = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (instance < OREOLED_NUM_LEDS) {
|
} else if (instance < OREOLED_NUM_LEDS) {
|
||||||
// store desired rgb for one LED
|
// store desired rgb for one LED
|
||||||
if (_state_desired[instance].mode != OREOLED_MODE_RGB || _state_desired[instance].red != red || _state_desired[instance].green != green || _state_desired[instance].blue != blue) {
|
_state_desired[instance].set_rgb(pattern, red, green, blue);
|
||||||
_state_desired[instance].mode = OREOLED_MODE_RGB;
|
if (!(_state_desired[instance] == _state_sent[instance])) {
|
||||||
_state_desired[instance].red = red;
|
|
||||||
_state_desired[instance].green = green;
|
|
||||||
_state_desired[instance].blue = blue;
|
|
||||||
_send_required = true;
|
_send_required = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -271,6 +378,37 @@ void OreoLED_PX4::set_rgb(uint8_t instance, uint8_t red, uint8_t green, uint8_t
|
||||||
_state_desired_semaphore = false;
|
_state_desired_semaphore = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// set_rgb - Sets a color, pattern, and uses extended options for amplitude, period, and phase offset
|
||||||
|
void OreoLED_PX4::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)
|
||||||
|
{
|
||||||
|
// get semaphore
|
||||||
|
_state_desired_semaphore = true;
|
||||||
|
|
||||||
|
// check for all instances
|
||||||
|
if (instance == OREOLED_INSTANCE_ALL) {
|
||||||
|
// store desired rgb for all LEDs
|
||||||
|
for (uint8_t i=0; i<OREOLED_NUM_LEDS; i++) {
|
||||||
|
_state_desired[i].set_rgb(pattern, red, green, blue, amplitude_red, amplitude_green, amplitude_blue, period, phase_offset);
|
||||||
|
if (!(_state_desired[i] == _state_sent[i])) {
|
||||||
|
_send_required = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (instance < OREOLED_NUM_LEDS) {
|
||||||
|
// store desired rgb for one LED
|
||||||
|
_state_desired[instance].set_rgb(pattern, red, green, blue, amplitude_red, amplitude_green, amplitude_blue, period, phase_offset);
|
||||||
|
if (!(_state_desired[instance] == _state_sent[instance])) {
|
||||||
|
_send_required = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// release semaphore
|
||||||
|
_state_desired_semaphore = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// set_macro - set macro for one or all LEDs
|
// set_macro - set macro for one or all LEDs
|
||||||
void OreoLED_PX4::set_macro(uint8_t instance, oreoled_macro macro)
|
void OreoLED_PX4::set_macro(uint8_t instance, oreoled_macro macro)
|
||||||
{
|
{
|
||||||
|
@ -286,17 +424,15 @@ void OreoLED_PX4::set_macro(uint8_t instance, oreoled_macro macro)
|
||||||
if (instance == OREOLED_INSTANCE_ALL) {
|
if (instance == OREOLED_INSTANCE_ALL) {
|
||||||
// store desired macro for all LEDs
|
// store desired macro for all LEDs
|
||||||
for (uint8_t i=0; i<OREOLED_NUM_LEDS; i++) {
|
for (uint8_t i=0; i<OREOLED_NUM_LEDS; i++) {
|
||||||
if (_state_desired[i].mode != OREOLED_MODE_MACRO || _state_desired[i].macro != macro) {
|
_state_desired[i].set_macro(macro);
|
||||||
_state_desired[i].mode = OREOLED_MODE_MACRO;
|
if (!(_state_desired[i] == _state_sent[i])) {
|
||||||
_state_desired[i].macro = macro;
|
|
||||||
_send_required = true;
|
_send_required = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (instance < OREOLED_NUM_LEDS) {
|
} else if (instance < OREOLED_NUM_LEDS) {
|
||||||
// store desired macro for one LED
|
// store desired macro for one LED
|
||||||
if (_state_desired[instance].mode != OREOLED_MODE_MACRO || _state_desired[instance].macro != macro) {
|
_state_desired[instance].set_macro(macro);
|
||||||
_state_desired[instance].mode = OREOLED_MODE_MACRO;
|
if (!(_state_desired[instance] == _state_sent[instance])) {
|
||||||
_state_desired[instance].macro = macro;
|
|
||||||
_send_required = true;
|
_send_required = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -305,8 +441,8 @@ void OreoLED_PX4::set_macro(uint8_t instance, oreoled_macro macro)
|
||||||
_state_desired_semaphore = false;
|
_state_desired_semaphore = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// set_macro - set macro for one or all LEDs
|
// send_sync - force a syncronisation of the all LED's
|
||||||
void OreoLED_PX4::send_sync(void)
|
void OreoLED_PX4::send_sync()
|
||||||
{
|
{
|
||||||
// return immediately if no healthy leds
|
// return immediately if no healthy leds
|
||||||
if (!_overall_health) {
|
if (!_overall_health) {
|
||||||
|
@ -316,17 +452,36 @@ void OreoLED_PX4::send_sync(void)
|
||||||
// set semaphore
|
// set semaphore
|
||||||
_state_desired_semaphore = true;
|
_state_desired_semaphore = true;
|
||||||
|
|
||||||
|
// store desired macro for all LEDs
|
||||||
for (uint8_t i=0; i<OREOLED_NUM_LEDS; i++) {
|
for (uint8_t i=0; i<OREOLED_NUM_LEDS; i++) {
|
||||||
if (_state_desired[i].mode != OREOLED_MODE_SYNC) {
|
_state_desired[i].send_sync();
|
||||||
_state_desired[i].mode = OREOLED_MODE_SYNC;
|
if (!(_state_desired[i] == _state_sent[i])) {
|
||||||
_send_required = true;
|
_send_required = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// release semaphore
|
// release semaphore
|
||||||
_state_desired_semaphore = false;
|
_state_desired_semaphore = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Clear the desired state
|
||||||
|
void OreoLED_PX4::clear_state(void)
|
||||||
|
{
|
||||||
|
// set semaphore
|
||||||
|
_state_desired_semaphore = true;
|
||||||
|
|
||||||
|
for (uint8_t i=0; i<OREOLED_NUM_LEDS; i++) {
|
||||||
|
_state_desired[i].clear_state();
|
||||||
|
}
|
||||||
|
|
||||||
|
_send_required = false;
|
||||||
|
|
||||||
|
// release semaphore
|
||||||
|
_state_desired_semaphore = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// update_timer - called by scheduler and updates PX4 driver with commands
|
// update_timer - called by scheduler and updates PX4 driver with commands
|
||||||
void OreoLED_PX4::update_timer(void)
|
void OreoLED_PX4::update_timer(void)
|
||||||
{
|
{
|
||||||
|
@ -346,9 +501,6 @@ void OreoLED_PX4::update_timer(void)
|
||||||
// check for state change
|
// check for state change
|
||||||
if (!(_state_desired[i] == _state_sent[i])) {
|
if (!(_state_desired[i] == _state_sent[i])) {
|
||||||
switch (_state_desired[i].mode) {
|
switch (_state_desired[i].mode) {
|
||||||
case OREOLED_MODE_PATTERN:
|
|
||||||
// not yet supported
|
|
||||||
break;
|
|
||||||
case OREOLED_MODE_MACRO:
|
case OREOLED_MODE_MACRO:
|
||||||
{
|
{
|
||||||
oreoled_macrorun_t macro_run = {i, _state_desired[i].macro};
|
oreoled_macrorun_t macro_run = {i, _state_desired[i].macro};
|
||||||
|
@ -357,16 +509,48 @@ void OreoLED_PX4::update_timer(void)
|
||||||
break;
|
break;
|
||||||
case OREOLED_MODE_RGB:
|
case OREOLED_MODE_RGB:
|
||||||
{
|
{
|
||||||
oreoled_rgbset_t rgb_set = {i, OREOLED_PATTERN_SOLID, _state_desired[i].red, _state_desired[i].green, _state_desired[i].blue};
|
oreoled_rgbset_t rgb_set = {i, _state_desired[i].pattern, _state_desired[i].red, _state_desired[i].green, _state_desired[i].blue};
|
||||||
ioctl(_oreoled_fd, OREOLED_SET_RGB, (unsigned long)&rgb_set);
|
ioctl(_oreoled_fd, OREOLED_SET_RGB, (unsigned long)&rgb_set);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case OREOLED_MODE_RGB_EXTENDED:
|
||||||
|
{
|
||||||
|
oreoled_cmd_t cmd;
|
||||||
|
memset(&cmd, 0, sizeof(oreoled_cmd_t));
|
||||||
|
cmd.led_num = i;
|
||||||
|
cmd.buff[0] = _state_desired[i].pattern;
|
||||||
|
cmd.buff[1] = OREOLED_PARAM_BIAS_RED;
|
||||||
|
cmd.buff[2] = _state_desired[i].red;
|
||||||
|
cmd.buff[3] = OREOLED_PARAM_BIAS_GREEN;
|
||||||
|
cmd.buff[4] = _state_desired[i].green;
|
||||||
|
cmd.buff[5] = OREOLED_PARAM_BIAS_BLUE;
|
||||||
|
cmd.buff[6] = _state_desired[i].blue;
|
||||||
|
cmd.buff[7] = OREOLED_PARAM_AMPLITUDE_RED;
|
||||||
|
cmd.buff[8] = _state_desired[i].amplitude_red;
|
||||||
|
cmd.buff[9] = OREOLED_PARAM_AMPLITUDE_GREEN;
|
||||||
|
cmd.buff[10] = _state_desired[i].amplitude_green;
|
||||||
|
cmd.buff[11] = OREOLED_PARAM_AMPLITUDE_BLUE;
|
||||||
|
cmd.buff[12] = _state_desired[i].amplitude_blue;
|
||||||
|
// Note: The Oreo LED controller expects to receive uint16 values
|
||||||
|
// in little endian order
|
||||||
|
cmd.buff[13] = OREOLED_PARAM_PERIOD;
|
||||||
|
cmd.buff[14] = (_state_desired[i].period & 0xFF00) >> 8;
|
||||||
|
cmd.buff[15] = (_state_desired[i].period & 0x00FF);
|
||||||
|
cmd.buff[16] = OREOLED_PARAM_PHASEOFFSET;
|
||||||
|
cmd.buff[17] = (_state_desired[i].phase_offset & 0xFF00) >> 8;
|
||||||
|
cmd.buff[18] = (_state_desired[i].phase_offset & 0x00FF);
|
||||||
|
cmd.num_bytes = 19;
|
||||||
|
ioctl(_oreoled_fd, OREOLED_SEND_BYTES, (unsigned long)&cmd);
|
||||||
|
}
|
||||||
|
break;
|
||||||
case OREOLED_MODE_SYNC:
|
case OREOLED_MODE_SYNC:
|
||||||
{
|
{
|
||||||
ioctl(_oreoled_fd, OREOLED_FORCE_SYNC, 0);
|
ioctl(_oreoled_fd, OREOLED_FORCE_SYNC, 0);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
default:
|
||||||
|
break;
|
||||||
|
};
|
||||||
// save state change
|
// save state change
|
||||||
_state_sent[i] = _state_desired[i];
|
_state_sent[i] = _state_desired[i];
|
||||||
}
|
}
|
||||||
|
@ -376,7 +560,8 @@ void OreoLED_PX4::update_timer(void)
|
||||||
_send_required = false;
|
_send_required = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// handle a LED_CONTROL message
|
|
||||||
|
// Handle an LED_CONTROL mavlink message
|
||||||
void OreoLED_PX4::handle_led_control(mavlink_message_t *msg)
|
void OreoLED_PX4::handle_led_control(mavlink_message_t *msg)
|
||||||
{
|
{
|
||||||
// exit immediately if unhealthy
|
// exit immediately if unhealthy
|
||||||
|
@ -396,17 +581,142 @@ void OreoLED_PX4::handle_led_control(mavlink_message_t *msg)
|
||||||
// if pattern is OFF, we clear pattern override so normal lighting should resume
|
// if pattern is OFF, we clear pattern override so normal lighting should resume
|
||||||
if (packet.pattern == LED_CONTROL_PATTERN_OFF) {
|
if (packet.pattern == LED_CONTROL_PATTERN_OFF) {
|
||||||
_pattern_override = 0;
|
_pattern_override = 0;
|
||||||
|
clear_state();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// custom patterns not implemented
|
|
||||||
if (packet.pattern == LED_CONTROL_PATTERN_CUSTOM) {
|
if (packet.pattern == LED_CONTROL_PATTERN_CUSTOM) {
|
||||||
return;
|
// Here we handle two different "sub commands",
|
||||||
}
|
// depending on the bytes in the first CUSTOM_HEADER_LENGTH
|
||||||
|
// of the custom pattern byte buffer
|
||||||
|
|
||||||
// other patterns sent as macro
|
// Return if we don't have at least CUSTOM_HEADER_LENGTH bytes
|
||||||
set_macro(packet.instance, (oreoled_macro)packet.pattern);
|
if (packet.custom_len < CUSTOM_HEADER_LENGTH) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check for the RGB0 sub-command
|
||||||
|
if (memcmp(packet.custom_bytes, "RGB0", CUSTOM_HEADER_LENGTH) == 0) {
|
||||||
|
// check to make sure the total length matches the length of the RGB0 command + data values
|
||||||
|
if (packet.custom_len != CUSTOM_HEADER_LENGTH + 4) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check for valid pattern id
|
||||||
|
if (packet.custom_bytes[CUSTOM_HEADER_LENGTH] >= OREOLED_PATTERN_ENUM_COUNT) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// convert the first byte after the command to a oreoled_pattern
|
||||||
|
oreoled_pattern pattern = (oreoled_pattern)packet.custom_bytes[CUSTOM_HEADER_LENGTH];
|
||||||
|
|
||||||
|
// call the set_rgb function, using the rest of the bytes as the RGB values
|
||||||
|
set_rgb(packet.instance, pattern, packet.custom_bytes[CUSTOM_HEADER_LENGTH + 1], packet.custom_bytes[CUSTOM_HEADER_LENGTH + 2], packet.custom_bytes[CUSTOM_HEADER_LENGTH + 3]);
|
||||||
|
|
||||||
|
} else if (memcmp(packet.custom_bytes, "RGB1", CUSTOM_HEADER_LENGTH) == 0) { // check for the RGB1 sub-command
|
||||||
|
|
||||||
|
// check to make sure the total length matches the length of the RGB1 command + data values
|
||||||
|
if (packet.custom_len != CUSTOM_HEADER_LENGTH + 11) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check for valid pattern id
|
||||||
|
if (packet.custom_bytes[CUSTOM_HEADER_LENGTH] >= OREOLED_PATTERN_ENUM_COUNT) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// convert the first byte after the command to a oreoled_pattern
|
||||||
|
oreoled_pattern pattern = (oreoled_pattern)packet.custom_bytes[CUSTOM_HEADER_LENGTH];
|
||||||
|
|
||||||
|
// uint16_t values are stored in custom_bytes in little endian order
|
||||||
|
// assume the flight controller is little endian when decoding values
|
||||||
|
uint16_t period =
|
||||||
|
((0x00FF & (uint16_t)packet.custom_bytes[CUSTOM_HEADER_LENGTH + 7]) << 8) |
|
||||||
|
(0x00FF & (uint16_t)packet.custom_bytes[CUSTOM_HEADER_LENGTH + 8]);
|
||||||
|
uint16_t phase_offset =
|
||||||
|
((0x00FF & (uint16_t)packet.custom_bytes[CUSTOM_HEADER_LENGTH + 9]) << 8) |
|
||||||
|
(0x00FF & (uint16_t)packet.custom_bytes[CUSTOM_HEADER_LENGTH + 10]);
|
||||||
|
|
||||||
|
// call the set_rgb function, using the rest of the bytes as the RGB values
|
||||||
|
set_rgb(packet.instance, pattern, packet.custom_bytes[CUSTOM_HEADER_LENGTH + 1], packet.custom_bytes[CUSTOM_HEADER_LENGTH + 2],
|
||||||
|
packet.custom_bytes[CUSTOM_HEADER_LENGTH + 3], packet.custom_bytes[CUSTOM_HEADER_LENGTH + 4], packet.custom_bytes[CUSTOM_HEADER_LENGTH + 5],
|
||||||
|
packet.custom_bytes[CUSTOM_HEADER_LENGTH + 6], period, phase_offset);
|
||||||
|
} else if (memcmp(packet.custom_bytes, "SYNC", CUSTOM_HEADER_LENGTH) == 0) { // check for the SYNC sub-command
|
||||||
|
// check to make sure the total length matches the length of the SYN0 command + data values
|
||||||
|
if (packet.custom_len != CUSTOM_HEADER_LENGTH + 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
send_sync();
|
||||||
|
} else { // unrecognized command
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// other patterns sent as macro
|
||||||
|
set_macro(packet.instance, (oreoled_macro)packet.pattern);
|
||||||
|
}
|
||||||
_pattern_override = packet.pattern;
|
_pattern_override = packet.pattern;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
OreoLED_PX4::oreo_state::oreo_state() {
|
||||||
|
clear_state();
|
||||||
|
}
|
||||||
|
|
||||||
|
void OreoLED_PX4::oreo_state::clear_state() {
|
||||||
|
mode = OREOLED_MODE_NONE;
|
||||||
|
pattern = OREOLED_PATTERN_OFF;
|
||||||
|
macro = OREOLED_PARAM_MACRO_RESET;
|
||||||
|
red = 0;
|
||||||
|
green = 0;
|
||||||
|
blue = 0;
|
||||||
|
amplitude_red = 0;
|
||||||
|
amplitude_green = 0;
|
||||||
|
amplitude_blue = 0;
|
||||||
|
period = 0;
|
||||||
|
repeat = 0;
|
||||||
|
phase_offset = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OreoLED_PX4::oreo_state::send_sync() {
|
||||||
|
clear_state();
|
||||||
|
mode = OREOLED_MODE_SYNC;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OreoLED_PX4::oreo_state::set_macro(oreoled_macro new_macro) {
|
||||||
|
clear_state();
|
||||||
|
mode = OREOLED_MODE_MACRO;
|
||||||
|
macro = new_macro;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OreoLED_PX4::oreo_state::set_rgb(enum oreoled_pattern new_pattern, uint8_t new_red, uint8_t new_green, uint8_t new_blue) {
|
||||||
|
clear_state();
|
||||||
|
mode = OREOLED_MODE_RGB;
|
||||||
|
pattern = new_pattern;
|
||||||
|
red = new_red;
|
||||||
|
green = new_green;
|
||||||
|
blue = new_blue;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OreoLED_PX4::oreo_state::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) {
|
||||||
|
clear_state();
|
||||||
|
mode = OREOLED_MODE_RGB_EXTENDED;
|
||||||
|
pattern = new_pattern;
|
||||||
|
red = new_red;
|
||||||
|
green = new_green;
|
||||||
|
blue = new_blue;
|
||||||
|
amplitude_red = new_amplitude_red;
|
||||||
|
amplitude_green = new_amplitude_green;
|
||||||
|
amplitude_blue = new_amplitude_blue;
|
||||||
|
period = new_period;
|
||||||
|
phase_offset = new_phase_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool OreoLED_PX4::oreo_state::operator==(const OreoLED_PX4::oreo_state &os) {
|
||||||
|
return ((os.mode==mode) && (os.pattern==pattern) && (os.macro==macro) && (os.red==red) && (os.green==green) && (os.blue==blue)
|
||||||
|
&& (os.amplitude_red==amplitude_red) && (os.amplitude_green==amplitude_green) && (os.amplitude_blue==amplitude_blue)
|
||||||
|
&& (os.period==period) && (os.repeat==repeat) && (os.phase_offset==phase_offset));
|
||||||
|
}
|
||||||
|
|
||||||
#endif // CONFIG_HAL_BOARD == HAL_BOARD_PX4
|
#endif // CONFIG_HAL_BOARD == HAL_BOARD_PX4
|
||||||
|
|
||||||
|
|
|
@ -26,11 +26,13 @@
|
||||||
#define OREOLED_INSTANCE_ALL 0xff // instance number to indicate all LEDs (used for set_rgb and set_macro)
|
#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 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_PX4 : public NotifyDevice
|
class OreoLED_PX4 : public NotifyDevice
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// constuctor
|
// constuctor
|
||||||
OreoLED_PX4();
|
OreoLED_PX4(uint8_t theme);
|
||||||
|
|
||||||
// init - initialised the device
|
// init - initialised the device
|
||||||
bool init(void);
|
bool init(void);
|
||||||
|
@ -49,23 +51,53 @@ private:
|
||||||
// update_timer - called by scheduler and updates PX4 driver with commands
|
// update_timer - called by scheduler and updates PX4 driver with commands
|
||||||
void update_timer(void);
|
void update_timer(void);
|
||||||
|
|
||||||
// set_rgb - set color as a combination of red, green and blue values for one or all LEDs
|
// 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);
|
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
|
// set_macro - set macro for one or all LEDs
|
||||||
void set_macro(uint8_t instance, enum oreoled_macro macro);
|
void set_macro(uint8_t instance, enum oreoled_macro macro);
|
||||||
|
|
||||||
// send_sync - force a syncronisation of the LEDs
|
// send_sync - force a syncronisation of the all LED's
|
||||||
void send_sync(void);
|
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);
|
||||||
|
void sync_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)
|
// oreo led modes (pattern, macro or rgb)
|
||||||
enum oreoled_mode {
|
enum oreoled_mode {
|
||||||
OREOLED_MODE_PATTERN,
|
OREOLED_MODE_NONE,
|
||||||
OREOLED_MODE_MACRO,
|
OREOLED_MODE_MACRO,
|
||||||
OREOLED_MODE_RGB,
|
OREOLED_MODE_RGB,
|
||||||
|
OREOLED_MODE_RGB_EXTENDED,
|
||||||
OREOLED_MODE_SYNC
|
OREOLED_MODE_SYNC
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 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
|
// oreo_state structure holds possible state of an led
|
||||||
struct oreo_state {
|
struct oreo_state {
|
||||||
enum oreoled_mode mode;
|
enum oreoled_mode mode;
|
||||||
|
@ -74,11 +106,28 @@ private:
|
||||||
uint8_t red;
|
uint8_t red;
|
||||||
uint8_t green;
|
uint8_t green;
|
||||||
uint8_t blue;
|
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;
|
||||||
|
|
||||||
// operator==
|
oreo_state();
|
||||||
inline bool operator==(const oreo_state &os) {
|
|
||||||
return ((os.mode==mode) && (os.pattern==pattern) && (os.macro==macro) && (os.red==red) && (os.green==green) && (os.blue==blue));
|
void clear_state();
|
||||||
}
|
|
||||||
|
void send_sync();
|
||||||
|
|
||||||
|
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);
|
||||||
};
|
};
|
||||||
|
|
||||||
// private members
|
// private members
|
||||||
|
@ -89,6 +138,10 @@ private:
|
||||||
oreo_state _state_desired[OREOLED_NUM_LEDS]; // desired state
|
oreo_state _state_desired[OREOLED_NUM_LEDS]; // desired state
|
||||||
oreo_state _state_sent[OREOLED_NUM_LEDS]; // last state sent to led
|
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 _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
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CONFIG_HAL_BOARD == HAL_BOARD_PX4
|
#endif // CONFIG_HAL_BOARD == HAL_BOARD_PX4
|
||||||
|
|
Loading…
Reference in New Issue