Update Files
This commit is contained in:
155
Kinc/Sources/kinc/libs/drivers/led/README.md
Normal file
155
Kinc/Sources/kinc/libs/drivers/led/README.md
Normal file
@ -0,0 +1,155 @@
|
||||
# lws_led gpio and pwm class drivers
|
||||
|
||||
Lws provides an abstract led controller class that can bind an array of LEDs
|
||||
to gpio and pwm controllers, and automatically handled pwm sequencers.
|
||||
|
||||
Lumience intensity is corrected for IEC curves to match perceptual intensity,
|
||||
and the correction can be overridden per led for curve adaptation matching.
|
||||
|
||||
Intensity is normalized to a 16-bit scale, when controlled by a GPIO b15 is
|
||||
significant and the rest ignored. When controlled by PWM, as many bits from
|
||||
b15 down are significant as the PWM arrangements can represent.
|
||||
|
||||
The PWM sequencers use arbitrary function generation callbacks on a normalized
|
||||
16-bit phase space, they can choose how much to interpolate and how much to put
|
||||
in a table, a 64-sample, 16-bit sine function is provided along with 16-bit
|
||||
linear sawtooth.
|
||||
|
||||
Changing the sequencer is subject to a third transition function sequencer, this
|
||||
can for example mix the transition linearly over, eg, 500ms so the leds look
|
||||
very smooth.
|
||||
|
||||
## Defining an led controller
|
||||
|
||||
An array of inidividual LED information is provided first, and referenced by
|
||||
the LED controller definintion. Leds are named so code does not introduce
|
||||
dependencies on specific implementations.
|
||||
|
||||
```
|
||||
static const lws_led_gpio_map_t lgm[] = {
|
||||
{
|
||||
.name = "alert",
|
||||
.gpio = GPIO_NUM_25,
|
||||
.pwm_ops = &pwm_ops,
|
||||
.active_level = 1,
|
||||
},
|
||||
};
|
||||
|
||||
static const lws_led_gpio_controller_t lgc = {
|
||||
.led_ops = lws_led_gpio_ops,
|
||||
.gpio_ops = &lws_gpio_plat,
|
||||
.led_map = &lgm[0],
|
||||
.count_leds = LWS_ARRAY_SIZE(lgm)
|
||||
};
|
||||
|
||||
struct lws_led_state *lls;
|
||||
|
||||
lls = lgc.led_ops.create(&lgc.led_ops);
|
||||
if (!lls) {
|
||||
lwsl_err("%s: could not create led\n", __func__);
|
||||
goto spin;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
For GPIO control, the active level of the GPIO to light the LED may be set.
|
||||
|
||||
Each LED may bind to a pwm controller, in which case setting the intensity
|
||||
programs the pwm controller corresponding to the GPIO.
|
||||
|
||||
## Setting the intensity directly
|
||||
|
||||
```
|
||||
lgc.led_ops.intensity(&lgc.led_ops, "alert", 0);
|
||||
```
|
||||
|
||||
## Defining Sequencer
|
||||
|
||||
Some common sequencers are provided out of the box, you can also define your
|
||||
own arbitrary ones.
|
||||
|
||||
The main point is sequencers have a function that returns an intensity for each
|
||||
of 65536 phase steps in its cycle. For example, this is the linear function
|
||||
that is included
|
||||
|
||||
```
|
||||
lws_led_intensity_t
|
||||
lws_led_func_linear(lws_led_seq_phase_t n)
|
||||
{
|
||||
return (lws_led_intensity_t)n;
|
||||
}
|
||||
```
|
||||
|
||||
It simply returns an intensity between 0 - 65535 matching the phase angle of
|
||||
0 - 65535 that it was given, so it's a sawtooth ramp.
|
||||
|
||||
An interpolated sine function is also provided that returns an intensity
|
||||
between 0 - 65535 reflecting one cycle of sine wave for the phase angle of 0 -
|
||||
65535.
|
||||
|
||||
These functions are packaged into sequencer structures like this
|
||||
|
||||
```
|
||||
const lws_led_sequence_def_t lws_pwmseq_sine_endless_fast = {
|
||||
.func = lws_led_func_sine,
|
||||
.ledphase_offset = 0, /* already at 0 amp at 0 phase */
|
||||
.ledphase_total = LWS_SEQ_LEDPHASE_TOTAL_ENDLESS,
|
||||
.ms = 750
|
||||
};
|
||||
```
|
||||
|
||||
This "endless" sequencer cycles through the sine function at 750ms per cycle.
|
||||
Non-endless sequencers have a specific start and end in the phase space, eg
|
||||
|
||||
```
|
||||
const lws_led_sequence_def_t lws_pwmseq_sine_up = {
|
||||
.func = lws_led_func_sine,
|
||||
.ledphase_offset = 0, /* already at 0 amp at 0 phase */
|
||||
.ledphase_total = LWS_LED_FUNC_PHASE / 2, /* 180 degree ./^ */
|
||||
.ms = 300
|
||||
};
|
||||
```
|
||||
|
||||
... this one traverses 180 degrees of the sine wave starting from 0 and ending
|
||||
at full intensity, over 300ms.
|
||||
|
||||
A commonly-used, provided one is like this, as used in the next section
|
||||
|
||||
```
|
||||
const lws_led_sequence_def_t lws_pwmseq_linear_wipe = {
|
||||
.func = lws_led_func_linear,
|
||||
.ledphase_offset = 0,
|
||||
.ledphase_total = LWS_LED_FUNC_PHASE - 1,
|
||||
.ms = 300
|
||||
};
|
||||
```
|
||||
|
||||
## Setting the intensity using sequencer transitions
|
||||
|
||||
The main api for high level sequenced control is
|
||||
|
||||
```
|
||||
int
|
||||
lws_led_transition(struct lws_led_state *lcs, const char *name,
|
||||
const lws_led_sequence_def_t *next,
|
||||
const lws_led_sequence_def_t *trans);
|
||||
```
|
||||
|
||||
This fades from the current sequence to a new sequence, using `trans` sequencer
|
||||
intensity as the mix factor. `trans` is typically `lws_pwmseq_linear_wipe`,
|
||||
fading between the current and new linearly over 300ms. At the end of the
|
||||
`trans` sequence, the new sequence simply replaces the current one and the
|
||||
transition is completed.
|
||||
|
||||
Sequencers use a single 30Hz OS timer while any sequence is active.
|
||||
|
||||
exported sequencer symbol|description
|
||||
---|---
|
||||
lws_pwmseq_sine_endless_slow|continuous 100% sine, 1.5s cycle
|
||||
lws_pwmseq_sine_endless_fast|continuous 100% sine, 0.75s cycle
|
||||
lws_pwmseq_linear_wipe|single 0 - 100% ramp over 0.3s
|
||||
lws_pwmseq_sine_up|single 0 - 100% using sine curve over 0.3s
|
||||
lws_pwmseq_sine_down|single 100% - 0 using sine curve over 0.3s
|
||||
lws_pwmseq_static_on|100% static
|
||||
lws_pwmseq_static_half|50% static
|
||||
lws_pwmseq_static_off|0% static
|
120
Kinc/Sources/kinc/libs/drivers/led/led-gpio.c
Normal file
120
Kinc/Sources/kinc/libs/drivers/led/led-gpio.c
Normal file
@ -0,0 +1,120 @@
|
||||
/*
|
||||
* Generic GPIO led
|
||||
*
|
||||
* Copyright (C) 2019 - 2020 Andy Green <andy@warmcat.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
#include "private-lib-core.h"
|
||||
#include "drivers/led/private-lib-drivers-led.h"
|
||||
|
||||
#if defined(LWS_PLAT_TIMER_CB)
|
||||
static LWS_PLAT_TIMER_CB(lws_led_timer_cb, th)
|
||||
{
|
||||
lws_led_state_t *lcs = LWS_PLAT_TIMER_CB_GET_OPAQUE(th);
|
||||
|
||||
lws_seq_timer_handle(lcs);
|
||||
}
|
||||
#endif
|
||||
|
||||
struct lws_led_state *
|
||||
lws_led_gpio_create(const lws_led_ops_t *led_ops)
|
||||
{
|
||||
lws_led_gpio_controller_t *lgc = (lws_led_gpio_controller_t *)led_ops;
|
||||
/*
|
||||
* We allocate the main state object, and a 3 x seq dynamic footprint
|
||||
* for each led, since it may be sequencing the transition between two
|
||||
* other sequences.
|
||||
*/
|
||||
|
||||
lws_led_state_t *lcs = lws_zalloc(sizeof(lws_led_state_t) +
|
||||
(lgc->count_leds * sizeof(lws_led_state_chs_t)),
|
||||
__func__);
|
||||
int n;
|
||||
|
||||
if (!lcs)
|
||||
return NULL;
|
||||
|
||||
lcs->controller = lgc;
|
||||
|
||||
#if defined(LWS_PLAT_TIMER_CREATE)
|
||||
lcs->timer = LWS_PLAT_TIMER_CREATE("leds",
|
||||
LWS_LED_SEQUENCER_UPDATE_INTERVAL_MS, 1, lcs,
|
||||
(TimerCallbackFunction_t)lws_led_timer_cb);
|
||||
if (!lcs->timer)
|
||||
return NULL;
|
||||
#endif
|
||||
|
||||
for (n = 0; n < lgc->count_leds; n++) {
|
||||
const lws_led_gpio_map_t *map = &lgc->led_map[n];
|
||||
|
||||
if (map->pwm_ops) {
|
||||
lgc->gpio_ops->mode(map->gpio, LWSGGPIO_FL_READ);
|
||||
lgc->gpio_ops->set(map->gpio, 0);
|
||||
} else {
|
||||
lgc->gpio_ops->mode(map->gpio, LWSGGPIO_FL_WRITE);
|
||||
lgc->gpio_ops->set(map->gpio,
|
||||
!lgc->led_map[n].active_level);
|
||||
}
|
||||
}
|
||||
|
||||
return lcs;
|
||||
}
|
||||
|
||||
void
|
||||
lws_led_gpio_destroy(struct lws_led_state *lcs)
|
||||
{
|
||||
#if defined(LWS_PLAT_TIMER_DELETE)
|
||||
LWS_PLAT_TIMER_DELETE(lcs->timer);
|
||||
#endif
|
||||
lws_free(lcs);
|
||||
}
|
||||
|
||||
int
|
||||
lws_led_gpio_lookup(const struct lws_led_ops *lo, const char *name)
|
||||
{
|
||||
const lws_led_gpio_controller_t *lgc = (lws_led_gpio_controller_t *)lo;
|
||||
int n;
|
||||
|
||||
for (n = 0; n < lgc->count_leds; n++)
|
||||
if (!strcmp(name, lgc->led_map[n].name))
|
||||
return n;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void
|
||||
lws_led_gpio_intensity(const struct lws_led_ops *lo, const char *name,
|
||||
lws_led_intensity_t inten)
|
||||
{
|
||||
const lws_led_gpio_controller_t *lgc = (lws_led_gpio_controller_t *)lo;
|
||||
int idx = lws_led_gpio_lookup(lo, name);
|
||||
const lws_led_gpio_map_t *map;
|
||||
|
||||
if (idx < 0)
|
||||
return;
|
||||
|
||||
map = &lgc->led_map[idx];
|
||||
|
||||
if (map->pwm_ops)
|
||||
map->pwm_ops->intensity(map->pwm_ops, map->gpio, inten);
|
||||
else
|
||||
lgc->gpio_ops->set(map->gpio,
|
||||
(!!map->active_level) ^ !(inten & 0x8000));
|
||||
}
|
200
Kinc/Sources/kinc/libs/drivers/led/led-seq.c
Normal file
200
Kinc/Sources/kinc/libs/drivers/led/led-seq.c
Normal file
@ -0,0 +1,200 @@
|
||||
/*
|
||||
* Generic GPIO led
|
||||
*
|
||||
* Copyright (C) 2019 - 2020 Andy Green <andy@warmcat.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
#include "private-lib-core.h"
|
||||
|
||||
#include "drivers/led/private-lib-drivers-led.h"
|
||||
|
||||
/*
|
||||
* 64 entry interpolated CIE correction
|
||||
* https://en.wikipedia.org/wiki/Lightness
|
||||
*/
|
||||
|
||||
uint16_t cie[] = {
|
||||
0, 113, 227, 340, 454, 568, 688, 824, 976, 1146,
|
||||
1335, 1543, 1772, 2023, 2296, 2592, 2914, 3260, 3633, 4034,
|
||||
4463, 4921, 5409, 5929, 6482, 7067, 7687, 8341, 9032, 9761,
|
||||
10527, 11332, 12178, 13064, 13993, 14964, 15980, 17040, 18146, 19299,
|
||||
20500, 21750, 23049, 24400, 25802, 27256, 28765, 30328, 31946, 33622,
|
||||
35354, 37146, 38996, 40908, 42881, 44916, 47014, 49177, 51406, 53700,
|
||||
56062, 58492, 60992, 63561,
|
||||
65535 /* for interpolation */
|
||||
};
|
||||
|
||||
/*
|
||||
* This is the default intensity correction function, it can be overridden
|
||||
* per-led to eg, normalize intensity of different leds
|
||||
*/
|
||||
|
||||
static lws_led_intensity_t
|
||||
cie_antilog(lws_led_intensity_t lin)
|
||||
{
|
||||
return (cie[lin >> 10] * (0x3ff - (lin & 0x3ff)) +
|
||||
cie[(lin >> 10) + 1] * (lin & 0x3ff)) / 0x3ff;
|
||||
}
|
||||
|
||||
static void
|
||||
lws_seq_advance(lws_led_state_t *lcs, lws_led_state_ch_t *ch)
|
||||
{
|
||||
if (!ch->seq)
|
||||
return;
|
||||
|
||||
if (ch->phase_budget != LWS_SEQ_LEDPHASE_TOTAL_ENDLESS &&
|
||||
(ch->phase_budget < ch->step || !ch->phase_budget)) {
|
||||
|
||||
/* we are done */
|
||||
|
||||
ch->seq = NULL;
|
||||
if (!(--lcs->timer_refcount)) {
|
||||
#if defined(LWS_PLAT_TIMER_STOP)
|
||||
LWS_PLAT_TIMER_STOP(lcs->timer);
|
||||
#endif
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
ch->ph += ch->step;
|
||||
if (ch->phase_budget != LWS_SEQ_LEDPHASE_TOTAL_ENDLESS)
|
||||
ch->phase_budget -= ch->step;
|
||||
}
|
||||
|
||||
static lws_led_intensity_t
|
||||
lws_seq_sample(const lws_led_gpio_map_t *map, lws_led_state_chs_t *chs)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
if (chs->seqs[LLSI_CURR].seq)
|
||||
chs->seqs[LLSI_CURR].last = chs->seqs[LLSI_CURR].seq->
|
||||
func(chs->seqs[LLSI_CURR].ph);
|
||||
|
||||
if (chs->seqs[LLSI_TRANS].seq) {
|
||||
/*
|
||||
* If a transition is ongoing, we need to use the transition
|
||||
* intensity as the mixing factor between the still-live current
|
||||
* and newly-live next sequences
|
||||
*/
|
||||
chs->seqs[LLSI_TRANS].last = chs->seqs[LLSI_TRANS].seq->
|
||||
func(chs->seqs[LLSI_TRANS].ph);
|
||||
|
||||
if (chs->seqs[LLSI_NEXT].seq)
|
||||
chs->seqs[LLSI_NEXT].last = chs->seqs[LLSI_NEXT].seq->
|
||||
func(chs->seqs[LLSI_NEXT].ph);
|
||||
|
||||
i = (lws_led_intensity_t)(((
|
||||
(unsigned int)chs->seqs[LLSI_CURR].last *
|
||||
(65535 - chs->seqs[LLSI_TRANS].last) >> 16) +
|
||||
(((unsigned int)chs->seqs[LLSI_NEXT].last *
|
||||
(unsigned int)chs->seqs[LLSI_TRANS].last) >> 16)));
|
||||
} else
|
||||
i = chs->seqs[LLSI_CURR].last;
|
||||
|
||||
return map->intensity_correction ? map->intensity_correction(i) :
|
||||
cie_antilog((lws_led_intensity_t)i);
|
||||
}
|
||||
|
||||
void
|
||||
lws_seq_timer_handle(lws_led_state_t *lcs)
|
||||
{
|
||||
lws_led_gpio_controller_t *lgc = lcs->controller;
|
||||
lws_led_state_chs_t *chs = (lws_led_state_chs_t *)&lcs[1];
|
||||
const lws_led_gpio_map_t *map = &lgc->led_map[0];
|
||||
unsigned int n;
|
||||
|
||||
for (n = 0; n < lgc->count_leds; n++) {
|
||||
|
||||
lgc->led_ops.intensity(&lgc->led_ops, map->name,
|
||||
lws_seq_sample(map, chs));
|
||||
|
||||
lws_seq_advance(lcs, &chs->seqs[LLSI_CURR]);
|
||||
|
||||
if (chs->seqs[LLSI_TRANS].seq) {
|
||||
lws_seq_advance(lcs, &chs->seqs[LLSI_NEXT]);
|
||||
lws_seq_advance(lcs, &chs->seqs[LLSI_TRANS]);
|
||||
|
||||
/*
|
||||
* When we finished the transition, we can make the
|
||||
* "next" sequence the current sequence and no need for
|
||||
* a "next" or a transition any more.
|
||||
*/
|
||||
|
||||
if (!chs->seqs[LLSI_TRANS].seq) {
|
||||
chs->seqs[LLSI_CURR] = chs->seqs[LLSI_NEXT];
|
||||
chs->seqs[LLSI_NEXT].seq = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
map++;
|
||||
chs++;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
lws_led_set_chs_seq(struct lws_led_state *lcs, lws_led_state_ch_t *dest,
|
||||
const lws_led_sequence_def_t *def)
|
||||
{
|
||||
int steps;
|
||||
|
||||
dest->seq = def;
|
||||
dest->ph = def->ledphase_offset;
|
||||
dest->phase_budget = def->ledphase_total;
|
||||
|
||||
/*
|
||||
* We need to compute the incremental phase angle step to cover the
|
||||
* total number of phases in the indicated ms, incrementing at the
|
||||
* timer rate of LWS_LED_SEQUENCER_UPDATE_RATE_HZ. Eg,
|
||||
*
|
||||
* 65536 phase steps (one cycle) in 2000ms at 30Hz timer rate means we
|
||||
* will update 2000ms / 33ms = 60 times, so we must step at at
|
||||
* 65536 / 60 = 1092 phase angle resolution
|
||||
*/
|
||||
|
||||
steps = def->ms / LWS_LED_SEQUENCER_UPDATE_INTERVAL_MS;
|
||||
dest->step = (def->ledphase_total != LWS_SEQ_LEDPHASE_TOTAL_ENDLESS ?
|
||||
def->ledphase_total : LWS_LED_FUNC_PHASE) / (steps ? steps : 1);
|
||||
|
||||
if (!lcs->timer_refcount++) {
|
||||
#if defined(LWS_PLAT_TIMER_START)
|
||||
LWS_PLAT_TIMER_START(lcs->timer);
|
||||
#endif
|
||||
}
|
||||
|
||||
return steps;
|
||||
}
|
||||
|
||||
int
|
||||
lws_led_transition(struct lws_led_state *lcs, const char *name,
|
||||
const lws_led_sequence_def_t *next,
|
||||
const lws_led_sequence_def_t *trans)
|
||||
{
|
||||
lws_led_state_chs_t *chs = (lws_led_state_chs_t *)&lcs[1];
|
||||
int index = lws_led_gpio_lookup(&lcs->controller->led_ops, name);
|
||||
|
||||
if (index < 0)
|
||||
return 1;
|
||||
|
||||
lws_led_set_chs_seq(lcs, &chs[index].seqs[LLSI_TRANS], trans);
|
||||
lws_led_set_chs_seq(lcs, &chs[index].seqs[LLSI_NEXT], next);
|
||||
|
||||
return 0;
|
||||
}
|
39
Kinc/Sources/kinc/libs/drivers/led/private-lib-drivers-led.h
Normal file
39
Kinc/Sources/kinc/libs/drivers/led/private-lib-drivers-led.h
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Generic GPIO led
|
||||
*
|
||||
* Copyright (C) 2019 - 2020 Andy Green <andy@warmcat.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
typedef struct lws_led_state
|
||||
{
|
||||
#if defined(LWS_PLAT_TIMER_TYPE)
|
||||
LWS_PLAT_TIMER_TYPE timer;
|
||||
#endif
|
||||
|
||||
lws_led_gpio_controller_t *controller;
|
||||
int timer_refcount;
|
||||
} lws_led_state_t;
|
||||
|
||||
void
|
||||
lws_seq_timer_handle(lws_led_state_t *lcs);
|
||||
|
||||
int
|
||||
lws_led_gpio_lookup(const struct lws_led_ops *lo, const char *name);
|
Reference in New Issue
Block a user