Verified Commit 91b2c78a authored by Rahix's avatar Rahix
Browse files

feat(bma400): Add basic API and pycardium module


Signed-off-by: Rahix's avatarRahix <rahix@rahix.de>
parent 7a6b17a6
...@@ -21,6 +21,7 @@ Last but not least, if you want to start hacking the lower-level firmware, the ...@@ -21,6 +21,7 @@ Last but not least, if you want to start hacking the lower-level firmware, the
:caption: Pycardium :caption: Pycardium
pycardium/overview pycardium/overview
pycardium/bma400
pycardium/color pycardium/color
pycardium/display pycardium/display
pycardium/leds pycardium/leds
......
``bma400`` - Accelerometer
==========================
.. py:function:: bma400.get_accel()
Get acceleration vector.
:return: Tuple containing ``x``, ``y``, and ``z`` acceleration.
...@@ -67,6 +67,8 @@ typedef unsigned int size_t; ...@@ -67,6 +67,8 @@ typedef unsigned int size_t;
#define API_LIGHT_SENSOR_RUN 0x80 #define API_LIGHT_SENSOR_RUN 0x80
#define API_LIGHT_SENSOR_GET 0x81 #define API_LIGHT_SENSOR_GET 0x81
#define API_LIGHT_SENSOR_STOP 0x82 #define API_LIGHT_SENSOR_STOP 0x82
#define API_BMA400_GET_ACCEL 0x90
/* clang-format on */ /* clang-format on */
typedef uint32_t api_int_id_t; typedef uint32_t api_int_id_t;
...@@ -279,6 +281,37 @@ API(API_LEDS_SET, void epic_leds_set(int led, uint8_t r, uint8_t g, uint8_t b)); ...@@ -279,6 +281,37 @@ API(API_LEDS_SET, void epic_leds_set(int led, uint8_t r, uint8_t g, uint8_t b));
*/ */
API(API_STREAM_READ, int epic_stream_read(int sd, void *buf, size_t count)); API(API_STREAM_READ, int epic_stream_read(int sd, void *buf, size_t count));
/**
* BMA400
* ======
*/
/**
* An acceleration vector.
*/
struct acceleration {
/** Acceleration component along x axis. */
float x;
/** Acceleration component along y axis. */
float y;
/** Acceleration component along z axis. */
float z;
};
/**
* Get the current acceleration vector.
*
* :param data: Where to store the acceleration vector.
* :return: 0 on success or ``-Exxx`` on error. The following
* errors might occur:
*
* - ``-EFAULT``: On NULL-pointer.
* - ``-EINVAL``: Invalid configuration.
* - ``-EIO``: Communication with the device failed.
* - ``-ENODEV``: Device was not found.
*/
API(API_BMA400_GET_ACCEL, int epic_bma400_get_accel(struct acceleration *data));
/** /**
* Vibration Motor * Vibration Motor
* =============== * ===============
......
#include <stdbool.h>
#include <stddef.h>
#include <stdio.h>
#include "bma400.h"
#include "bosch.h"
#include "card10.h"
#include "epicardium.h"
#include "modules/log.h"
static bool initialized;
static struct bma400_dev bma400;
#define GRAVITY_EARTH (9.80665f) /* Earth's gravity in m/s^2 */
static float lsb_to_ms2(int16_t val, float g_range, uint8_t bit_width)
{
float half_scale = (float)(1 << bit_width) / 2.0f;
return GRAVITY_EARTH * val * g_range / half_scale;
}
static int convert_error(int8_t error)
{
switch (error) {
case BMA400_E_NULL_PTR:
return EFAULT;
case BMA400_E_COM_FAIL:
return EIO;
case BMA400_E_DEV_NOT_FOUND:
return ENODEV;
case BMA400_E_INVALID_CONFIG:
return EINVAL;
default:
return 1;
}
}
int epic_bma400_get_accel(struct acceleration *data)
{
uint8_t result;
if (__builtin_expect(!initialized, 0)) {
bma400.intf_ptr = NULL;
bma400.delay_ms = card10_bosch_delay;
bma400.dev_id = BMA400_I2C_ADDRESS_SDO_LOW;
bma400.read = card10_bosch_i2c_read_ex;
bma400.write = card10_bosch_i2c_write_ex;
bma400.intf = BMA400_I2C_INTF;
result = bma400_init(&bma400);
if (result != BMA400_OK) {
LOG_ERR("bma400", "init error: %d", result);
return -convert_error(result);
}
result = bma400_soft_reset(&bma400);
if (result != BMA400_OK) {
LOG_ERR("bma400", "soft_reset error: %d", result);
return -convert_error(result);
}
struct bma400_sensor_conf conf;
conf.type = BMA400_ACCEL;
result = bma400_get_sensor_conf(&conf, 1, &bma400);
if (result != BMA400_OK) {
LOG_ERR("bma400", "get_sensor_conf error: %d", result);
return -convert_error(result);
}
conf.param.accel.odr = BMA400_ODR_100HZ;
conf.param.accel.range = BMA400_2G_RANGE;
conf.param.accel.data_src = BMA400_DATA_SRC_ACCEL_FILT_1;
result = bma400_set_sensor_conf(&conf, 1, &bma400);
if (result != BMA400_OK) {
LOG_ERR("bma400", "set_sensor_conf error: %d", result);
return -convert_error(result);
}
result = bma400_set_power_mode(BMA400_LOW_POWER_MODE, &bma400);
if (result != BMA400_OK) {
LOG_ERR("bma400", "set_power_mode error: %d", result);
return -convert_error(result);
}
initialized = true;
}
struct bma400_sensor_data data_in;
result = bma400_get_accel_data(
BMA400_DATA_SENSOR_TIME, &data_in, &bma400
);
if (result != BMA400_OK) {
LOG_ERR("bma400", "get_accel_data error: %d\n", result);
return -convert_error(result);
}
data->x = lsb_to_ms2(data_in.x, 2, 12);
data->y = lsb_to_ms2(data_in.y, 2, 12);
data->z = lsb_to_ms2(data_in.z, 2, 12);
return 0;
}
module_sources = files( module_sources = files(
'bma400.c',
'display.c', 'display.c',
'fatfs.c', 'fatfs.c',
'fatfs_fileops.c', 'fatfs_fileops.c',
......
name = 'pycardium' name = 'pycardium'
modsrc = files( modsrc = files(
'modules/bma400.c',
'modules/interrupt.c', 'modules/interrupt.c',
'modules/leds.c', 'modules/leds.c',
'modules/sys_display.c', 'modules/sys_display.c',
......
#include "py/obj.h"
#include "py/objlist.h"
#include "py/runtime.h"
#include "epicardium.h"
static mp_obj_t mp_bma400_get_accel()
{
struct acceleration values;
int ret = epic_bma400_get_accel(&values);
if (ret < 0) {
mp_raise_OSError(-ret);
}
mp_obj_t values_list[] = {
mp_obj_new_float(values.x),
mp_obj_new_float(values.y),
mp_obj_new_float(values.z),
};
return mp_obj_new_tuple(3, values_list);
}
static MP_DEFINE_CONST_FUN_OBJ_0(bma400_get_accel_obj, mp_bma400_get_accel);
static const mp_rom_map_elem_t bma400_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_bma400) },
{ MP_ROM_QSTR(MP_QSTR_get_accel), MP_ROM_PTR(&bma400_get_accel_obj) },
};
static MP_DEFINE_CONST_DICT(bma400_module_globals, bma400_module_globals_table);
const mp_obj_module_t bma400_module = {
.base = { &mp_type_module },
.globals = (mp_obj_dict_t *)&bma400_module_globals,
};
/* Register the module to make it available in Python */
MP_REGISTER_MODULE(MP_QSTR_bma400, bma400_module, MODULE_BMA400_ENABLED);
...@@ -4,6 +4,10 @@ ...@@ -4,6 +4,10 @@
#define Q(x) #define Q(x)
#endif #endif
/* bma400 */
Q(bma400)
Q(get_accel)
/* leds */ /* leds */
Q(leds) Q(leds)
Q(BOTTOM_LEFT) Q(BOTTOM_LEFT)
......
...@@ -40,6 +40,7 @@ ...@@ -40,6 +40,7 @@
/* Modules */ /* Modules */
#define MODULE_UTIME_ENABLED (1) #define MODULE_UTIME_ENABLED (1)
#define MODULE_LEDS_ENABLED (1) #define MODULE_LEDS_ENABLED (1)
#define MODULE_BMA400_ENABLED (1)
#define MODULE_VIBRA_ENABLED (1) #define MODULE_VIBRA_ENABLED (1)
#define MODULE_INTERRUPT_ENABLED (1) #define MODULE_INTERRUPT_ENABLED (1)
#define MODULE_DISPLAY_ENABLED (1) #define MODULE_DISPLAY_ENABLED (1)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment