102 #include <px4_platform_common/px4_work_queue/ScheduledWorkItem.hpp> 116 class BlinkM :
public device::I2C,
public px4::ScheduledWorkItem
119 BlinkM(
int bus,
int blinkm);
201 int set_rgb(uint8_t r, uint8_t g, uint8_t b);
203 int fade_rgb(uint8_t r, uint8_t g, uint8_t b);
204 int fade_hsb(uint8_t h, uint8_t s, uint8_t b);
215 int write_script_line(uint8_t line, uint8_t ticks, uint8_t cmd, uint8_t arg1, uint8_t arg2, uint8_t arg3);
217 int set_script(uint8_t length, uint8_t repeats);
219 int get_rgb(uint8_t &r, uint8_t &g, uint8_t &b);
259 ScheduledWorkItem(MODULE_NAME,
px4::device_bus_to_wq(get_device_id())),
288 warnx(
"I2C init failed");
325 DEVICE_DEBUG(
"found BlinkM firmware version %c%c", version[1], version[0]);
357 const uint8_t *script = (
const uint8_t *)arg;
359 while ((lines < 50) && (script[1] != 0)) {
360 ret =
write_script_line(lines, script[0], script[1], script[2], script[3], script[4]);
446 int no_data_vehicle_status = 0;
447 int no_data_battery_status = 0;
448 int no_data_vehicle_control_mode = 0;
449 int no_data_actuator_armed = 0;
450 int no_data_vehicle_gps_position = 0;
456 if (new_data_vehicle_status) {
458 no_data_vehicle_status = 0;
461 no_data_vehicle_status++;
463 if (no_data_vehicle_status >= 3) {
464 no_data_vehicle_status = 3;
472 if (new_data_battery_status) {
476 no_data_battery_status++;
478 if (no_data_battery_status >= 3) {
479 no_data_battery_status = 3;
487 if (new_data_vehicle_control_mode) {
489 no_data_vehicle_control_mode = 0;
492 no_data_vehicle_control_mode++;
494 if (no_data_vehicle_control_mode >= 3) {
495 no_data_vehicle_control_mode = 3;
503 if (new_data_actuator_armed) {
505 no_data_actuator_armed = 0;
508 no_data_actuator_armed++;
510 if (no_data_actuator_armed >= 3) {
511 no_data_actuator_armed = 3;
519 if (new_data_vehicle_gps_position) {
521 no_data_vehicle_gps_position = 0;
524 no_data_vehicle_gps_position++;
526 if (no_data_vehicle_gps_position >= 3) {
527 no_data_vehicle_gps_position = 3;
536 if (new_data_safety) {
543 if (new_data_battery_status || no_data_battery_status < 3) {
549 if (
battery_status.warning == battery_status_s::BATTERY_WARNING_CRITICAL) {
561 }
else if (vehicle_status_raw.rc_signal_lost) {
573 }
else if (
battery_status.warning == battery_status_s::BATTERY_WARNING_LOW) {
588 if (actuator_armed.armed ==
false) {
625 if (new_data_vehicle_control_mode || no_data_vehicle_control_mode < 3) {
628 if (vehicle_control_mode.flag_control_auto_enabled) {
631 }
else if (vehicle_control_mode.flag_control_position_enabled) {
634 }
else if (vehicle_control_mode.flag_control_altitude_enabled) {
637 }
else if (vehicle_control_mode.flag_control_manual_enabled) {
647 if (new_data_vehicle_gps_position || no_data_vehicle_gps_position < 3) {
774 const uint8_t
msg[4] = {
'n', r, g, b };
776 return transfer(msg,
sizeof(msg),
nullptr, 0);
782 const uint8_t
msg[4] = {
'c', r, g, b };
784 return transfer(msg,
sizeof(msg),
nullptr, 0);
790 const uint8_t
msg[4] = {
'h', h, s, b };
792 return transfer(msg,
sizeof(msg),
nullptr, 0);
798 const uint8_t
msg[4] = {
'C', r, g, b };
800 return transfer(msg,
sizeof(msg),
nullptr, 0);
806 const uint8_t
msg[4] = {
'H', h, s, b };
808 return transfer(msg,
sizeof(msg),
nullptr, 0);
814 const uint8_t
msg[2] = {
'f', s };
816 return transfer(msg,
sizeof(msg),
nullptr, 0);
822 const uint8_t
msg[4] = {
'p', script_id, 0, 0 };
824 return transfer(msg,
sizeof(msg),
nullptr, 0);
831 if (isxdigit(script_name[0]) && (strlen(script_name) == 6)) {
837 code[0] = script_name[1];
838 code[1] = script_name[2];
839 r = strtol(code, 0, 16);
840 code[0] = script_name[3];
841 code[1] = script_name[4];
842 g = strtol(code, 0, 16);
843 code[0] = script_name[5];
844 code[1] = script_name[6];
845 b = strtol(code, 0, 16);
862 const uint8_t
msg[1] = {
'o' };
864 return transfer(msg,
sizeof(msg),
nullptr, 0);
870 const uint8_t
msg[8] = {
'W', 0, line, ticks, cmd, arg1, arg2, arg3 };
872 return transfer(msg,
sizeof(msg),
nullptr, 0);
878 const uint8_t
msg[3] = {
'R', 0, line };
881 int ret = transfer(msg,
sizeof(msg), result,
sizeof(result));
897 const uint8_t
msg[4] = {
'L', 0, len, repeats };
899 return transfer(msg,
sizeof(msg),
nullptr, 0);
905 const uint8_t
msg =
'g';
908 int ret = transfer(&msg,
sizeof(msg), result,
sizeof(result));
922 const uint8_t
msg =
'Z';
924 return transfer(&msg,
sizeof(msg), version, 2);
931 warnx(
"missing command: try 'start', 'systemstate', 'ledoff', 'list' or a script name {options}");
933 warnx(
"\t-b --bus i2cbus (3)");
934 warnx(
"\t-a --blinkmaddr blinkmaddr (9)");
941 int i2cdevice = PX4_I2C_BUS_EXPANSION;
951 for (x = 1; x < argc; x++) {
952 if (strcmp(argv[x],
"-b") == 0 || strcmp(argv[x],
"--bus") == 0) {
954 i2cdevice = atoi(argv[x + 1]);
958 if (strcmp(argv[x],
"-a") == 0 || strcmp(argv[x],
"--blinkmaddr") == 0) {
960 blinkmadr = atoi(argv[x + 1]);
966 if (!strcmp(argv[1],
"start")) {
967 if (g_blinkm !=
nullptr) {
968 warnx(
"already started");
972 g_blinkm =
new BlinkM(i2cdevice, blinkmadr);
974 if (g_blinkm ==
nullptr) {
979 if (
OK != g_blinkm->init()) {
982 warnx(
"init failed");
990 if (g_blinkm ==
nullptr) {
991 PX4_ERR(
"not started");
996 if (!strcmp(argv[1],
"systemstate")) {
997 g_blinkm->setMode(1);
1001 if (!strcmp(argv[1],
"ledoff")) {
1002 g_blinkm->setMode(0);
1007 if (!strcmp(argv[1],
"list")) {
1012 PX4_ERR(
" <html color number>");
1020 warn(
"can't open BlinkM device");
1024 g_blinkm->setMode(0);
#define BLINKM_PLAY_SCRIPT_NAMED
play the named script in *(char *)arg, repeating forever
int fade_rgb(uint8_t r, uint8_t g, uint8_t b)
int write_script_line(uint8_t line, uint8_t ticks, uint8_t cmd, uint8_t arg1, uint8_t arg2, uint8_t arg3)
__EXPORT int blinkm_main(int argc, char *argv[])
static const int LED_OFFTIME
uORB::Subscription vehicle_status_sub
int set_rgb(uint8_t r, uint8_t g, uint8_t b)
uORB::Subscription safety_sub
static const int LED_ONTIME
#define BLINKM_PLAY_SCRIPT
play the numbered script in (arg), repeating forever
bool detected_cells_blinked
static char msg[NUM_MSG][CONFIG_USART1_TXBUFSIZE]
static struct safety_s safety
#define ORB_ID(_name)
Generates a pointer to the uORB metadata structure for a given topic.
int fade_hsb_random(uint8_t h, uint8_t s, uint8_t b)
void init()
Activates/configures the hardware registers.
#define BLINKM0_DEVICE_PATH
uORB::Subscription vehicle_gps_position_sub
virtual ~BlinkM()=default
int get_firmware_version(uint8_t version[2])
uORB::Subscription vehicle_control_mode_sub
uORB::Subscription actuator_armed_sub
int fade_hsb(uint8_t h, uint8_t s, uint8_t b)
bool updated()
Check if there is a new update.
uORB::Subscription battery_status_sub
int set_script(uint8_t length, uint8_t repeats)
static const int LED_BLINK
int set_fade_speed(uint8_t s)
virtual int setMode(int mode)
static const char *const script_names[]
int read_script_line(uint8_t line, uint8_t &ticks, uint8_t cmd[4])
#define BLINKM_SET_USER_SCRIPT
Set the user script; (arg) is a pointer to an array of script lines, where each line is an array of f...
int fade_rgb_random(uint8_t r, uint8_t g, uint8_t b)
int detected_cells_runcount
static const int LED_NOBLINK
int get_rgb(uint8_t &r, uint8_t &g, uint8_t &b)
BlinkM(int bus, int blinkm)
int play_script(uint8_t script_id)
void setLEDColor(int ledcolor)
virtual int ioctl(device::file_t *filp, int cmd, unsigned long arg)
bool copy(void *dst)
Copy the struct.
#define DEVICE_DEBUG(FMT,...)
Base class for devices connected via I2C.