blob: 4206cffe24b8f0ea3f2a5dded359bbd471615c71 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#include <string.h>
#include <errno.h>
#include "os/mynewt.h"
#include "console/console.h"
#include "shell/shell.h"
#include "hal/hal_gpio.h"
#include "bno055_priv.h"
#include "bno055/bno055.h"
#include "sensor/sensor.h"
#include "sensor/accel.h"
#include "sensor/mag.h"
#include "sensor/quat.h"
#include "sensor/euler.h"
#include "hal/hal_i2c.h"
#include "parse/parse.h"
#if MYNEWT_VAL(BNO055_CLI)
static int bno055_shell_cmd(int argc, char **argv);
static struct shell_cmd bno055_shell_cmd_struct = {
.sc_cmd = "bno055",
.sc_cmd_func = bno055_shell_cmd
};
static struct sensor_itf g_sensor_itf = {
.si_type = MYNEWT_VAL(BNO055_SHELL_ITF_TYPE),
.si_num = MYNEWT_VAL(BNO055_SHELL_ITF_NUM),
.si_addr = MYNEWT_VAL(BNO055_SHELL_ITF_ADDR),
};
static int
bno055_shell_err_too_many_args(char *cmd_name)
{
console_printf("Error: too many arguments for command \"%s\"\n",
cmd_name);
return EINVAL;
}
static int
bno055_shell_err_unknown_arg(char *cmd_name)
{
console_printf("Error: unknown argument \"%s\"\n",
cmd_name);
return EINVAL;
}
static int
bno055_shell_err_invalid_arg(char *cmd_name)
{
console_printf("Error: invalid argument \"%s\"\n",
cmd_name);
return EINVAL;
}
static int
bno055_shell_help(void)
{
console_printf("%s cmd [flags...]\n", bno055_shell_cmd_struct.sc_cmd);
console_printf("cmd:\n");
console_printf("\tr [n_samples] [ 0-acc | 1 -mag | 2 -gyro | 4 -temp |\n"
"\t 9-quat | 26-linearacc | 27-gravity | 28-euler ]\n\n");
console_printf("\tmode [0-config | 1-acc | 2 -mag | 3 -gyro | 4 -accmag |\n"
"\t 5-accgyro | 6-maggyro | 7 -amg | 8 -imuplus | 9 -compass|\n"
"\t 9-m4g |11-NDOF_FMC_OFF | 12-NDOF ]\n");
console_printf("\tchip_id\n");
console_printf("\trev\n");
console_printf("\treset\n");
console_printf("\tpmode [0-normal | 1-lowpower | 2-suspend]\n");
console_printf("\tsensor_offsets\n");
console_printf("\tdumpreg [addr]\n");
return 0;
}
static int
bno055_shell_cmd_sensor_offsets(int argc, char **argv)
{
int i;
int rc;
struct bno055_sensor_offsets bso;
uint16_t val;
uint16_t offsetdata[11] = {0};
char *tok;
rc = 0;
if (argc > 3) {
return bno055_shell_err_too_many_args(argv[1]);
}
/* Display the chip id */
if (argc == 2) {
rc = bno055_get_sensor_offsets(&g_sensor_itf, &bso);
if (rc) {
console_printf("Read failed %d\n", rc);
goto err;
}
console_printf("Offsets:\n");
console_printf(" \tacc \t | gyro\t | mag \t \n"
"\tx :0x%02X\t : 0x%02X\t : 0x%02X\t \n"
"\ty :0x%02X\t : 0x%02X\t : 0x%02X\t \n"
"\tz :0x%02X\t : 0x%02X\t : 0x%02X\t \n"
"\trad:0x%02X\t : \t : 0x%02X\t \n",
bso.bso_acc_off_x, bso.bso_mag_off_x,
bso.bso_gyro_off_x, bso.bso_acc_off_y,
bso.bso_mag_off_y, bso.bso_gyro_off_y,
bso.bso_acc_off_z, bso.bso_mag_off_z,
bso.bso_gyro_off_z, bso.bso_acc_radius,
bso.bso_mag_radius);
} else if (argc == 3) {
tok = strtok(argv[2], ":");
i = 0;
do {
val = parse_ll_bounds(tok, 0, UINT16_MAX, &rc);
if (rc) {
return bno055_shell_err_invalid_arg(argv[2]);
}
offsetdata[i] = val;
tok = strtok(0, ":");
} while(i++ < 11 && tok);
bso.bso_acc_off_x = offsetdata[0];
bso.bso_acc_off_y = offsetdata[1];
bso.bso_acc_off_z = offsetdata[2];
bso.bso_gyro_off_x = offsetdata[3];
bso.bso_gyro_off_y = offsetdata[4];
bso.bso_gyro_off_z = offsetdata[5];
bso.bso_mag_off_x = offsetdata[6];
bso.bso_mag_off_y = offsetdata[7];
bso.bso_mag_off_z = offsetdata[8];
bso.bso_acc_radius = offsetdata[9];
bso.bso_mag_radius = offsetdata[10];
rc = bno055_set_sensor_offsets(&g_sensor_itf, &bso);
if (rc) {
goto err;
}
}
return 0;
err:
return rc;
}
static int
bno055_shell_cmd_get_chip_id(int argc, char **argv)
{
uint8_t id;
int rc;
if (argc > 3) {
return bno055_shell_err_too_many_args(argv[1]);
}
/* Display the chip id */
if (argc == 2) {
rc = bno055_get_chip_id(&g_sensor_itf, &id);
if (rc) {
console_printf("Read failed %d", rc);
}
console_printf("0x%02X\n", id);
}
return 0;
}
static int
bno055_shell_cmd_get_rev_info(int argc, char **argv)
{
int rc;
struct bno055_rev_info ri;
if (argc > 3) {
return bno055_shell_err_too_many_args(argv[1]);
}
/* Display the rev ids */
if (argc == 2) {
rc = bno055_get_rev_info(&g_sensor_itf, &ri);
if (rc) {
console_printf("Read failed %d", rc);
}
console_printf("accel_rev:0x%02X\nmag_rev:0x%02X\ngyro_rev:0x%02X\n"
"sw_rev:0x%02X\nbl_rev:0x%02X\n", ri.bri_accel_rev,
ri.bri_mag_rev, ri.bri_gyro_rev, ri.bri_sw_rev,
ri.bri_bl_rev);
}
return 0;
}
static int
bno055_shell_cmd_read(int argc, char **argv)
{
uint16_t samples = 1;
uint16_t val;
int rc;
void *databuf;
struct sensor_quat_data *sqd;
struct sensor_euler_data *sed;
struct sensor_accel_data *sad;
int8_t *temp;
int type;
char tmpstr[13];
type = SENSOR_TYPE_NONE;
if (argc > 4) {
return bno055_shell_err_too_many_args(argv[1]);
}
/* Since this is the biggest struct, malloc space for it */
databuf = malloc(sizeof(*sqd));
assert(databuf != NULL);
/* Check if more than one sample requested */
if (argc == 4) {
val = parse_ll_bounds(argv[2], 0, UINT16_MAX, &rc);
if (rc) {
return bno055_shell_err_invalid_arg(argv[2]);
}
samples = (uint16_t)val;
val = parse_ll_bounds(argv[3], 0, UINT16_MAX, &rc);
if (rc) {
return bno055_shell_err_invalid_arg(argv[3]);
}
type = (int)(1 << val);
} else {
console_printf("Usage:\n");
console_printf("\tr [n_samples] [ 0-acc | 1 -mag | 2 -gyro | 4 -temp |\n"
"\t 9-quat | 26-linearacc | 27-gravity | 28-euler ]\n\n");
}
while(samples--) {
if (type == SENSOR_TYPE_ROTATION_VECTOR) {
rc = bno055_get_quat_data(&g_sensor_itf, databuf);
if (rc) {
console_printf("Read failed: %d\n", rc);
goto err;
}
sqd = databuf;
console_printf("x:%s ", sensor_ftostr(sqd->sqd_x, tmpstr, 13));
console_printf("y:%s ", sensor_ftostr(sqd->sqd_y, tmpstr, 13));
console_printf("z:%s ", sensor_ftostr(sqd->sqd_z, tmpstr, 13));
console_printf("w:%s\n", sensor_ftostr(sqd->sqd_w, tmpstr, 13));
} else if (type == SENSOR_TYPE_EULER) {
rc = bno055_get_vector_data(&g_sensor_itf, databuf, type);
if (rc) {
console_printf("Read failed: %d\n", rc);
goto err;
}
sed = databuf;
console_printf("h:%s ", sensor_ftostr(sed->sed_h, tmpstr, 13));
console_printf("r:%s ", sensor_ftostr(sed->sed_r, tmpstr, 13));
console_printf("p:%s\n", sensor_ftostr(sed->sed_p, tmpstr, 13));
} else if (type == SENSOR_TYPE_TEMPERATURE) {
rc = bno055_get_temp(&g_sensor_itf, databuf);
if (rc) {
console_printf("Read failed: %d\n", rc);
goto err;
}
temp = databuf;
console_printf("Temperature:%u\n", *temp);
} else {
rc = bno055_get_vector_data(&g_sensor_itf, databuf, type);
if (rc) {
console_printf("Read failed: %d\n", rc);
goto err;
}
sad = databuf;
console_printf("x:%s ", sensor_ftostr(sad->sad_x, tmpstr, 13));
console_printf("y:%s ", sensor_ftostr(sad->sad_y, tmpstr, 13));
console_printf("z:%s\n", sensor_ftostr(sad->sad_z, tmpstr, 13));
}
}
free(databuf);
return 0;
err:
return rc;
}
static int
bno055_shell_cmd_opr_mode(int argc, char **argv)
{
uint8_t val;
int rc;
if (argc > 3) {
return bno055_shell_err_too_many_args(argv[1]);
}
/* Display the mode */
if (argc == 2) {
rc = bno055_get_opr_mode(&g_sensor_itf, (uint8_t *)&val);
if (rc) {
goto err;
}
console_printf("%u\n", ((unsigned int)(*(uint8_t *)&val)));
}
/* Update the mode */
if (argc == 3) {
val = parse_ll_bounds(argv[2], 0, BNO055_OPR_MODE_NDOF, &rc);
if (rc) {
return bno055_shell_err_invalid_arg(argv[2]);
}
/* Make sure mode is valid */
if (val > BNO055_OPR_MODE_NDOF) {
return bno055_shell_err_invalid_arg(argv[2]);
}
rc = bno055_set_opr_mode(&g_sensor_itf, val);
if (rc) {
goto err;
}
}
return 0;
err:
return rc;
}
static int
bno055_shell_cmd_pwr_mode(int argc, char **argv)
{
uint8_t val;
int rc;
if (argc > 3) {
return bno055_shell_err_too_many_args(argv[1]);
}
/* Display the mode */
if (argc == 2) {
rc = bno055_get_pwr_mode(&g_sensor_itf, (uint8_t *)&val);
if (rc) {
goto err;
}
console_printf("%u\n", (unsigned int)val);
}
/* Update the mode */
if (argc == 3) {
val = parse_ll_bounds(argv[2], 0, BNO055_PWR_MODE_SUSPEND, &rc);
if (rc) {
return bno055_shell_err_invalid_arg(argv[2]);
}
rc = bno055_set_pwr_mode(&g_sensor_itf, val);
if (rc) {
goto err;
}
}
return 0;
err:
return rc;
}
static int
bno055_shell_units_cmd(int argc, char **argv)
{
uint8_t val;
int rc;
if (argc > 3) {
return bno055_shell_err_too_many_args(argv[1]);
}
/* Display the units */
if (argc == 2) {
rc = bno055_get_units(&g_sensor_itf, (uint8_t *)&val);
console_printf("Acc, linear acc, gravity: %s\n"
"Mag field strength: Micro Tesla\n"
"Ang rate: %s\n"
"Euler ang: %s\n",
(uint8_t)val & BNO055_ACC_UNIT_MG ? "mg":"m/s^2",
(uint8_t)val & BNO055_ANGRATE_UNIT_RPS ? "Rps":"Dps",
(uint8_t)val & BNO055_EULER_UNIT_RAD ? "Rad":"Deg");
console_printf("Quat: Quat units\n"
"Temp: %s\n"
"Fusion data output: %s\n",
(uint8_t)val & BNO055_TEMP_UNIT_DEGF ? "Deg F":"Deg C",
(uint8_t)val & BNO055_DO_FORMAT_ANDROID ? "Android":"Windows");
}
/* Update the units */
if (argc == 3) {
val = parse_ll_bounds(argv[2], 0, UINT8_MAX, &rc);
if (rc) {
return bno055_shell_err_invalid_arg(argv[2]);
}
rc = bno055_set_units(&g_sensor_itf, val);
if (rc) {
goto err;
}
}
return 0;
err:
return rc;
}
static int
bno055_shell_cmd_dumpreg(int argc, char **argv)
{
uint8_t addr;
uint8_t val;
int rc;
addr = parse_ll_bounds(argv[2], 0, UINT8_MAX, &rc);
if (rc) {
return bno055_shell_err_invalid_arg(argv[2]);
}
rc = bno055_read8(&g_sensor_itf, addr, &val);
if (rc) {
goto err;
}
console_printf("0x%02X (ADDR): 0x%02X", addr, val);
return 0;
err:
return rc;
}
static int
bno055_shell_cmd_reset(int argc, char **argv)
{
int rc;
/* Reset sensor */
rc = bno055_write8(&g_sensor_itf, BNO055_SYS_TRIGGER_ADDR, BNO055_SYS_TRIGGER_RST_SYS);
if (rc) {
goto err;
}
return 0;
err:
return rc;
}
static int
bno055_shell_cmd(int argc, char **argv)
{
if (argc == 1) {
return bno055_shell_help();
}
/* Read command (get a new data sample) */
if (argc > 1 && strcmp(argv[1], "r") == 0) {
return bno055_shell_cmd_read(argc, argv);
}
/* Mode command */
if (argc > 1 && strcmp(argv[1], "mode") == 0) {
return bno055_shell_cmd_opr_mode(argc, argv);
}
/* Chip ID command */
if (argc > 1 && strcmp(argv[1], "chip_id") == 0) {
return bno055_shell_cmd_get_chip_id(argc, argv);
}
/* Rev command */
if (argc > 1 && strcmp(argv[1], "rev") == 0) {
return bno055_shell_cmd_get_rev_info(argc, argv);
}
/* Reset command */
if (argc > 1 && strcmp(argv[1], "reset") == 0) {
return bno055_shell_cmd_reset(argc, argv);
}
/* Power mode command */
if (argc > 1 && strcmp(argv[1], "pmode") == 0) {
return bno055_shell_cmd_pwr_mode(argc, argv);
}
/* Dump Registers command */
if (argc > 1 && strcmp(argv[1], "dumpreg") == 0) {
return bno055_shell_cmd_dumpreg(argc, argv);
}
if (argc > 1 && strcmp(argv[1], "units") == 0) {
return bno055_shell_units_cmd(argc, argv);
}
if (argc > 1 && strcmp(argv[1], "sensor_offsets") == 0) {
return bno055_shell_cmd_sensor_offsets(argc, argv);
}
return bno055_shell_err_unknown_arg(argv[1]);
}
int
bno055_shell_init(void)
{
int rc;
rc = shell_cmd_register(&bno055_shell_cmd_struct);
SYSINIT_PANIC_ASSERT(rc == 0);
return rc;
}
#endif