mirror of
https://github.com/DarkFlippers/unleashed-firmware
synced 2024-11-13 00:07:12 +00:00
add js adc
by jamisonderek https://github.com/Next-Flip/Momentum-Firmware/pull/143/files
This commit is contained in:
parent
949b55f31a
commit
ceaf2d4153
2 changed files with 180 additions and 15 deletions
|
@ -0,0 +1,42 @@
|
|||
// This is an example of how to use the analog pins (ADC) on the Flipper Zero.
|
||||
// The example uses a reference voltage of 2048mV (2.048V), but you can also use 2500mV (2.5V).
|
||||
// The example reads the values of the analog pins A7, A6, and A4 and prints them to the console.
|
||||
// The example also checks if the value of A7 is twice the value of A6 and breaks the loop if it is.
|
||||
// The example uses the analog pins A7, A6, and A4, but you can also use PC3, PC1, and PC0.
|
||||
|
||||
let gpio = require("gpio");
|
||||
|
||||
// initialize pins A7, A6, A4 as analog (you can also use PC3, PC1, PC0)
|
||||
gpio.init("PA7", "analog", "no"); // pin, mode, pull
|
||||
gpio.init("PA6", "analog", "no"); // pin, mode, pull
|
||||
gpio.init("PA4", "analog", "no"); // pin, mode, pull
|
||||
|
||||
gpio.startAnalog(2048); // vRef = 2.048V (you can also use 2500 for a 2.5V reference voltage)
|
||||
|
||||
while (true) {
|
||||
let pa7_value = gpio.readAnalog("PA7");
|
||||
let pa6_value = gpio.readAnalog("PA6");
|
||||
let pa4_value = gpio.readAnalog("PA4");
|
||||
print("A7: " + to_string(pa7_value) + " A6: " + to_string(pa6_value) + " A4: " + to_string(pa4_value));
|
||||
delay(100);
|
||||
if (pa7_value === pa6_value * 2) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
print("A7 is twice A6!");
|
||||
|
||||
gpio.stopAnalog();
|
||||
|
||||
// possible analog pins https://docs.flipper.net/gpio-and-modules#miFsS
|
||||
// "PA7" aka 2
|
||||
// "PA6" aka 3
|
||||
// "PA4" aka 4
|
||||
// "PC3" aka 7
|
||||
// "PC1" aka 15
|
||||
// "PC0" aka 16
|
||||
|
||||
// possible modes
|
||||
// "analog"
|
||||
|
||||
// possible pull
|
||||
// "no"
|
|
@ -3,25 +3,30 @@
|
|||
#include <furi_hal_resources.h>
|
||||
#include <expansion/expansion.h>
|
||||
|
||||
typedef struct {
|
||||
FuriHalAdcHandle* handle;
|
||||
} JsGpioInst;
|
||||
|
||||
typedef struct {
|
||||
const GpioPin* pin;
|
||||
const char* name;
|
||||
const FuriHalAdcChannel channel;
|
||||
} 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
|
||||
{.pin = &gpio_ext_pa7, .name = "PA7", .channel = FuriHalAdcChannel12}, // 2
|
||||
{.pin = &gpio_ext_pa6, .name = "PA6", .channel = FuriHalAdcChannel11}, // 3
|
||||
{.pin = &gpio_ext_pa4, .name = "PA4", .channel = FuriHalAdcChannel9}, // 4
|
||||
{.pin = &gpio_ext_pb3, .name = "PB3", .channel = FuriHalAdcChannelNone}, // 5
|
||||
{.pin = &gpio_ext_pb2, .name = "PB2", .channel = FuriHalAdcChannelNone}, // 6
|
||||
{.pin = &gpio_ext_pc3, .name = "PC3", .channel = FuriHalAdcChannel4}, // 7
|
||||
{.pin = &gpio_swclk, .name = "PA14", .channel = FuriHalAdcChannelNone}, // 10
|
||||
{.pin = &gpio_swdio, .name = "PA13", .channel = FuriHalAdcChannelNone}, // 12
|
||||
{.pin = &gpio_usart_tx, .name = "PB6", .channel = FuriHalAdcChannelNone}, // 13
|
||||
{.pin = &gpio_usart_rx, .name = "PB7", .channel = FuriHalAdcChannelNone}, // 14
|
||||
{.pin = &gpio_ext_pc1, .name = "PC1", .channel = FuriHalAdcChannel2}, // 15
|
||||
{.pin = &gpio_ext_pc0, .name = "PC0", .channel = FuriHalAdcChannel1}, // 16
|
||||
{.pin = &gpio_ibutton, .name = "PB14", .channel = FuriHalAdcChannelNone}, // 17
|
||||
};
|
||||
|
||||
bool js_gpio_get_gpio_pull(const char* pull, GpioPull* value) {
|
||||
|
@ -92,6 +97,15 @@ const GpioPin* js_gpio_get_gpio_pin(const char* name) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
FuriHalAdcChannel js_gpio_get_gpio_channel(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].channel;
|
||||
}
|
||||
}
|
||||
return FuriHalAdcChannelNone;
|
||||
}
|
||||
|
||||
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);
|
||||
|
@ -232,18 +246,127 @@ static void js_gpio_read(struct mjs* mjs) {
|
|||
mjs_return(mjs, mjs_mk_boolean(mjs, value));
|
||||
}
|
||||
|
||||
static void js_gpio_read_analog(struct mjs* mjs) {
|
||||
mjs_val_t obj_inst = mjs_get(mjs, mjs_get_this(mjs), INST_PROP_NAME, ~0);
|
||||
JsGpioInst* gpio = mjs_get_ptr(mjs, obj_inst);
|
||||
furi_assert(gpio);
|
||||
|
||||
if(gpio->handle == NULL) {
|
||||
mjs_prepend_errorf(mjs, MJS_INTERNAL_ERROR, "Analog mode not started");
|
||||
mjs_return(mjs, MJS_UNDEFINED);
|
||||
return;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
FuriHalAdcChannel channel = js_gpio_get_gpio_channel(pin_name);
|
||||
if(channel == FuriHalAdcChannelNone) {
|
||||
mjs_prepend_errorf(mjs, MJS_BAD_ARGS_ERROR, "Invalid pin name");
|
||||
mjs_return(mjs, MJS_UNDEFINED);
|
||||
return;
|
||||
}
|
||||
|
||||
uint16_t adc_value = furi_hal_adc_read(gpio->handle, channel);
|
||||
float adc_mv = furi_hal_adc_convert_to_voltage(gpio->handle, adc_value);
|
||||
|
||||
mjs_return(mjs, mjs_mk_number(mjs, adc_mv));
|
||||
}
|
||||
|
||||
static void js_gpio_start_analog(struct mjs* mjs) {
|
||||
mjs_val_t obj_inst = mjs_get(mjs, mjs_get_this(mjs), INST_PROP_NAME, ~0);
|
||||
JsGpioInst* gpio = mjs_get_ptr(mjs, obj_inst);
|
||||
furi_assert(gpio);
|
||||
|
||||
FuriHalAdcScale scale = FuriHalAdcScale2048;
|
||||
if(mjs_nargs(mjs) > 0) {
|
||||
mjs_val_t scale_arg = mjs_arg(mjs, 0);
|
||||
|
||||
if(!mjs_is_number(scale_arg)) {
|
||||
mjs_prepend_errorf(mjs, MJS_BAD_ARGS_ERROR, "Argument must be a number");
|
||||
mjs_return(mjs, MJS_UNDEFINED);
|
||||
return;
|
||||
}
|
||||
|
||||
int32_t scale_num = mjs_get_int32(mjs, scale_arg);
|
||||
if(scale_num == 2048 || scale_num == 2000) { // 2 volt reference
|
||||
scale = FuriHalAdcScale2048;
|
||||
} else if(scale_num == 2500) { // 2.5 volt reference
|
||||
scale = FuriHalAdcScale2500;
|
||||
} else {
|
||||
mjs_prepend_errorf(mjs, MJS_BAD_ARGS_ERROR, "Invalid scale");
|
||||
mjs_return(mjs, MJS_UNDEFINED);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if(gpio->handle != NULL) {
|
||||
mjs_prepend_errorf(mjs, MJS_INTERNAL_ERROR, "Analog mode already started");
|
||||
mjs_return(mjs, MJS_UNDEFINED);
|
||||
return;
|
||||
}
|
||||
|
||||
gpio->handle = furi_hal_adc_acquire();
|
||||
furi_hal_adc_configure_ex(
|
||||
gpio->handle,
|
||||
scale,
|
||||
FuriHalAdcClockSync64,
|
||||
FuriHalAdcOversample64,
|
||||
FuriHalAdcSamplingtime247_5);
|
||||
}
|
||||
|
||||
static void js_gpio_stop_analog(struct mjs* mjs) {
|
||||
mjs_val_t obj_inst = mjs_get(mjs, mjs_get_this(mjs), INST_PROP_NAME, ~0);
|
||||
JsGpioInst* gpio = mjs_get_ptr(mjs, obj_inst);
|
||||
furi_assert(gpio);
|
||||
|
||||
if(gpio->handle == NULL) {
|
||||
mjs_prepend_errorf(mjs, MJS_INTERNAL_ERROR, "Analog mode not started");
|
||||
mjs_return(mjs, MJS_UNDEFINED);
|
||||
return;
|
||||
}
|
||||
|
||||
furi_hal_adc_release(gpio->handle);
|
||||
gpio->handle = NULL;
|
||||
}
|
||||
|
||||
static void* js_gpio_create(struct mjs* mjs, mjs_val_t* object) {
|
||||
JsGpioInst* gpio = malloc(sizeof(JsGpioInst));
|
||||
gpio->handle = NULL;
|
||||
mjs_val_t gpio_obj = mjs_mk_object(mjs);
|
||||
mjs_set(mjs, gpio_obj, INST_PROP_NAME, ~0, mjs_mk_foreign(mjs, gpio));
|
||||
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));
|
||||
mjs_set(mjs, gpio_obj, "readAnalog", ~0, MJS_MK_FN(js_gpio_read_analog));
|
||||
mjs_set(mjs, gpio_obj, "startAnalog", ~0, MJS_MK_FN(js_gpio_start_analog));
|
||||
mjs_set(mjs, gpio_obj, "stopAnalog", ~0, MJS_MK_FN(js_gpio_stop_analog));
|
||||
*object = gpio_obj;
|
||||
|
||||
return (void*)1;
|
||||
return (void*)gpio;
|
||||
}
|
||||
|
||||
static void js_gpio_destroy(void* inst) {
|
||||
UNUSED(inst);
|
||||
if(inst != NULL) {
|
||||
JsGpioInst* gpio = (JsGpioInst*)inst;
|
||||
if(gpio->handle != NULL) {
|
||||
furi_hal_adc_release(gpio->handle);
|
||||
gpio->handle = NULL;
|
||||
}
|
||||
free(gpio);
|
||||
}
|
||||
|
||||
// loop through all pins and reset them to analog mode
|
||||
for(size_t i = 0; i < COUNT_OF(js_gpio_pins); i++) {
|
||||
|
|
Loading…
Reference in a new issue