flipper-zero-tutorials/js/vgm_sensor/js_vgm/js_vgm.c
2024-04-12 15:00:38 -05:00

160 lines
4.7 KiB
C

#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;
}