125 lines
3.2 KiB
Markdown
125 lines
3.2 KiB
Markdown
|
LED state describes by struct:
|
||
|
|
||
|
```C
|
||
|
typedef struct {
|
||
|
uint8_t red;
|
||
|
uint8_t green;
|
||
|
uint8_t blue;
|
||
|
} Rgb;
|
||
|
```
|
||
|
|
||
|
LED API provided by struct:
|
||
|
|
||
|
```C
|
||
|
typedef struct {
|
||
|
LayeredReducer* source; /// every app add its layer to set value, LayeredReducer<Rgb*>
|
||
|
Subscriber* updates; /// LED value changes Supscriber<Rgb*>
|
||
|
ValueMutex* state; /// LED state, ValueMutex<Rgb*>
|
||
|
} LedApi;
|
||
|
```
|
||
|
|
||
|
You can get API instance by calling `open_led`:
|
||
|
|
||
|
```C
|
||
|
/// Add new layer to LED:
|
||
|
inline LedApi* open_led(const char* name) {
|
||
|
return (LedApi*)furi_open(name);
|
||
|
}
|
||
|
```
|
||
|
|
||
|
Default system led is `/dev/led`.
|
||
|
|
||
|
Then add new layer to control LED by calling `add_led_layer`:
|
||
|
|
||
|
```C
|
||
|
inline ValueManager* add_led_layer(Rgb* layer, uint8_t priority) {
|
||
|
ValueManager* manager = register_valuemanager((void*)layer);
|
||
|
if(manager == NULL) return NULL;
|
||
|
|
||
|
if(!add_layered_reducer(manager, priority, layer_compose_default)) {
|
||
|
unregister_valuemanager(manager);
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
return manager;
|
||
|
}
|
||
|
```
|
||
|
|
||
|
For change led you can get display instance pointer by calling `take_led`, do something and commit your changes by calling `commit_led`. Or you can call `write_led`:
|
||
|
|
||
|
```C
|
||
|
/// return pointer in case off success, NULL otherwise
|
||
|
inline Rgb* take_led(ValueManager* led, uint32_t timeout) {
|
||
|
return (Rgb*)take_mutex(led->value, timeout);
|
||
|
}
|
||
|
|
||
|
inline void commit_led(ValueManager* led, Rgb* value) {
|
||
|
commit_valuemanager(led, value);
|
||
|
}
|
||
|
|
||
|
/// return true if success, false otherwise
|
||
|
inline bool write_led(ValueManager* led, Rgb* value, uint32_t timeout) {
|
||
|
return write_valuemanager(state, (void*)value, sizeof(Rgb), timeout);
|
||
|
}
|
||
|
```
|
||
|
|
||
|
To read current led state you should use `read_led` function:
|
||
|
|
||
|
```C
|
||
|
/// return true if success, false otherwise
|
||
|
inline bool read_led(ValueManager* led, Rgb* value, uint32_t timeout) {
|
||
|
return read_mutex(led->value, (void*)value, sizeof(Rgb), timeout);
|
||
|
}
|
||
|
```
|
||
|
|
||
|
Also you can subscribe to led state changes:
|
||
|
|
||
|
Use `subscribe_led_changes` to register your callback:
|
||
|
|
||
|
```C
|
||
|
/// return true if success, false otherwise
|
||
|
inline bool subscribe_led_changes(Subscriber* updates, void(*cb)(Rgb*, void*), void* ctx) {
|
||
|
return subscribe_pubsub(events, void(*)(void*, void*)(cb), ctx);
|
||
|
}
|
||
|
```
|
||
|
|
||
|
## Usage example
|
||
|
|
||
|
```C
|
||
|
|
||
|
void handle_led_state(Rgb* rgb, void* _ctx) {
|
||
|
printf("led: #%02X%02X%02X\n", rgb->red, rgb->green, rgb->blue);
|
||
|
}
|
||
|
|
||
|
void led_example(void* p) {
|
||
|
LedApi* led_api = open_display("/dev/led");
|
||
|
if(led_api == NULL) return; // led not available, critical error
|
||
|
|
||
|
// subscribe to led state updates
|
||
|
subscribe_led_changes(led_api->updates, handle_led_state, NULL);
|
||
|
|
||
|
Rgb current_state;
|
||
|
if(read_led(led_api->state, ¤t_state, OsWaitForever)) {
|
||
|
printf(
|
||
|
"initial led: #%02X%02X%02X\n",
|
||
|
current_state->red,
|
||
|
current_state->green,
|
||
|
current_state->blue
|
||
|
);
|
||
|
}
|
||
|
|
||
|
// add layer to control led
|
||
|
ValueManager* led_manager = add_led_layer(¤t_state, UI_LAYER_APP);
|
||
|
|
||
|
// write only blue by getting pointer
|
||
|
Rgb* rgb = take_led(led_manager, OsWaitForever);
|
||
|
if(rgb != NULL) {
|
||
|
rgb->blue = 0;
|
||
|
}
|
||
|
commit_led(led_manager, rgb);
|
||
|
|
||
|
// write RGB value
|
||
|
write_led(led_manager, &(Rgb{.red = 0xFA, green = 0xCE, .blue = 0x8D}), OsWaitForever);
|
||
|
}
|
||
|
```
|