-
-
Notifications
You must be signed in to change notification settings - Fork 213
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
3 changed files
with
308 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
let gpio = require("gpio"); | ||
|
||
// initialize pins | ||
gpio.init("PC3", "outputPushPull", "up"); // pin, mode, pull | ||
print("PC3 is initialized as outputPushPull with pull-up"); | ||
|
||
gpio.init("PC1", "input", "down"); // pin, mode, pull | ||
print("PC1 is initialized as input with pull-down"); | ||
|
||
// let led on PC3 blink | ||
gpio.write("PC3", true); // high | ||
delay(1000); | ||
gpio.write("PC3", false); // low | ||
delay(1000); | ||
gpio.write("PC3", true); // high | ||
delay(1000); | ||
gpio.write("PC3", false); // low | ||
|
||
// read value from PC1 and write it to PC3 | ||
while (true) { | ||
let value = gpio.read("PC1"); | ||
gpio.write("PC3", value); | ||
|
||
value ? print("PC1 is high") : print("PC1 is low"); | ||
|
||
delay(100); | ||
} | ||
|
||
|
||
// possible pins https://docs.flipper.net/gpio-and-modules#miFsS | ||
// "PA7" aka 2 | ||
// "PA6" aka 3 | ||
// "PA4" aka 4 | ||
// "PB3" aka 5 | ||
// "PB2" aka 6 | ||
// "PC3" aka 7 | ||
// "PA14" aka 10 | ||
// "PA13" aka 12 | ||
// "PB6" aka 13 | ||
// "PB7" aka 14 | ||
// "PC1" aka 15 | ||
// "PC0" aka 16 | ||
// "PB14" aka 17 | ||
|
||
// possible modes | ||
// "input" | ||
// "outputPushPull" | ||
// "outputOpenDrain" | ||
// "altFunctionPushPull" | ||
// "altFunctionOpenDrain" | ||
// "analog" | ||
// "interruptRise" | ||
// "interruptFall" | ||
// "interruptRiseFall" | ||
// "eventRise" | ||
// "eventFall" | ||
// "eventRiseFall" | ||
|
||
// possible pull | ||
// "no" | ||
// "up" | ||
// "down" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,237 @@ | ||
#include "../js_modules.h" | ||
#include <furi_hal_gpio.h> | ||
#include <furi_hal_resources.h> | ||
|
||
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 | ||
}; | ||
|
||
GpioPull js_gpio_get_gpio_pull(const char* pull) { | ||
if(strcmp(pull, "no") == 0) { | ||
return GpioPullNo; | ||
} else if(strcmp(pull, "up") == 0) { | ||
return GpioPullUp; | ||
} else if(strcmp(pull, "down") == 0) { | ||
return GpioPullDown; | ||
} else { | ||
return GpioPullNo; | ||
} | ||
} | ||
|
||
GpioMode js_gpio_get_gpio_mode(const char* mode) { | ||
if(strcmp(mode, "input") == 0) { | ||
return GpioModeInput; | ||
} else if(strcmp(mode, "outputPushPull") == 0) { | ||
return GpioModeOutputPushPull; | ||
} else if(strcmp(mode, "outputOpenDrain") == 0) { | ||
return GpioModeOutputOpenDrain; | ||
} else if(strcmp(mode, "altFunctionPushPull") == 0) { | ||
return GpioModeAltFunctionPushPull; | ||
} else if(strcmp(mode, "altFunctionOpenDrain") == 0) { | ||
return GpioModeAltFunctionOpenDrain; | ||
} else if(strcmp(mode, "analog") == 0) { | ||
return GpioModeAnalog; | ||
} else if(strcmp(mode, "interruptRise") == 0) { | ||
return GpioModeInterruptRise; | ||
} else if(strcmp(mode, "interruptFall") == 0) { | ||
return GpioModeInterruptFall; | ||
} else if(strcmp(mode, "interruptRiseFall") == 0) { | ||
return GpioModeInterruptRiseFall; | ||
} else if(strcmp(mode, "eventRise") == 0) { | ||
return GpioModeEventRise; | ||
} else if(strcmp(mode, "eventFall") == 0) { | ||
return GpioModeEventFall; | ||
} else if(strcmp(mode, "eventRiseFall") == 0) { | ||
return GpioModeEventRiseFall; | ||
} else { | ||
return GpioModeInput; | ||
} | ||
} | ||
|
||
const GpioPin* js_gpio_get_gpio_pin(const char* name) { | ||
for(int i = 0; i < 12; i++) { | ||
if(strcmp(js_gpio_pins[i].name, name) == 0) { | ||
return js_gpio_pins[i].pin; | ||
} | ||
} | ||
return NULL; | ||
} | ||
|
||
static void js_gpio_init(struct mjs* mjs) { | ||
mjs_val_t pin_arg = mjs_arg(mjs, 0); | ||
mjs_val_t mode_arg = mjs_arg(mjs, 1); | ||
mjs_val_t pull_arg = mjs_arg(mjs, 2); | ||
|
||
if(!mjs_is_string(pin_arg)) { | ||
mjs_prepend_errorf(mjs, MJS_BAD_ARGS_ERROR, "Argument must be a string"); | ||
mjs_return(mjs, MJS_UNDEFINED); | ||
return; | ||
} | ||
|
||
const char* pin_name = mjs_get_string(mjs, &pin_arg, NULL); | ||
if(!pin_name) { | ||
mjs_prepend_errorf(mjs, MJS_BAD_ARGS_ERROR, "Failed to get pin name"); | ||
mjs_return(mjs, MJS_UNDEFINED); | ||
return; | ||
} | ||
|
||
if(!mjs_is_string(mode_arg)) { | ||
mjs_prepend_errorf(mjs, MJS_BAD_ARGS_ERROR, "Argument must be a string"); | ||
mjs_return(mjs, MJS_UNDEFINED); | ||
return; | ||
} | ||
|
||
const char* mode_name = mjs_get_string(mjs, &mode_arg, NULL); | ||
if(!mode_name) { | ||
mjs_prepend_errorf(mjs, MJS_BAD_ARGS_ERROR, "Failed to get mode name"); | ||
mjs_return(mjs, MJS_UNDEFINED); | ||
return; | ||
} | ||
|
||
if(!mjs_is_string(pull_arg)) { | ||
mjs_prepend_errorf(mjs, MJS_BAD_ARGS_ERROR, "Argument must be a string"); | ||
mjs_return(mjs, MJS_UNDEFINED); | ||
return; | ||
} | ||
|
||
const char* pull_name = mjs_get_string(mjs, &pull_arg, NULL); | ||
if(!pull_name) { | ||
mjs_prepend_errorf(mjs, MJS_BAD_ARGS_ERROR, "Failed to get pull name"); | ||
mjs_return(mjs, MJS_UNDEFINED); | ||
return; | ||
} | ||
|
||
const GpioPin* gpio_pin = js_gpio_get_gpio_pin(pin_name); | ||
const GpioMode gpio_mode = js_gpio_get_gpio_mode(mode_name); | ||
const GpioPull gpio_pull = js_gpio_get_gpio_pull(pull_name); | ||
|
||
if(gpio_pin == NULL) { | ||
mjs_prepend_errorf(mjs, MJS_BAD_ARGS_ERROR, "Invalid pin name"); | ||
mjs_return(mjs, MJS_UNDEFINED); | ||
return; | ||
} | ||
|
||
furi_hal_gpio_init(gpio_pin, gpio_mode, gpio_pull, GpioSpeedVeryHigh); | ||
|
||
mjs_return(mjs, MJS_UNDEFINED); | ||
} | ||
|
||
static void js_gpio_write(struct mjs* mjs) { | ||
mjs_val_t pin_arg = mjs_arg(mjs, 0); | ||
mjs_val_t value_arg = mjs_arg(mjs, 1); | ||
|
||
if(!mjs_is_string(pin_arg)) { | ||
mjs_prepend_errorf(mjs, MJS_BAD_ARGS_ERROR, "Argument must be a string"); | ||
mjs_return(mjs, MJS_UNDEFINED); | ||
return; | ||
} | ||
|
||
const char* pin_name = mjs_get_string(mjs, &pin_arg, NULL); | ||
if(!pin_name) { | ||
mjs_prepend_errorf(mjs, MJS_BAD_ARGS_ERROR, "Failed to get pin name"); | ||
mjs_return(mjs, MJS_UNDEFINED); | ||
return; | ||
} | ||
|
||
if(!mjs_is_boolean(value_arg)) { | ||
mjs_prepend_errorf(mjs, MJS_BAD_ARGS_ERROR, "Argument must be a boolean"); | ||
mjs_return(mjs, MJS_UNDEFINED); | ||
return; | ||
} | ||
|
||
bool value = mjs_get_bool(mjs, value_arg); | ||
|
||
const GpioPin* gpio_pin = js_gpio_get_gpio_pin(pin_name); | ||
|
||
if(gpio_pin == NULL) { | ||
mjs_prepend_errorf(mjs, MJS_BAD_ARGS_ERROR, "Invalid pin name"); | ||
mjs_return(mjs, MJS_UNDEFINED); | ||
return; | ||
} | ||
|
||
furi_hal_gpio_write(gpio_pin, value); | ||
|
||
mjs_return(mjs, MJS_UNDEFINED); | ||
} | ||
|
||
static void js_gpio_read(struct mjs* mjs) { | ||
mjs_val_t pin_arg = mjs_arg(mjs, 0); | ||
|
||
if(!mjs_is_string(pin_arg)) { | ||
mjs_prepend_errorf(mjs, MJS_BAD_ARGS_ERROR, "Argument must be a string"); | ||
mjs_return(mjs, MJS_UNDEFINED); | ||
return; | ||
} | ||
|
||
const char* pin_name = mjs_get_string(mjs, &pin_arg, NULL); | ||
if(!pin_name) { | ||
mjs_prepend_errorf(mjs, MJS_BAD_ARGS_ERROR, "Failed to get pin name"); | ||
mjs_return(mjs, MJS_UNDEFINED); | ||
return; | ||
} | ||
|
||
const GpioPin* gpio_pin = js_gpio_get_gpio_pin(pin_name); | ||
|
||
if(gpio_pin == NULL) { | ||
mjs_prepend_errorf(mjs, MJS_BAD_ARGS_ERROR, "Invalid pin name"); | ||
mjs_return(mjs, MJS_UNDEFINED); | ||
return; | ||
} | ||
|
||
bool value = furi_hal_gpio_read(gpio_pin); | ||
|
||
mjs_return(mjs, mjs_mk_boolean(mjs, value)); | ||
} | ||
|
||
static void* js_gpio_create(struct mjs* mjs, mjs_val_t* object) { | ||
mjs_val_t gpio_obj = mjs_mk_object(mjs); | ||
mjs_set(mjs, gpio_obj, "init", ~0, MJS_MK_FN(js_gpio_init)); | ||
mjs_set(mjs, gpio_obj, "write", ~0, MJS_MK_FN(js_gpio_write)); | ||
mjs_set(mjs, gpio_obj, "read", ~0, MJS_MK_FN(js_gpio_read)); | ||
*object = gpio_obj; | ||
|
||
return (void*)1; | ||
} | ||
|
||
static void js_gpio_destroy(void* inst) { | ||
UNUSED(inst); | ||
|
||
// loop through all pins and reset them to analog mode | ||
for(int i = 0; i < 12; i++) { | ||
furi_hal_gpio_write(js_gpio_pins[i].pin, false); | ||
furi_hal_gpio_init(js_gpio_pins[i].pin, GpioModeAnalog, GpioPullNo, GpioSpeedVeryHigh); | ||
} | ||
} | ||
|
||
static const JsModuleDescriptor js_gpio_desc = { | ||
"gpio", | ||
js_gpio_create, | ||
js_gpio_destroy, | ||
}; | ||
|
||
static const FlipperAppPluginDescriptor plugin_descriptor = { | ||
.appid = PLUGIN_APP_ID, | ||
.ep_api_version = PLUGIN_API_VERSION, | ||
.entry_point = &js_gpio_desc, | ||
}; | ||
|
||
const FlipperAppPluginDescriptor* js_gpio_ep(void) { | ||
return &plugin_descriptor; | ||
} |