Simplified the RGBLED driver

This commit is contained in:
Julian Oes
2013-08-16 13:04:57 +02:00
parent 2c6570cec8
commit 0fe612e843
2 changed files with 136 additions and 143 deletions
+16 -11
View File
@@ -67,22 +67,26 @@
#define RGBLED_SET_USER_SCRIPT _RGBLEDIOC(3) #define RGBLED_SET_USER_SCRIPT _RGBLEDIOC(3)
/** set constant RGB values */ /** set constant RGB values */
#define RGBLED_SET _RGBLEDIOC(4) #define RGBLED_SET_RGB _RGBLEDIOC(4)
/** set color */ /** set color */
#define RGBLED_SET_COLOR _RGBLEDIOC(5) #define RGBLED_SET_COLOR _RGBLEDIOC(5)
/** set blink pattern and speed */
#define RGBLED_SET_MODE _RGBLEDIOC(6)
/* /*
structure passed to RGBLED_SET ioctl() structure passed to RGBLED_SET_RGB ioctl()
Note that the driver scales the brightness to 0 to 255, regardless Note that the driver scales the brightness to 0 to 255, regardless
of the hardware scaling of the hardware scaling
*/ */
struct RGBLEDSet { typedef struct {
uint8_t red; uint8_t red;
uint8_t green; uint8_t green;
uint8_t blue; uint8_t blue;
}; } rgbled_rgbset_t;
/* enum passed to RGBLED_SET_COLOR ioctl()*/
typedef enum { typedef enum {
RGBLED_COLOR_OFF, RGBLED_COLOR_OFF,
RGBLED_COLOR_RED, RGBLED_COLOR_RED,
@@ -91,13 +95,14 @@ typedef enum {
RGBLED_COLOR_GREEN, RGBLED_COLOR_GREEN,
RGBLED_COLOR_BLUE, RGBLED_COLOR_BLUE,
RGBLED_COLOR_WHITE, RGBLED_COLOR_WHITE,
RGBLED_COLOR_AMBER, RGBLED_COLOR_AMBER
} rgbled_color_t; } rgbled_color_t;
/* enum passed to RGBLED_SET_MODE ioctl()*/
typedef enum { typedef enum {
RGBLED_BLINK_ON, RGBLED_MODE_OFF,
RGBLED_BLINK_FAST, RGBLED_MODE_ON,
RGBLED_BLINK_NORMAL, RGBLED_MODE_BLINK_SLOW,
RGBLED_BLINK_SLOW, RGBLED_MODE_BLINK_NORMAL,
RGBLED_BLINK_OFF RGBLED_MODE_BLINK_FAST
} rgbled_blinkmode_t; } rgbled_mode_t;
+120 -132
View File
@@ -77,13 +77,6 @@
#define SETTING_ENABLE 0x02 /**< on */ #define SETTING_ENABLE 0x02 /**< on */
enum ledModes {
RGBLED_MODE_TEST,
RGBLED_MODE_SYSTEMSTATE,
RGBLED_MODE_OFF,
RGBLED_MODE_RGB
};
class RGBLED : public device::I2C class RGBLED : public device::I2C
{ {
public: public:
@@ -94,29 +87,29 @@ public:
virtual int init(); virtual int init();
virtual int probe(); virtual int probe();
virtual int info(); virtual int info();
virtual int setMode(enum ledModes mode);
virtual int ioctl(struct file *filp, int cmd, unsigned long arg); virtual int ioctl(struct file *filp, int cmd, unsigned long arg);
private: private:
work_s _work; work_s _work;
rgbled_color_t _led_colors[8]; rgbled_color_t _colors[8];
rgbled_blinkmode_t _led_blinkmode; rgbled_mode_t _mode;
// RGB values for MODE_RGB bool _should_run;
struct RGBLEDSet _rgb; bool _running;
int _led_interval;
int _counter;
int _mode; void set_color(rgbled_color_t ledcolor);
int _running; void set_mode(rgbled_mode_t mode);
void setLEDColor(rgbled_color_t ledcolor);
static void led_trampoline(void *arg); static void led_trampoline(void *arg);
void led(); void led();
int set(bool on, uint8_t r, uint8_t g, uint8_t b); int set(bool on, uint8_t r, uint8_t g, uint8_t b);
int set_on(bool on); int set_on(bool on);
int set_rgb(uint8_t r, uint8_t g, uint8_t b); int set_rgb(uint8_t r, uint8_t g, uint8_t b);
int get(bool &on, bool &not_powersave, uint8_t &r, uint8_t &g, uint8_t &b); int get(bool &on, bool &not_powersave, uint8_t &r, uint8_t &g, uint8_t &b);
}; };
/* for now, we only support one RGBLED */ /* for now, we only support one RGBLED */
@@ -130,10 +123,11 @@ extern "C" __EXPORT int rgbled_main(int argc, char *argv[]);
RGBLED::RGBLED(int bus, int rgbled) : RGBLED::RGBLED(int bus, int rgbled) :
I2C("rgbled", RGBLED_DEVICE_PATH, bus, rgbled, 100000), I2C("rgbled", RGBLED_DEVICE_PATH, bus, rgbled, 100000),
_led_colors({RGBLED_COLOR_OFF,RGBLED_COLOR_OFF,RGBLED_COLOR_OFF,RGBLED_COLOR_OFF,RGBLED_COLOR_OFF,RGBLED_COLOR_OFF,RGBLED_COLOR_OFF,RGBLED_COLOR_OFF}), _colors({RGBLED_COLOR_OFF,RGBLED_COLOR_OFF,RGBLED_COLOR_OFF,RGBLED_COLOR_OFF,RGBLED_COLOR_OFF,RGBLED_COLOR_OFF,RGBLED_COLOR_OFF,RGBLED_COLOR_OFF}),
_led_blinkmode(RGBLED_BLINK_OFF),
_mode(RGBLED_MODE_OFF), _mode(RGBLED_MODE_OFF),
_running(false) _running(false),
_led_interval(0),
_counter(0)
{ {
memset(&_work, 0, sizeof(_work)); memset(&_work, 0, sizeof(_work));
} }
@@ -158,35 +152,6 @@ RGBLED::init()
return OK; return OK;
} }
int
RGBLED::setMode(enum ledModes new_mode)
{
switch (new_mode) {
case RGBLED_MODE_SYSTEMSTATE:
case RGBLED_MODE_TEST:
case RGBLED_MODE_RGB:
_mode = new_mode;
if (!_running) {
_running = true;
set_on(true);
work_queue(LPWORK, &_work, (worker_t)&RGBLED::led_trampoline, this, 1);
}
break;
case RGBLED_MODE_OFF:
default:
if (_running) {
_running = false;
set_on(false);
}
_mode = RGBLED_MODE_OFF;
break;
}
return OK;
}
int int
RGBLED::probe() RGBLED::probe()
{ {
@@ -225,16 +190,24 @@ RGBLED::ioctl(struct file *filp, int cmd, unsigned long arg)
int ret = ENOTTY; int ret = ENOTTY;
switch (cmd) { switch (cmd) {
case RGBLED_SET: { case RGBLED_SET_RGB:
/* set the specified RGB values */ /* set the specified RGB values */
memcpy(&_rgb, (struct RGBLEDSet *)arg, sizeof(_rgb)); rgbled_rgbset_t rgbset;
setMode(RGBLED_MODE_RGB); memcpy(&rgbset, (rgbled_rgbset_t*)arg, sizeof(rgbset));
set_rgb(rgbset.red, rgbset.green, rgbset.blue);
set_mode(RGBLED_MODE_ON);
return OK; return OK;
}
case RGBLED_SET_COLOR: { case RGBLED_SET_COLOR:
/* set the specified color name */ /* set the specified color name */
setLEDColor((rgbled_color_t)arg); set_color((rgbled_color_t)arg);
} return OK;
case RGBLED_SET_MODE:
/* set the specified blink pattern/speed */
set_mode((rgbled_mode_t)arg);
return OK;
default: default:
break; break;
@@ -257,77 +230,32 @@ RGBLED::led_trampoline(void *arg)
void void
RGBLED::led() RGBLED::led()
{ {
static int led_thread_runcount=0;
static int _led_interval = 1000;
switch (_mode) { switch (_mode) {
case RGBLED_MODE_TEST: case RGBLED_MODE_BLINK_SLOW:
/* Demo LED pattern for now */ case RGBLED_MODE_BLINK_NORMAL:
_led_colors[0] = RGBLED_COLOR_YELLOW; case RGBLED_MODE_BLINK_FAST:
_led_colors[1] = RGBLED_COLOR_AMBER; if(_counter % 2 == 0)
_led_colors[2] = RGBLED_COLOR_RED; set_on(true);
_led_colors[3] = RGBLED_COLOR_PURPLE; else
_led_colors[4] = RGBLED_COLOR_BLUE; set_on(false);
_led_colors[5] = RGBLED_COLOR_GREEN;
_led_colors[6] = RGBLED_COLOR_WHITE;
_led_colors[7] = RGBLED_COLOR_OFF;
_led_blinkmode = RGBLED_BLINK_ON;
break; break;
case RGBLED_MODE_SYSTEMSTATE:
/* XXX TODO set pattern */
_led_colors[0] = RGBLED_COLOR_OFF;
_led_colors[1] = RGBLED_COLOR_OFF;
_led_colors[2] = RGBLED_COLOR_OFF;
_led_colors[3] = RGBLED_COLOR_OFF;
_led_colors[4] = RGBLED_COLOR_OFF;
_led_colors[5] = RGBLED_COLOR_OFF;
_led_colors[6] = RGBLED_COLOR_OFF;
_led_colors[7] = RGBLED_COLOR_OFF;
_led_blinkmode = RGBLED_BLINK_OFF;
break;
case RGBLED_MODE_RGB:
set_rgb(_rgb.red, _rgb.green, _rgb.blue);
_running = false;
return;
case RGBLED_MODE_OFF:
default: default:
return;
break; break;
} }
_counter++;
if (led_thread_runcount & 1) { /* re-queue ourselves to run again later */
if (_led_blinkmode == RGBLED_BLINK_ON) work_queue(LPWORK, &_work, (worker_t)&RGBLED::led_trampoline, this, _led_interval);
setLEDColor(RGBLED_COLOR_OFF);
_led_interval = RGBLED_OFFTIME;
} else {
setLEDColor(_led_colors[(led_thread_runcount/2) % 8]);
_led_interval = RGBLED_ONTIME;
}
led_thread_runcount++;
if(_running) {
/* re-queue ourselves to run again later */
work_queue(LPWORK, &_work, (worker_t)&RGBLED::led_trampoline, this, _led_interval);
} else if (_mode == RGBLED_MODE_RGB) {
// no need to run again until the colour changes
set_on(true);
} else {
set_on(false);
}
} }
void RGBLED::setLEDColor(rgbled_color_t ledcolor) { void
switch (ledcolor) { RGBLED::set_color(rgbled_color_t color) {
case RGBLED_COLOR_OFF: // off switch (color) {
case RGBLED_COLOR_OFF: // off
set_rgb(0,0,0); set_rgb(0,0,0);
break; break;
case RGBLED_COLOR_RED: // red case RGBLED_COLOR_RED: // red
set_rgb(255,0,0); set_rgb(255,0,0);
break; break;
case RGBLED_COLOR_YELLOW: // yellow case RGBLED_COLOR_YELLOW: // yellow
@@ -339,7 +267,7 @@ void RGBLED::setLEDColor(rgbled_color_t ledcolor) {
case RGBLED_COLOR_GREEN: // green case RGBLED_COLOR_GREEN: // green
set_rgb(0,255,0); set_rgb(0,255,0);
break; break;
case RGBLED_COLOR_BLUE: // blue case RGBLED_COLOR_BLUE: // blue
set_rgb(0,0,255); set_rgb(0,0,255);
break; break;
case RGBLED_COLOR_WHITE: // white case RGBLED_COLOR_WHITE: // white
@@ -348,6 +276,52 @@ void RGBLED::setLEDColor(rgbled_color_t ledcolor) {
case RGBLED_COLOR_AMBER: // amber case RGBLED_COLOR_AMBER: // amber
set_rgb(255,20,0); set_rgb(255,20,0);
break; break;
default:
warnx("color unknown");
break;
}
}
void
RGBLED::set_mode(rgbled_mode_t mode)
{
_mode = mode;
switch (mode) {
case RGBLED_MODE_OFF:
_should_run = false;
set_on(false);
break;
case RGBLED_MODE_ON:
_should_run = false;
set_on(true);
break;
case RGBLED_MODE_BLINK_SLOW:
_should_run = true;
_led_interval = 2000;
break;
case RGBLED_MODE_BLINK_NORMAL:
_should_run = true;
_led_interval = 1000;
break;
case RGBLED_MODE_BLINK_FAST:
_should_run = true;
_led_interval = 500;
break;
default:
warnx("mode unknown");
break;
}
/* if it should run now, start the workq */
if (_should_run && !_running) {
_running = true;
work_queue(LPWORK, &_work, (worker_t)&RGBLED::led_trampoline, this, 1);
}
/* if it should stop, then cancel the workq */
if (!_should_run && _running) {
_running = false;
work_cancel(LPWORK, &_work);
} }
} }
@@ -417,7 +391,7 @@ void rgbled_usage();
void rgbled_usage() { void rgbled_usage() {
warnx("missing command: try 'start', 'systemstate', 'test', 'info', 'off', 'rgb'"); warnx("missing command: try 'start', 'test', 'info', 'off', 'rgb'");
warnx("options:"); warnx("options:");
warnx(" -b i2cbus (%d)", PX4_I2C_BUS_LED); warnx(" -b i2cbus (%d)", PX4_I2C_BUS_LED);
errx(0, " -a addr (0x%x)", ADDR); errx(0, " -a addr (0x%x)", ADDR);
@@ -446,6 +420,9 @@ rgbled_main(int argc, char *argv[])
argv += optind; argv += optind;
const char *verb = argv[0]; const char *verb = argv[0];
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");
@@ -480,19 +457,25 @@ rgbled_main(int argc, char *argv[])
/* need the driver past this point */ /* need the driver past this point */
if (g_rgbled == nullptr) { if (g_rgbled == nullptr) {
fprintf(stderr, "not started\n"); warnx("not started");
rgbled_usage(); rgbled_usage();
exit(0); exit(0);
} }
if (!strcmp(verb, "test")) { if (!strcmp(verb, "test")) {
g_rgbled->setMode(RGBLED_MODE_TEST); fd = open(RGBLED_DEVICE_PATH, 0);
exit(0); if (fd == -1) {
} errx(1, "Unable to open " RGBLED_DEVICE_PATH);
}
ret = ioctl(fd, RGBLED_SET_COLOR, (unsigned long)RGBLED_COLOR_WHITE);
if (!strcmp(verb, "systemstate")) { if(ret != OK) {
g_rgbled->setMode(RGBLED_MODE_SYSTEMSTATE); close(fd);
exit(0); exit(ret);
}
ret = ioctl(fd, RGBLED_SET_MODE, (unsigned long)RGBLED_MODE_BLINK_NORMAL);
close(fd);
exit(ret);
} }
if (!strcmp(verb, "info")) { if (!strcmp(verb, "info")) {
@@ -501,23 +484,28 @@ rgbled_main(int argc, char *argv[])
} }
if (!strcmp(verb, "off")) { if (!strcmp(verb, "off")) {
g_rgbled->setMode(RGBLED_MODE_OFF); fd = open(RGBLED_DEVICE_PATH, 0);
exit(0); if (fd == -1) {
errx(1, "Unable to open " RGBLED_DEVICE_PATH);
}
ret = ioctl(fd, RGBLED_SET_MODE, (unsigned long)RGBLED_MODE_OFF);
close(fd);
exit(ret);
} }
if (!strcmp(verb, "rgb")) { if (!strcmp(verb, "rgb")) {
int fd = open(RGBLED_DEVICE_PATH, 0); fd = open(RGBLED_DEVICE_PATH, 0);
if (fd == -1) { if (fd == -1) {
errx(1, "Unable to open " RGBLED_DEVICE_PATH); errx(1, "Unable to open " RGBLED_DEVICE_PATH);
} }
if (argc < 4) { if (argc < 4) {
errx(1, "Usage: rgbled rgb <red> <green> <blue>"); errx(1, "Usage: rgbled rgb <red> <green> <blue>");
} }
struct RGBLEDSet v; rgbled_rgbset_t v;
v.red = strtol(argv[1], NULL, 0); v.red = strtol(argv[1], NULL, 0);
v.green = strtol(argv[2], NULL, 0); v.green = strtol(argv[2], NULL, 0);
v.blue = strtol(argv[3], NULL, 0); v.blue = strtol(argv[3], NULL, 0);
int ret = ioctl(fd, RGBLED_SET, (unsigned long)&v); ret = ioctl(fd, RGBLED_SET_RGB, (unsigned long)&v);
close(fd); close(fd);
exit(ret); exit(ret);
} }