Browse Source

rgbled_pwm: switch to new led uorb interface

sbg
Beat Küng 8 years ago committed by Lorenz Meier
parent
commit
7fd6748f34
  1. 1
      src/drivers/rgbled_pwm/CMakeLists.txt
  2. 461
      src/drivers/rgbled_pwm/rgbled_pwm.cpp

1
src/drivers/rgbled_pwm/CMakeLists.txt

@ -38,5 +38,6 @@ px4_add_module(
rgbled_pwm.cpp rgbled_pwm.cpp
DEPENDS DEPENDS
platforms__common platforms__common
lib__led
) )
# vim: set noet ft=cmake fenc=utf-8 ff=unix : # vim: set noet ft=cmake fenc=utf-8 ff=unix :

461
src/drivers/rgbled_pwm/rgbled_pwm.cpp

@ -62,7 +62,8 @@
#include <board_config.h> #include <board_config.h>
#include <drivers/drv_rgbled.h> #include <drivers/drv_led.h>
#include <lib/led/led.h>
#include <drivers/device/device.h> #include <drivers/device/device.h>
#include <systemlib/err.h> #include <systemlib/err.h>
@ -78,44 +79,24 @@ public:
virtual int init(); virtual int init();
virtual int probe(); virtual int probe();
virtual int info(); int status();
virtual int ioctl(struct file *filp, int cmd, unsigned long arg);
private: private:
struct hrt_call _call;
struct hrt_call _call_r;
struct hrt_call _call_g;
struct hrt_call _call_b;
work_s _work; work_s _work;
rgbled_mode_t _mode;
rgbled_pattern_t _pattern;
uint8_t _r; uint8_t _r;
uint8_t _g; uint8_t _g;
uint8_t _b; uint8_t _b;
bool _enable;
float _brightness; float _brightness;
bool _running; volatile bool _running;
int _led_interval; volatile bool _should_run;
bool _should_run;
int _counter;
static void pwm_begin(void *arg); LedController _led_controller;
static void pwm_end_r(void *arg);
static void pwm_end_g(void *arg);
static void pwm_end_b(void *arg);
void set_color(rgbled_color_t ledcolor);
void set_mode(rgbled_mode_t mode);
void set_pattern(rgbled_pattern_t *pattern);
static void led_trampoline(void *arg); static void led_trampoline(void *arg);
void led(); void led();
int send_led_enable(bool enable);
int send_led_rgb(); int send_led_rgb();
int get(bool &on, bool &powersave, uint8_t &r, uint8_t &g, uint8_t &b); int get(bool &on, bool &powersave, uint8_t &r, uint8_t &g, uint8_t &b);
}; };
@ -137,32 +118,24 @@ void rgbled_usage();
RGBLED_PWM::RGBLED_PWM() : RGBLED_PWM::RGBLED_PWM() :
CDev("rgbled", RGBLED0_DEVICE_PATH), CDev("rgbled", RGBLED0_DEVICE_PATH),
_call{}, _work{},
_call_r{},
_call_g{},
_call_b{},
_mode(RGBLED_MODE_OFF),
_r(0), _r(0),
_g(0), _g(0),
_b(0), _b(0),
_enable(false),
_brightness(1.0f), _brightness(1.0f),
_running(false), _running(false),
_led_interval(0), _should_run(true)
_should_run(false),
_counter(0)
{ {
memset(&_work, 0, sizeof(_work));
memset(&_pattern, 0, sizeof(_pattern));
memset(&_call, 0, sizeof(_call));
memset(&_call_r, 0, sizeof(_call_r));
memset(&_call_g, 0, sizeof(_call_g));
memset(&_call_b, 0, sizeof(_call_b));
} }
RGBLED_PWM::~RGBLED_PWM() RGBLED_PWM::~RGBLED_PWM()
{ {
_should_run = false;
int counter = 0;
while (_running && ++counter < 10) {
usleep(100000);
}
} }
int int
@ -171,32 +144,17 @@ RGBLED_PWM::init()
/* switch off LED on start */ /* switch off LED on start */
CDev::init(); CDev::init();
led_pwm_servo_init(); led_pwm_servo_init();
send_led_enable(false);
send_led_rgb(); send_led_rgb();
return OK;
}
void
RGBLED_PWM::pwm_begin(void *arg)
{
}
_running = true;
// kick off work queue
work_queue(LPWORK, &_work, (worker_t)&RGBLED_PWM::led_trampoline, this, 0);
void return OK;
RGBLED_PWM::pwm_end_r(void *arg)
{
}
void
RGBLED_PWM::pwm_end_g(void *arg)
{
}
void
RGBLED_PWM::pwm_end_b(void *arg)
{
} }
int int
RGBLED_PWM::info() RGBLED_PWM::status()
{ {
int ret; int ret;
bool on, powersave; bool on, powersave;
@ -220,45 +178,6 @@ RGBLED_PWM::probe()
{ {
return (OK); return (OK);
} }
int
RGBLED_PWM::ioctl(struct file *filp, int cmd, unsigned long arg)
{
int ret = ENOTTY;
switch (cmd) {
case RGBLED_SET_RGB:
/* set the specified color */
_r = ((rgbled_rgbset_t *) arg)->red;
_g = ((rgbled_rgbset_t *) arg)->green;
_b = ((rgbled_rgbset_t *) arg)->blue;
send_led_rgb();
return OK;
case RGBLED_SET_COLOR:
/* set the specified color name */
set_color((rgbled_color_t)arg);
send_led_rgb();
return OK;
case RGBLED_SET_MODE:
/* set the specified mode */
set_mode((rgbled_mode_t)arg);
return OK;
case RGBLED_SET_PATTERN:
/* set a special pattern */
set_pattern((rgbled_pattern_t *)arg);
return OK;
default:
/* see if the parent class can make any use of it */
ret = CDev::ioctl(filp, cmd, arg);
break;
}
return ret;
}
void void
RGBLED_PWM::led_trampoline(void *arg) RGBLED_PWM::led_trampoline(void *arg)
@ -275,257 +194,65 @@ void
RGBLED_PWM::led() RGBLED_PWM::led()
{ {
if (!_should_run) { if (!_should_run) {
_running = false; int led_control_sub = _led_controller.led_control_subscription();
return;
}
switch (_mode) {
case RGBLED_MODE_BLINK_SLOW:
case RGBLED_MODE_BLINK_NORMAL:
case RGBLED_MODE_BLINK_FAST:
if (_counter >= 2) {
_counter = 0;
}
send_led_enable(_counter == 0);
break;
case RGBLED_MODE_BREATHE:
if (_counter >= 62) { if (led_control_sub >= 0) {
_counter = 0; orb_unsubscribe(led_control_sub);
} }
int n; _running = false;
return;
if (_counter < 32) {
n = _counter;
} else {
n = 62 - _counter;
}
_brightness = n * n / (31.0f * 31.0f);
// send_led_rgb();
break;
case RGBLED_MODE_PATTERN:
/* don't run out of the pattern array and stop if the next frame is 0 */
if (_counter >= RGBLED_PATTERN_LENGTH || _pattern.duration[_counter] <= 0) {
_counter = 0;
}
set_color(_pattern.color[_counter]);
send_led_rgb();
_led_interval = _pattern.duration[_counter];
break;
default:
break;
} }
_counter++; if (!_led_controller.is_init()) {
int led_control_sub = orb_subscribe(ORB_ID(led_control));
/* re-queue ourselves to run again later */ _led_controller.init(led_control_sub);
work_queue(LPWORK, &_work, (worker_t)&RGBLED_PWM::led_trampoline, this, _led_interval);
}
/**
* Parse color constant and set _r _g _b values
*/
void
RGBLED_PWM::set_color(rgbled_color_t color)
{
switch (color) {
case RGBLED_COLOR_OFF:
_r = 0;
_g = 0;
_b = 0;
break;
case RGBLED_COLOR_RED:
_r = 255;
_g = 0;
_b = 0;
break;
case RGBLED_COLOR_YELLOW:
_r = 255;
_g = 200;
_b = 0;
break;
case RGBLED_COLOR_PURPLE:
_r = 255;
_g = 0;
_b = 255;
break;
case RGBLED_COLOR_GREEN:
_r = 0;
_g = 255;
_b = 0;
break;
case RGBLED_COLOR_BLUE:
_r = 0;
_g = 0;
_b = 255;
break;
case RGBLED_COLOR_WHITE:
_r = 255;
_g = 255;
_b = 255;
break;
case RGBLED_COLOR_AMBER:
_r = 255;
_g = 80;
_b = 0;
break;
case RGBLED_COLOR_DIM_RED:
_r = 90;
_g = 0;
_b = 0;
break;
case RGBLED_COLOR_DIM_YELLOW:
_r = 80;
_g = 30;
_b = 0;
break;
case RGBLED_COLOR_DIM_PURPLE:
_r = 45;
_g = 0;
_b = 45;
break;
case RGBLED_COLOR_DIM_GREEN:
_r = 0;
_g = 90;
_b = 0;
break;
case RGBLED_COLOR_DIM_BLUE:
_r = 0;
_g = 0;
_b = 90;
break;
case RGBLED_COLOR_DIM_WHITE:
_r = 30;
_g = 30;
_b = 30;
break;
case RGBLED_COLOR_DIM_AMBER:
_r = 80;
_g = 20;
_b = 0;
break;
default:
PX4_WARN("color unknown");
break;
} }
}
/** LedControlData led_control_data;
* Set mode, if mode not changed has no any effect (doesn't reset blinks phase)
*/
void
RGBLED_PWM::set_mode(rgbled_mode_t mode)
{
if (mode != _mode) {
_mode = mode;
switch (mode) { if (_led_controller.update(led_control_data) == 1) {
case RGBLED_MODE_OFF: switch (led_control_data.leds[0].color) {
_should_run = false; case led_control_s::COLOR_RED:
send_led_enable(false); _r = 255; _g = 0; _b = 0;
break; break;
case RGBLED_MODE_ON: case led_control_s::COLOR_GREEN:
_brightness = 1.0f; _r = 0; _g = 255; _b = 0;
send_led_rgb();
send_led_enable(true);
break; break;
case RGBLED_MODE_BLINK_SLOW: case led_control_s::COLOR_BLUE:
_should_run = true; _r = 0; _g = 0; _b = 255;
_counter = 0;
_led_interval = 2000;
_brightness = 1.0f;
send_led_rgb();
break; break;
case RGBLED_MODE_BLINK_NORMAL: case led_control_s::COLOR_AMBER: //make it the same as yellow
_should_run = true; case led_control_s::COLOR_YELLOW:
_counter = 0; _r = 255; _g = 255; _b = 0;
_led_interval = 500;
_brightness = 1.0f;
send_led_rgb();
break; break;
case RGBLED_MODE_BLINK_FAST: case led_control_s::COLOR_PURPLE:
_should_run = true; _r = 255; _g = 0; _b = 255;
_counter = 0;
_led_interval = 100;
_brightness = 1.0f;
send_led_rgb();
break; break;
case RGBLED_MODE_BREATHE: case led_control_s::COLOR_CYAN:
_should_run = true; _r = 0; _g = 255; _b = 255;
_counter = 0;
_led_interval = 25;
send_led_enable(true);
break; break;
case RGBLED_MODE_PATTERN: case led_control_s::COLOR_WHITE:
_should_run = true; _r = 255; _g = 255; _b = 255;
_counter = 0;
_brightness = 1.0f;
send_led_enable(true);
break; break;
default: default: // led_control_s::COLOR_OFF
PX4_WARN("mode unknown"); _r = 0; _g = 0; _b = 0;
break; break;
} }
/* if it should run now, start the workq */ send_led_rgb();
if (_should_run && !_running) {
_running = true;
work_queue(LPWORK, &_work, (worker_t)&RGBLED_PWM::led_trampoline, this, 1);
}
} }
}
/** /* re-queue ourselves to run again later */
* Set pattern for PATTERN mode, but don't change current mode work_queue(LPWORK, &_work, (worker_t)&RGBLED_PWM::led_trampoline, this,
*/ USEC2TICK(_led_controller.maximum_update_interval()));
void
RGBLED_PWM::set_pattern(rgbled_pattern_t *pattern)
{
memcpy(&_pattern, pattern, sizeof(rgbled_pattern_t));
}
/**
* Sent ENABLE flag to LED driver
*/
int
RGBLED_PWM::send_led_enable(bool enable)
{
_enable = enable;
send_led_rgb();
return (OK);
} }
/** /**
@ -535,16 +262,9 @@ int
RGBLED_PWM::send_led_rgb() RGBLED_PWM::send_led_rgb()
{ {
if (_enable) { led_pwm_servo_set(0, _r);
led_pwm_servo_set(0, _r); led_pwm_servo_set(1, _g);
led_pwm_servo_set(1, _g); led_pwm_servo_set(2, _b);
led_pwm_servo_set(2, _b);
} else {
led_pwm_servo_set(0, 0);
led_pwm_servo_set(1, 0);
led_pwm_servo_set(2, 0);
}
return (OK); return (OK);
} }
@ -552,7 +272,8 @@ RGBLED_PWM::send_led_rgb()
int int
RGBLED_PWM::get(bool &on, bool &powersave, uint8_t &r, uint8_t &g, uint8_t &b) RGBLED_PWM::get(bool &on, bool &powersave, uint8_t &r, uint8_t &g, uint8_t &b)
{ {
powersave = OK; on = _enable; powersave = OK;
on = _r > 0 || _g > 0 || _b > 0;
r = _r; r = _r;
g = _g; g = _g;
b = _b; b = _b;
@ -562,7 +283,7 @@ RGBLED_PWM::get(bool &on, bool &powersave, uint8_t &r, uint8_t &g, uint8_t &b)
void void
rgbled_usage() rgbled_usage()
{ {
PX4_WARN("missing command: try 'start', 'test', 'info', 'off', 'stop', 'rgb 30 40 50'"); PX4_INFO("missing command: try 'start', 'status', 'stop'");
} }
int int
@ -592,9 +313,6 @@ rgbled_main(int argc, char *argv[])
const char *verb = argv[optind]; const char *verb = argv[optind];
int fd;
int ret;
if (!strcmp(verb, "start")) { if (!strcmp(verb, "start")) {
if (g_rgbled != nullptr) { if (g_rgbled != nullptr) {
errx(1, "already started"); errx(1, "already started");
@ -624,68 +342,15 @@ rgbled_main(int argc, char *argv[])
exit(1); exit(1);
} }
if (!strcmp(verb, "test")) { if (!strcmp(verb, "status")) {
fd = open(RGBLED0_DEVICE_PATH, 0); g_rgbled->status();
if (fd == -1) {
errx(1, "Unable to open " RGBLED0_DEVICE_PATH);
}
rgbled_pattern_t pattern = { {RGBLED_COLOR_RED, RGBLED_COLOR_GREEN, RGBLED_COLOR_BLUE, RGBLED_COLOR_WHITE, RGBLED_COLOR_OFF, RGBLED_COLOR_OFF},
{500, 500, 500, 500, 1000, 0 } // "0" indicates end of pattern
};
ret = ioctl(fd, RGBLED_SET_PATTERN, (unsigned long)&pattern);
ret = ioctl(fd, RGBLED_SET_MODE, (unsigned long)RGBLED_MODE_PATTERN);
close(fd);
exit(ret);
}
if (!strcmp(verb, "info")) {
g_rgbled->info();
exit(0); exit(0);
} }
if (!strcmp(verb, "off") || !strcmp(verb, "stop")) { if (!strcmp(verb, "stop")) {
fd = open(RGBLED0_DEVICE_PATH, 0); delete g_rgbled;
g_rgbled = nullptr;
if (fd == -1) { exit(0);
errx(1, "Unable to open " RGBLED0_DEVICE_PATH);
}
ret = ioctl(fd, RGBLED_SET_MODE, (unsigned long)RGBLED_MODE_OFF);
close(fd);
/* delete the rgbled object if stop was requested, in addition to turning off the LED. */
if (!strcmp(verb, "stop")) {
delete g_rgbled;
g_rgbled = nullptr;
exit(0);
}
exit(ret);
}
if (!strcmp(verb, "rgb")) {
if (argc < 5) {
errx(1, "Usage: rgbled rgb <red> <green> <blue>");
}
fd = open(RGBLED0_DEVICE_PATH, 0);
if (fd == -1) {
errx(1, "Unable to open " RGBLED0_DEVICE_PATH);
}
rgbled_rgbset_t v;
v.red = strtol(argv[2], nullptr, 0);
v.green = strtol(argv[3], nullptr, 0);
v.blue = strtol(argv[4], nullptr, 0);
ret = ioctl(fd, RGBLED_SET_RGB, (unsigned long)&v);
ret = ioctl(fd, RGBLED_SET_MODE, (unsigned long)RGBLED_MODE_ON);
close(fd);
exit(ret);
} }
rgbled_usage(); rgbled_usage();

Loading…
Cancel
Save