214 lines
7.0 KiB
C
214 lines
7.0 KiB
C
#include <core/common_defines.h>
|
|
#include "../../js_modules.h"
|
|
#include <furi_hal.h>
|
|
|
|
#include "rgbleds.h"
|
|
|
|
typedef struct {
|
|
RgbLeds* leds;
|
|
} JsRgbledsInst;
|
|
|
|
typedef struct {
|
|
const GpioPin* pin;
|
|
const char* name;
|
|
} GpioPinCtx;
|
|
|
|
static const GpioPinCtx js_gpio_pins[] = {
|
|
{.pin = &gpio_ext_pa7, .name = "PA7"}, // 2
|
|
{.pin = &gpio_ext_pa6, .name = "PA6"}, // 3
|
|
{.pin = &gpio_ext_pa4, .name = "PA4"}, // 4
|
|
{.pin = &gpio_ext_pb3, .name = "PB3"}, // 5
|
|
{.pin = &gpio_ext_pb2, .name = "PB2"}, // 6
|
|
{.pin = &gpio_ext_pc3, .name = "PC3"}, // 7
|
|
{.pin = &gpio_swclk, .name = "PA14"}, // 10
|
|
{.pin = &gpio_swdio, .name = "PA13"}, // 12
|
|
{.pin = &gpio_usart_tx, .name = "PB6"}, // 13
|
|
{.pin = &gpio_usart_rx, .name = "PB7"}, // 14
|
|
{.pin = &gpio_ext_pc1, .name = "PC1"}, // 15
|
|
{.pin = &gpio_ext_pc0, .name = "PC0"}, // 16
|
|
{.pin = &gpio_ibutton, .name = "PB14"}, // 17
|
|
};
|
|
|
|
static const GpioPin* get_gpio_pin(const char* name) {
|
|
for(size_t i = 0; i < COUNT_OF(js_gpio_pins); i++) {
|
|
if(strcmp(js_gpio_pins[i].name, name) == 0) {
|
|
return js_gpio_pins[i].pin;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
static void js_rgbleds_setup(struct mjs* mjs) {
|
|
mjs_val_t obj_inst = mjs_get(mjs, mjs_get_this(mjs), INST_PROP_NAME, ~0);
|
|
JsRgbledsInst* rgbleds = mjs_get_ptr(mjs, obj_inst);
|
|
furi_assert(rgbleds);
|
|
|
|
if(mjs_nargs(mjs) != 1 || !mjs_is_object(mjs_arg(mjs, 0))) {
|
|
mjs_prepend_errorf(mjs, MJS_BAD_ARGS_ERROR, "");
|
|
mjs_return(mjs, MJS_UNDEFINED);
|
|
return;
|
|
}
|
|
|
|
mjs_val_t pin_obj = mjs_get(mjs, mjs_arg(mjs, 0), "pin", ~0);
|
|
mjs_val_t count_obj = mjs_get(mjs, mjs_arg(mjs, 0), "count", ~0);
|
|
mjs_val_t spec_obj = mjs_get(mjs, mjs_arg(mjs, 0), "spec", ~0);
|
|
|
|
if(!mjs_is_string(pin_obj)) {
|
|
mjs_prepend_errorf(mjs, MJS_BAD_ARGS_ERROR, "pin must be a string");
|
|
mjs_return(mjs, MJS_UNDEFINED);
|
|
return;
|
|
}
|
|
|
|
if(!mjs_is_number(count_obj)) {
|
|
mjs_prepend_errorf(mjs, MJS_BAD_ARGS_ERROR, "count must be a number");
|
|
mjs_return(mjs, MJS_UNDEFINED);
|
|
return;
|
|
}
|
|
|
|
if(!mjs_is_string(spec_obj)) {
|
|
mjs_prepend_errorf(mjs, MJS_BAD_ARGS_ERROR, "spec must be a string");
|
|
mjs_return(mjs, MJS_UNDEFINED);
|
|
return;
|
|
}
|
|
|
|
const GpioPin* pin = get_gpio_pin(mjs_get_string(mjs, &pin_obj, NULL));
|
|
if(!pin) {
|
|
mjs_prepend_errorf(mjs, MJS_BAD_ARGS_ERROR, "invalid pin");
|
|
mjs_return(mjs, MJS_UNDEFINED);
|
|
return;
|
|
}
|
|
|
|
if(rgbleds->leds) {
|
|
rgbleds_free(rgbleds->leds);
|
|
}
|
|
|
|
uint16_t count = mjs_get_int(mjs, count_obj);
|
|
rgbleds->leds = rgbleds_alloc(count, pin);
|
|
}
|
|
|
|
static void js_rgbleds_set(struct mjs* mjs) {
|
|
mjs_val_t obj_inst = mjs_get(mjs, mjs_get_this(mjs), INST_PROP_NAME, ~0);
|
|
JsRgbledsInst* rgbleds = mjs_get_ptr(mjs, obj_inst);
|
|
furi_assert(rgbleds);
|
|
|
|
if(!rgbleds->leds) {
|
|
mjs_prepend_errorf(mjs, MJS_INTERNAL_ERROR, "LEDs not setup");
|
|
mjs_return(mjs, MJS_UNDEFINED);
|
|
return;
|
|
}
|
|
|
|
uint32_t color;
|
|
if(mjs_nargs(mjs) == 2) {
|
|
if(mjs_is_number(mjs_arg(mjs, 0)) && mjs_is_number(mjs_arg(mjs, 1))) {
|
|
color = mjs_get_int(mjs, mjs_arg(mjs, 1));
|
|
} else if(mjs_is_number(mjs_arg(mjs, 0)) && mjs_is_object(mjs_arg(mjs, 1))) {
|
|
mjs_val_t red_obj = mjs_get(mjs, mjs_arg(mjs, 1), "red", ~0);
|
|
mjs_val_t green_obj = mjs_get(mjs, mjs_arg(mjs, 1), "green", ~0);
|
|
mjs_val_t blue_obj = mjs_get(mjs, mjs_arg(mjs, 1), "blue", ~0);
|
|
if(!mjs_is_number(red_obj) || !mjs_is_number(green_obj) || !mjs_is_number(blue_obj)) {
|
|
mjs_prepend_errorf(mjs, MJS_BAD_ARGS_ERROR, "");
|
|
mjs_return(mjs, MJS_UNDEFINED);
|
|
return;
|
|
}
|
|
color = (mjs_get_int(mjs, red_obj) << 16) | (mjs_get_int(mjs, green_obj) << 8) |
|
|
mjs_get_int(mjs, blue_obj);
|
|
} else {
|
|
mjs_prepend_errorf(mjs, MJS_BAD_ARGS_ERROR, "");
|
|
mjs_return(mjs, MJS_UNDEFINED);
|
|
return;
|
|
}
|
|
} else if(mjs_nargs(mjs) == 4) {
|
|
if(!mjs_is_number(mjs_arg(mjs, 0)) || !mjs_is_number(mjs_arg(mjs, 1)) ||
|
|
!mjs_is_number(mjs_arg(mjs, 2)) || !mjs_is_number(mjs_arg(mjs, 3))) {
|
|
mjs_prepend_errorf(mjs, MJS_BAD_ARGS_ERROR, "");
|
|
mjs_return(mjs, MJS_UNDEFINED);
|
|
return;
|
|
}
|
|
|
|
color = (mjs_get_int(mjs, mjs_arg(mjs, 1)) << 16) |
|
|
(mjs_get_int(mjs, mjs_arg(mjs, 2)) << 8) | mjs_get_int(mjs, mjs_arg(mjs, 3));
|
|
} else {
|
|
mjs_prepend_errorf(mjs, MJS_BAD_ARGS_ERROR, "");
|
|
mjs_return(mjs, MJS_UNDEFINED);
|
|
return;
|
|
}
|
|
|
|
uint16_t index = mjs_get_int(mjs, mjs_arg(mjs, 0));
|
|
|
|
uint16_t original_color = rgbleds_get(rgbleds->leds, index);
|
|
rgbleds_set(rgbleds->leds, index, color);
|
|
mjs_return(mjs, mjs_mk_number(mjs, original_color));
|
|
}
|
|
|
|
static void js_rgbleds_get(struct mjs* mjs) {
|
|
mjs_val_t obj_inst = mjs_get(mjs, mjs_get_this(mjs), INST_PROP_NAME, ~0);
|
|
JsRgbledsInst* rgbleds = mjs_get_ptr(mjs, obj_inst);
|
|
furi_assert(rgbleds);
|
|
|
|
if(!rgbleds->leds) {
|
|
mjs_prepend_errorf(mjs, MJS_INTERNAL_ERROR, "LEDs not setup");
|
|
mjs_return(mjs, MJS_UNDEFINED);
|
|
return;
|
|
}
|
|
|
|
if(mjs_nargs(mjs) != 1 || !mjs_is_number(mjs_arg(mjs, 0))) {
|
|
mjs_prepend_errorf(mjs, MJS_BAD_ARGS_ERROR, "");
|
|
mjs_return(mjs, MJS_UNDEFINED);
|
|
return;
|
|
}
|
|
|
|
uint16_t index = mjs_get_int(mjs, mjs_arg(mjs, 0));
|
|
mjs_return(mjs, mjs_mk_number(mjs, rgbleds_get(rgbleds->leds, index)));
|
|
}
|
|
|
|
static void js_rgbleds_update(struct mjs* mjs) {
|
|
mjs_val_t obj_inst = mjs_get(mjs, mjs_get_this(mjs), INST_PROP_NAME, ~0);
|
|
JsRgbledsInst* rgbleds = mjs_get_ptr(mjs, obj_inst);
|
|
furi_assert(rgbleds);
|
|
|
|
if(!rgbleds->leds) {
|
|
mjs_prepend_errorf(mjs, MJS_INTERNAL_ERROR, "LEDs not setup");
|
|
mjs_return(mjs, MJS_UNDEFINED);
|
|
return;
|
|
}
|
|
|
|
rgbleds_update(rgbleds->leds);
|
|
}
|
|
|
|
static void* js_rgbleds_create(struct mjs* mjs, mjs_val_t* object) {
|
|
JsRgbledsInst* rgbleds = malloc(sizeof(JsRgbledsInst));
|
|
rgbleds->leds = NULL;
|
|
mjs_val_t rgbleds_obj = mjs_mk_object(mjs);
|
|
mjs_set(mjs, rgbleds_obj, INST_PROP_NAME, ~0, mjs_mk_foreign(mjs, rgbleds));
|
|
mjs_set(mjs, rgbleds_obj, "setup", ~0, MJS_MK_FN(js_rgbleds_setup));
|
|
mjs_set(mjs, rgbleds_obj, "set", ~0, MJS_MK_FN(js_rgbleds_set));
|
|
mjs_set(mjs, rgbleds_obj, "get", ~0, MJS_MK_FN(js_rgbleds_get));
|
|
mjs_set(mjs, rgbleds_obj, "update", ~0, MJS_MK_FN(js_rgbleds_update));
|
|
*object = rgbleds_obj;
|
|
return rgbleds;
|
|
}
|
|
|
|
static void js_rgbleds_destroy(void* inst) {
|
|
JsRgbledsInst* rgbleds = inst;
|
|
if(rgbleds->leds) {
|
|
rgbleds_free(rgbleds->leds);
|
|
}
|
|
free(rgbleds);
|
|
}
|
|
|
|
static const JsModuleDescriptor js_rgbleds_desc = {
|
|
"rgbleds",
|
|
js_rgbleds_create,
|
|
js_rgbleds_destroy,
|
|
};
|
|
|
|
static const FlipperAppPluginDescriptor plugin_descriptor = {
|
|
.appid = PLUGIN_APP_ID,
|
|
.ep_api_version = PLUGIN_API_VERSION,
|
|
.entry_point = &js_rgbleds_desc,
|
|
};
|
|
|
|
const FlipperAppPluginDescriptor* js_rgbleds_ep(void) {
|
|
return &plugin_descriptor;
|
|
}
|