JS: vgm_sensor tutorial
This commit is contained in:
159
js/vgm_sensor/js_vgm/js_vgm.c
Normal file
159
js/vgm_sensor/js_vgm/js_vgm.c
Normal file
@@ -0,0 +1,159 @@
|
||||
#include "../../js_modules.h"
|
||||
#include <furi.h>
|
||||
#include <toolbox/path.h>
|
||||
#include "imu.h"
|
||||
|
||||
#define TAG "JsVgm"
|
||||
|
||||
typedef struct {
|
||||
Imu* imu;
|
||||
bool present;
|
||||
} JsVgmInst;
|
||||
|
||||
static void js_vgm_get_pitch(struct mjs* mjs) {
|
||||
mjs_val_t obj_inst = mjs_get(mjs, mjs_get_this(mjs), INST_PROP_NAME, ~0);
|
||||
JsVgmInst* vgm = mjs_get_ptr(mjs, obj_inst);
|
||||
furi_assert(vgm);
|
||||
|
||||
if(vgm->present) {
|
||||
mjs_return(mjs, mjs_mk_number(mjs, imu_pitch_get(vgm->imu)));
|
||||
} else {
|
||||
FURI_LOG_T(TAG, "VGM not present.");
|
||||
mjs_return(mjs, mjs_mk_undefined());
|
||||
}
|
||||
}
|
||||
|
||||
static void js_vgm_get_roll(struct mjs* mjs) {
|
||||
mjs_val_t obj_inst = mjs_get(mjs, mjs_get_this(mjs), INST_PROP_NAME, ~0);
|
||||
JsVgmInst* vgm = mjs_get_ptr(mjs, obj_inst);
|
||||
furi_assert(vgm);
|
||||
|
||||
if(vgm->present) {
|
||||
mjs_return(mjs, mjs_mk_number(mjs, imu_roll_get(vgm->imu)));
|
||||
} else {
|
||||
FURI_LOG_T(TAG, "VGM not present.");
|
||||
mjs_return(mjs, mjs_mk_undefined());
|
||||
}
|
||||
}
|
||||
|
||||
static void js_vgm_get_yaw(struct mjs* mjs) {
|
||||
mjs_val_t obj_inst = mjs_get(mjs, mjs_get_this(mjs), INST_PROP_NAME, ~0);
|
||||
JsVgmInst* vgm = mjs_get_ptr(mjs, obj_inst);
|
||||
furi_assert(vgm);
|
||||
|
||||
if(vgm->present) {
|
||||
mjs_return(mjs, mjs_mk_number(mjs, imu_yaw_get(vgm->imu)));
|
||||
} else {
|
||||
FURI_LOG_T(TAG, "VGM not present.");
|
||||
mjs_return(mjs, mjs_mk_undefined());
|
||||
}
|
||||
}
|
||||
|
||||
static float distance(float current, float start, float angle) {
|
||||
// make 0 to 359.999...
|
||||
current = (current < 0) ? current + 360 : current;
|
||||
start = (start < 0) ? start + 360 : start;
|
||||
|
||||
// get max and min
|
||||
bool max_is_current = current > start;
|
||||
float max = (max_is_current) ? current : start;
|
||||
float min = (max_is_current) ? start : current;
|
||||
|
||||
// get diff, check if it's greater than 180, and adjust
|
||||
float diff = max - min;
|
||||
bool diff_gt_180 = diff > 180;
|
||||
if(diff_gt_180) {
|
||||
diff = 360 - diff;
|
||||
}
|
||||
|
||||
// if diff is less than angle return 0
|
||||
if(diff < angle) {
|
||||
FURI_LOG_T(TAG, "diff: %f, angle: %f", (double)diff, (double)angle);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// return diff with sign
|
||||
return (max_is_current ^ diff_gt_180) ? -diff : diff;
|
||||
}
|
||||
|
||||
static void js_vgm_delta_yaw(struct mjs* mjs) {
|
||||
mjs_val_t obj_inst = mjs_get(mjs, mjs_get_this(mjs), INST_PROP_NAME, ~0);
|
||||
JsVgmInst* vgm = mjs_get_ptr(mjs, obj_inst);
|
||||
furi_assert(vgm);
|
||||
size_t num_args = mjs_nargs(mjs);
|
||||
if(num_args < 1 || num_args > 2) {
|
||||
mjs_prepend_errorf(
|
||||
mjs,
|
||||
MJS_BAD_ARGS_ERROR,
|
||||
"Invalid args. Pass (angle [, timeout]). Got %d args.",
|
||||
num_args);
|
||||
mjs_return(mjs, mjs_mk_undefined());
|
||||
return;
|
||||
}
|
||||
|
||||
if(!vgm->present) {
|
||||
FURI_LOG_T(TAG, "VGM not present.");
|
||||
mjs_return(mjs, MJS_UNDEFINED);
|
||||
return;
|
||||
}
|
||||
|
||||
double angle = mjs_get_double(mjs, mjs_arg(mjs, 0));
|
||||
if(isnan(angle)) {
|
||||
mjs_prepend_errorf(mjs, MJS_TYPE_ERROR, "Invalid arg (angle).");
|
||||
mjs_return(mjs, mjs_mk_undefined());
|
||||
return;
|
||||
}
|
||||
uint32_t ms = (num_args == 2) ? mjs_get_int(mjs, mjs_arg(mjs, 1)) : 3000;
|
||||
uint32_t timeout = furi_get_tick() + ms;
|
||||
float initial_yaw = imu_yaw_get(vgm->imu);
|
||||
do {
|
||||
float current_yaw = imu_yaw_get(vgm->imu);
|
||||
double diff = distance(current_yaw, initial_yaw, angle);
|
||||
if(diff != 0) {
|
||||
mjs_return(mjs, mjs_mk_number(mjs, diff));
|
||||
return;
|
||||
}
|
||||
furi_delay_ms(100);
|
||||
} while(furi_get_tick() < timeout);
|
||||
|
||||
mjs_return(mjs, mjs_mk_number(mjs, 0));
|
||||
}
|
||||
|
||||
static void* js_vgm_create(struct mjs* mjs, mjs_val_t* object) {
|
||||
JsVgmInst* vgm = malloc(sizeof(JsVgmInst));
|
||||
vgm->imu = imu_alloc();
|
||||
vgm->present = imu_present(vgm->imu);
|
||||
if(!vgm->present) FURI_LOG_W(TAG, "VGM not present.");
|
||||
mjs_val_t vgm_obj = mjs_mk_object(mjs);
|
||||
mjs_set(mjs, vgm_obj, INST_PROP_NAME, ~0, mjs_mk_foreign(mjs, vgm));
|
||||
mjs_set(mjs, vgm_obj, "getPitch", ~0, MJS_MK_FN(js_vgm_get_pitch));
|
||||
mjs_set(mjs, vgm_obj, "getRoll", ~0, MJS_MK_FN(js_vgm_get_roll));
|
||||
mjs_set(mjs, vgm_obj, "getYaw", ~0, MJS_MK_FN(js_vgm_get_yaw));
|
||||
mjs_set(mjs, vgm_obj, "deltaYaw", ~0, MJS_MK_FN(js_vgm_delta_yaw));
|
||||
*object = vgm_obj;
|
||||
return vgm;
|
||||
}
|
||||
|
||||
static void js_vgm_destroy(void* inst) {
|
||||
JsVgmInst* vgm = inst;
|
||||
furi_assert(vgm);
|
||||
imu_free(vgm->imu);
|
||||
vgm->imu = NULL;
|
||||
free(vgm);
|
||||
}
|
||||
|
||||
static const JsModuleDescriptor js_vgm_desc = {
|
||||
name: "vgm",
|
||||
create: js_vgm_create,
|
||||
destroy: js_vgm_destroy,
|
||||
};
|
||||
|
||||
static const FlipperAppPluginDescriptor plugin_descriptor = {
|
||||
.appid = PLUGIN_APP_ID,
|
||||
.ep_api_version = PLUGIN_API_VERSION,
|
||||
.entry_point = &js_vgm_desc,
|
||||
};
|
||||
|
||||
const FlipperAppPluginDescriptor* js_vgm_ep(void) {
|
||||
return &plugin_descriptor;
|
||||
}
|
||||
Reference in New Issue
Block a user