First integration of the motion sensor (bma 421) : step counting + wake on wrist rotation + app to see the value of the 3 axis in "real time".

This commit is contained in:
Jean-François Milants 2021-03-31 19:47:27 +02:00
parent 04fc33e2d4
commit 68bdaee1cc
27 changed files with 12344 additions and 26 deletions

View file

@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.10)
project(pinetime VERSION 0.15.0 LANGUAGES C CXX ASM)
project(pinetime VERSION 0.16.0 LANGUAGES C CXX ASM)
set(CMAKE_C_STANDARD 99)
set(CMAKE_CXX_STANDARD 14)

View file

@ -490,6 +490,7 @@ list(APPEND SOURCE_FILES
displayapp/screens/Notifications.cpp
displayapp/screens/Twos.cpp
displayapp/screens/HeartRate.cpp
displayapp/screens/Motion.cpp
## Watch faces
displayapp/icons/bg_clock.c
@ -508,11 +509,15 @@ list(APPEND SOURCE_FILES
drivers/DebugPins.cpp
drivers/InternalFlash.cpp
drivers/Hrs3300.cpp
drivers/Bma421.cpp
drivers/Bma421_C/bma4.c
drivers/Bma421_C/bma423.c
components/battery/BatteryController.cpp
components/ble/BleController.cpp
components/ble/NotificationManager.cpp
components/datetime/DateTimeController.cpp
components/brightness/BrightnessController.cpp
components/motion/MotionController.cpp
components/ble/NimbleController.cpp
components/ble/DeviceInformationService.cpp
components/ble/CurrentTimeClient.cpp
@ -563,11 +568,15 @@ list(APPEND RECOVERY_SOURCE_FILES
drivers/DebugPins.cpp
drivers/InternalFlash.cpp
drivers/Hrs3300.cpp
drivers/Bma421.cpp
drivers/Bma421_C/bma4.c
drivers/Bma421_C/bma423.c
components/battery/BatteryController.cpp
components/ble/BleController.cpp
components/ble/NotificationManager.cpp
components/datetime/DateTimeController.cpp
components/brightness/BrightnessController.cpp
components/motion/MotionController.cpp
components/ble/NimbleController.cpp
components/ble/DeviceInformationService.cpp
components/ble/CurrentTimeClient.cpp
@ -651,6 +660,7 @@ set(INCLUDE_FILES
displayapp/Apps.h
displayapp/screens/Notifications.h
displayapp/screens/HeartRate.h
displayapp/screens/Motion.h
drivers/St7789.h
drivers/SpiNorFlash.h
drivers/SpiMaster.h
@ -659,11 +669,15 @@ set(INCLUDE_FILES
drivers/DebugPins.h
drivers/InternalFlash.h
drivers/Hrs3300.h
drivers/Bma421.h
drivers/Bma421_C/bma4.c
drivers/Bma421_C/bma423.c
components/battery/BatteryController.h
components/ble/BleController.h
components/ble/NotificationManager.h
components/datetime/DateTimeController.h
components/brightness/BrightnessController.h
components/motion/MotionController.h
components/ble/NimbleController.h
components/ble/DeviceInformationService.h
components/ble/CurrentTimeClient.h

View file

@ -0,0 +1,33 @@
#include "MotionController.h"
using namespace Pinetime::Controllers;
void MotionController::Update(int16_t x, int16_t y, int16_t z, uint32_t nbSteps) {
this->x = x;
this->y = y;
this->z = z;
this->nbSteps = nbSteps;
}
bool MotionController::ShouldWakeUp(bool isSleeping) {
if ((x + 335) <= 670 && z < 0) {
if (not isSleeping) {
if (y <= 0) {
return false;
} else {
lastYForWakeUp = 0;
return false;
}
}
if (y >= 0) {
lastYForWakeUp = 0;
return false;
}
if (y + 230 < lastYForWakeUp) {
lastYForWakeUp = y;
return true;
}
}
return false;
}

View file

@ -0,0 +1,26 @@
#pragma once
#include <cstdint>
namespace Pinetime {
namespace Controllers {
class MotionController {
public:
void Update(int16_t x, int16_t y, int16_t z, uint32_t nbSteps);
uint16_t X() const { return x; }
uint16_t Y() const { return y; }
uint16_t Z() const { return z; }
uint32_t NbSteps() const { return nbSteps; }
bool ShouldWakeUp(bool isSleeping);
private:
uint32_t nbSteps;
int16_t x;
int16_t y;
int16_t z;
int16_t lastYForWakeUp = 0;
};
}
}

View file

@ -2,6 +2,7 @@
namespace Pinetime {
namespace Applications {
enum class Apps {None, Launcher, Clock, SysInfo, Meter, Brightness, Music, FirmwareValidation, Paint, Paddle, Notifications, Twos, HeartRate, Navigation, StopWatch};
enum class Apps {None, Launcher, Clock, SysInfo, Meter, Brightness, Music, FirmwareValidation,
Paint, Paddle, Notifications, Twos, HeartRate, Navigation, StopWatch, Motion};
}
}

View file

@ -1,10 +1,12 @@
#include "DisplayApp.h"
#include <libraries/log/nrf_log.h>
#include <displayapp/screens/HeartRate.h>
#include <displayapp/screens/Motion.h>
#include "components/battery/BatteryController.h"
#include "components/ble/BleController.h"
#include "components/datetime/DateTimeController.h"
#include "components/ble/NotificationManager.h"
#include "components/motion/MotionController.h"
#include "displayapp/screens/ApplicationList.h"
#include "displayapp/screens/Brightness.h"
#include "displayapp/screens/Clock.h"
@ -34,7 +36,8 @@ DisplayApp::DisplayApp(Drivers::St7789 &lcd, Components::LittleVgl &lvgl, Driver
System::SystemTask &systemTask,
Pinetime::Controllers::NotificationManager& notificationManager,
Pinetime::Controllers::HeartRateController& heartRateController,
Controllers::Settings &settingsController) :
Controllers::Settings &settingsController,
Pinetime::Controllers::MotionController& motionController) :
lcd{lcd},
lvgl{lvgl},
batteryController{batteryController},
@ -42,11 +45,12 @@ DisplayApp::DisplayApp(Drivers::St7789 &lcd, Components::LittleVgl &lvgl, Driver
dateTimeController{dateTimeController},
watchdog{watchdog},
touchPanel{touchPanel},
currentScreen{new Screens::Clock(this, dateTimeController, batteryController, bleController, notificationManager, settingsController, heartRateController) },
currentScreen{new Screens::Clock(this, dateTimeController, batteryController, bleController, notificationManager, settingsController, heartRateController, motionController) },
systemTask{systemTask},
notificationManager{notificationManager},
heartRateController{heartRateController},
settingsController{settingsController} {
settingsController{settingsController},
motionController{motionController} {
msgQueue = xQueueCreate(queueSize, itemSize);
onClockApp = true;
}
@ -204,7 +208,7 @@ void DisplayApp::RunningState() {
case Apps::None:
case Apps::Launcher: currentScreen = std::make_unique<Screens::ApplicationList>(this, settingsController); break;
case Apps::Clock:
currentScreen = std::make_unique<Screens::Clock>(this, dateTimeController, batteryController, bleController, notificationManager, settingsController, heartRateController);
currentScreen = std::make_unique<Screens::Clock>(this, dateTimeController, batteryController, bleController, notificationManager, settingsController, heartRateController, motionController);
onClockApp = true;
break;
case Apps::SysInfo: currentScreen = std::make_unique<Screens::SystemInfo>(this, dateTimeController, batteryController, brightnessController, bleController, watchdog); break;
@ -219,6 +223,7 @@ void DisplayApp::RunningState() {
case Apps::FirmwareValidation: currentScreen = std::make_unique<Screens::FirmwareValidation>(this, validator); break;
case Apps::Notifications: currentScreen = std::make_unique<Screens::Notifications>(this, notificationManager, systemTask.nimble().alertService(), Screens::Notifications::Modes::Normal); break;
case Apps::HeartRate: currentScreen = std::make_unique<Screens::HeartRate>(this, heartRateController); break;
case Apps::Motion: currentScreen = std::make_unique<Screens::Motion>(this, motionController); break;
}
nextApp = Apps::None;
}

View file

@ -27,6 +27,7 @@ namespace Pinetime {
class DateTime;
class NotificationManager;
class HeartRateController;
class MotionController;
}
namespace System {
@ -45,7 +46,8 @@ namespace Pinetime {
System::SystemTask &systemTask,
Pinetime::Controllers::NotificationManager& notificationManager,
Pinetime::Controllers::HeartRateController& heartRateController,
Controllers::Settings &settingsController
Controllers::Settings &settingsController,
Pinetime::Controllers::MotionController& motionController
);
void Start();
void PushMessage(Display::Messages msg);
@ -92,6 +94,7 @@ namespace Pinetime {
TouchModes touchMode = TouchModes::Gestures;
Pinetime::Controllers::HeartRateController& heartRateController;
Pinetime::Controllers::Settings& settingsController;
Pinetime::Controllers::MotionController& motionController;
};
}
}

View file

@ -13,7 +13,8 @@ DisplayApp::DisplayApp(Drivers::St7789 &lcd, Components::LittleVgl &lvgl, Driver
System::SystemTask &systemTask,
Pinetime::Controllers::NotificationManager& notificationManager,
Pinetime::Controllers::HeartRateController& heartRateController,
Pinetime::Controllers::Settings& settingsController):
Pinetime::Controllers::Settings& settingsController,
Pinetime::Controllers::MotionController& motionController):
lcd{lcd}, bleController{bleController} {
msgQueue = xQueueCreate(queueSize, itemSize);

View file

@ -16,6 +16,7 @@
#include <date/date.h>
#include <drivers/Watchdog.h>
#include <components/heartrate/HeartRateController.h>
#include <components/motion/MotionController.h>
#include <components/settings/Settings.h>
#include "TouchEvents.h"
#include "Apps.h"
@ -35,7 +36,8 @@ namespace Pinetime {
System::SystemTask &systemTask,
Pinetime::Controllers::NotificationManager& notificationManager,
Pinetime::Controllers::HeartRateController& heartRateController,
Pinetime::Controllers::Settings& settingsController);
Pinetime::Controllers::Settings& settingsController,
Pinetime::Controllers::MotionController& motionController);
void Start();
void PushMessage(Pinetime::Applications::Display::Messages msg);

View file

@ -53,6 +53,7 @@ static lv_style_t style_table_cell;
static lv_style_t style_pad_small;
static lv_style_t style_bg_grad;
static lv_style_t style_lmeter;
static lv_style_t style_chart_serie;
static bool inited;
@ -260,6 +261,11 @@ static void basic_init(void)
lv_style_set_line_width(&style_lmeter, LV_STATE_DEFAULT, LV_DPX(10));
lv_style_set_scale_end_line_width(&style_lmeter, LV_STATE_DEFAULT, LV_DPX(7));
style_init_reset(&style_chart_serie);
lv_style_set_line_color(&style_chart_serie, LV_STATE_DEFAULT, LV_PINETIME_WHITE);
lv_style_set_line_width(&style_chart_serie, LV_STATE_DEFAULT, 4);
lv_style_set_size(&style_chart_serie, LV_STATE_DEFAULT, 4);
lv_style_set_bg_opa(&style_chart_serie, LV_STATE_DEFAULT, 0);
}
@ -466,6 +472,11 @@ static void theme_apply(lv_obj_t * obj, lv_theme_style_t name)
_lv_style_list_add_style(list, &style_lmeter);
break;
case LV_THEME_CHART:
lv_obj_clean_style_list(obj, LV_CHART_PART_SERIES);
list = lv_obj_get_style_list(obj, LV_CHART_PART_SERIES);
_lv_style_list_add_style(list, &style_btn);
_lv_style_list_add_style(list, &style_chart_serie);
default:
break;

View file

@ -45,7 +45,7 @@ bool ApplicationList::OnTouchEvent(Pinetime::Applications::TouchEvents event) {
std::unique_ptr<Screen> ApplicationList::CreateScreen1() {
std::array<Screens::Tile::Applications, 6> applications {
{{Symbols::clock, Apps::Clock},
{{Symbols::info, Apps::Notifications},
{Symbols::music, Apps::Music},
{Symbols::sun, Apps::Brightness},
{Symbols::list, Apps::SysInfo},
@ -64,7 +64,7 @@ std::unique_ptr<Screen> ApplicationList::CreateScreen2() {
{{Symbols::map, Apps::Navigation},
{Symbols::stopWatch, Apps::StopWatch},
{Symbols::paintbrush, Apps::Paint},
{Symbols::info, Apps::Notifications},
{Symbols::shoe, Apps::Motion},
{Symbols::paddle, Apps::Paddle},
{"2", Apps::Twos}
}

View file

@ -8,6 +8,7 @@
#include "NotificationIcon.h"
#include "Symbols.h"
#include "components/battery/BatteryController.h"
#include "components/motion/MotionController.h"
#include "components/ble/BleController.h"
#include "components/ble/NotificationManager.h"
#include "../DisplayApp.h"
@ -23,11 +24,13 @@ Clock::Clock(DisplayApp* app,
Controllers::Ble& bleController,
Controllers::NotificationManager& notificatioManager,
Controllers::Settings &settingsController,
Controllers::HeartRateController& heartRateController) : Screen(app),
Controllers::HeartRateController& heartRateController,
Controllers::MotionController& motionController) : Screen(app),
dateTimeController{dateTimeController}, batteryController{batteryController},
bleController{bleController}, notificatioManager{notificatioManager},
settingsController{settingsController},
heartRateController{heartRateController},
motionController{motionController},
screens{app,
settingsController.GetClockFace(),
{
@ -64,7 +67,7 @@ bool Clock::OnTouchEvent(Pinetime::Applications::TouchEvents event) {
}
std::unique_ptr<Screen> Clock::WatchFaceDigitalScreen() {
return std::make_unique<Screens::WatchFaceDigital>(app, dateTimeController, batteryController, bleController, notificatioManager, settingsController, heartRateController);
return std::make_unique<Screens::WatchFaceDigital>(app, dateTimeController, batteryController, bleController, notificatioManager, settingsController, heartRateController, motionController);
}
std::unique_ptr<Screen> Clock::WatchFaceAnalogScreen() {

View file

@ -17,6 +17,7 @@ namespace Pinetime {
class Battery;
class Ble;
class NotificationManager;
class MotionController;
}
namespace Applications {
@ -29,7 +30,8 @@ namespace Pinetime {
Controllers::Ble& bleController,
Controllers::NotificationManager& notificatioManager,
Controllers::Settings &settingsController,
Controllers::HeartRateController& heartRateController);
Controllers::HeartRateController& heartRateController,
Controllers::MotionController& motionController);
~Clock() override;
bool Refresh() override;
@ -44,6 +46,7 @@ namespace Pinetime {
Controllers::NotificationManager& notificatioManager;
Controllers::Settings& settingsController;
Controllers::HeartRateController& heartRateController;
Controllers::MotionController& motionController;
ScreenList<2> screens;

View file

@ -0,0 +1,59 @@
#include <libs/lvgl/lvgl.h>
#include "Motion.h"
#include "../DisplayApp.h"
using namespace Pinetime::Applications::Screens;
extern lv_font_t jetbrains_mono_extrabold_compressed;
extern lv_font_t jetbrains_mono_bold_20;
Motion::Motion(Pinetime::Applications::DisplayApp *app, Controllers::MotionController& motionController) : Screen(app), motionController{motionController} {
chart = lv_chart_create(lv_scr_act(), NULL);
lv_obj_set_size(chart, 240, 240);
lv_obj_align(chart, NULL, LV_ALIGN_IN_TOP_MID, 0, 0);
lv_chart_set_type(chart, LV_CHART_TYPE_LINE); /*Show lines and points too*/
//lv_chart_set_series_opa(chart, LV_OPA_70); /*Opacity of the data series*/
//lv_chart_set_series_width(chart, 4); /*Line width and point radious*/
lv_chart_set_range(chart, -1100, 1100);
lv_chart_set_update_mode(chart, LV_CHART_UPDATE_MODE_SHIFT);
lv_chart_set_point_count(chart, 10);
/*Add 3 data series*/
ser1 = lv_chart_add_series(chart, LV_COLOR_RED);
ser2 = lv_chart_add_series(chart, LV_COLOR_GREEN);
ser3 = lv_chart_add_series(chart, LV_COLOR_YELLOW);
lv_chart_init_points(chart, ser1, 0);
lv_chart_init_points(chart, ser2, 0);
lv_chart_init_points(chart, ser3, 0);
lv_chart_refresh(chart); /*Required after direct set*/
labelStep = lv_label_create(lv_scr_act(), NULL);
lv_obj_align(labelStep, chart, LV_ALIGN_IN_BOTTOM_LEFT, 0, 0);
lv_label_set_text(labelStep, "Steps: ");
labelStepValue = lv_label_create(lv_scr_act(), NULL);
lv_obj_align(labelStepValue, labelStep, LV_ALIGN_OUT_RIGHT_MID, 0, 0);
lv_label_set_text(labelStepValue, "-");
}
Motion::~Motion() {
lv_obj_clean(lv_scr_act());
}
bool Motion::Refresh() {
lv_chart_set_next(chart, ser1, motionController.X());
lv_chart_set_next(chart, ser2, motionController.Y());
lv_chart_set_next(chart, ser3, motionController.Z());
snprintf(nbStepsBuffer, nbStepsBufferSize, "%lu", motionController.NbSteps());
lv_label_set_text(labelStepValue, nbStepsBuffer);
return running;
}
bool Motion::OnButtonPushed() {
running = false;
return true;
}

View file

@ -0,0 +1,39 @@
#pragma once
#include <cstdint>
#include <chrono>
#include "Screen.h"
#include <bits/unique_ptr.h>
#include <libs/lvgl/src/lv_core/lv_style.h>
#include <libs/lvgl/src/lv_core/lv_obj.h>
#include <components/motion/MotionController.h>
namespace Pinetime {
namespace Applications {
namespace Screens {
class Motion : public Screen{
public:
Motion(DisplayApp* app, Controllers::MotionController& motionController);
~Motion() override;
bool Refresh() override;
bool OnButtonPushed() override;
private:
Controllers::MotionController& motionController;
lv_obj_t * chart;
lv_chart_series_t * ser1;
lv_chart_series_t * ser2;
lv_chart_series_t * ser3;
lv_obj_t* labelStep;
lv_obj_t* labelStepValue;
static constexpr uint8_t nbStepsBufferSize = 9;
char nbStepsBuffer[nbStepsBufferSize+1];
bool running = true;
};
}
}
}

View file

@ -11,6 +11,7 @@
#include "components/ble/BleController.h"
#include "components/ble/NotificationManager.h"
#include "components/heartrate/HeartRateController.h"
#include "components/motion/MotionController.h"
#include "components/settings/Settings.h"
#include "../DisplayApp.h"
@ -23,11 +24,13 @@ WatchFaceDigital::WatchFaceDigital(DisplayApp* app,
Controllers::Ble& bleController,
Controllers::NotificationManager& notificatioManager,
Controllers::Settings &settingsController,
Controllers::HeartRateController& heartRateController): Screen(app), currentDateTime{{}},
Controllers::HeartRateController& heartRateController,
Controllers::MotionController& motionController) : Screen(app), currentDateTime{{}},
dateTimeController{dateTimeController}, batteryController{batteryController},
bleController{bleController}, notificatioManager{notificatioManager},
settingsController{settingsController},
heartRateController{heartRateController} {
heartRateController{heartRateController},
motionController{motionController} {
settingsController.SetClockFace(0);
displayedChar[0] = 0;
@ -236,7 +239,7 @@ bool WatchFaceDigital::Refresh() {
lv_obj_align(heartbeatBpm, heartbeatValue, LV_ALIGN_OUT_RIGHT_MID, 5, 0);
}
// TODO stepCount = stepController.GetValue();
stepCount = motionController.NbSteps();
if(stepCount.IsUpdated()) {
char stepBuffer[5];
sprintf(stepBuffer, "%lu", stepCount.Get());

View file

@ -15,6 +15,7 @@ namespace Pinetime {
class Ble;
class NotificationManager;
class HeartRateController;
class MotionController;
}
namespace Applications {
@ -28,7 +29,8 @@ namespace Pinetime {
Controllers::Ble& bleController,
Controllers::NotificationManager& notificatioManager,
Controllers::Settings &settingsController,
Controllers::HeartRateController& heartRateController);
Controllers::HeartRateController& heartRateController,
Controllers::MotionController& motionController);
~WatchFaceDigital() override;
bool Refresh() override;
@ -73,6 +75,7 @@ namespace Pinetime {
Controllers::NotificationManager& notificatioManager;
Controllers::Settings& settingsController;
Controllers::HeartRateController& heartRateController;
Controllers::MotionController& motionController;
bool running = true;

122
src/drivers/Bma421.cpp Normal file
View file

@ -0,0 +1,122 @@
#include <libraries/delay/nrf_delay.h>
#include <libraries/log/nrf_log.h>
#include "Bma421.h"
#include "TwiMaster.h"
#include <drivers/Bma421_C/bma423.h>
using namespace Pinetime::Drivers;
int8_t user_i2c_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t length, void *intf_ptr) {
auto bma421 = static_cast<Bma421*>(intf_ptr);
bma421->Read(reg_addr, reg_data, length);
return 0;
}
int8_t user_i2c_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t length, void *intf_ptr) {
auto bma421 = static_cast<Bma421*>(intf_ptr);
bma421->Write(reg_addr, reg_data, length);
return 0;
}
void user_delay(uint32_t period_us, void *intf_ptr) {
nrf_delay_us(period_us);
}
Bma421::Bma421(TwiMaster& twiMaster, uint8_t twiAddress) : twiMaster{twiMaster}, twiAddress{twiAddress} {
bma.intf = BMA4_I2C_INTF;
bma.bus_read = user_i2c_read;
bma.bus_write = user_i2c_write;
bma.variant = BMA42X_VARIANT;
bma.intf_ptr = this;
bma.delay_us = user_delay;
bma.read_write_len = 8;
accel_conf.odr = BMA4_OUTPUT_DATA_RATE_100HZ;
accel_conf.range = BMA4_ACCEL_RANGE_2G;
accel_conf.bandwidth = BMA4_ACCEL_NORMAL_AVG4;
accel_conf.perf_mode = BMA4_CIC_AVG_MODE;
}
void Bma421::Init() {
auto ret = bma4_soft_reset(&bma);
ASSERT(ret == BMA4_OK);
nrf_delay_ms(1);
ret = bma423_init(&bma);
NRF_LOG_INFO("RESET : %d", ret);
//ret = bma423_init(&bma);
//NRF_LOG_INFO("ID : %d", bma.chip_id);
ASSERT(ret == BMA4_OK);
ret = bma423_write_config_file(&bma);
ASSERT(ret == BMA4_OK);
bma4_set_interrupt_mode(BMA4_LATCH_MODE, &bma);
struct bma4_int_pin_config int_pin_config;
int_pin_config.edge_ctrl = BMA4_LEVEL_TRIGGER;
int_pin_config.lvl = BMA4_ACTIVE_LOW;
int_pin_config.od = BMA4_PUSH_PULL;
int_pin_config.output_en = BMA4_OUTPUT_ENABLE;
int_pin_config.input_en = BMA4_INPUT_DISABLE;
bma4_set_int_pin_config(&int_pin_config, BMA4_INTR1_MAP, &bma);
//ret = bma423_feature_enable(BMA423_STEP_CNTR | BMA423_STEP_ACT | BMA423_WRIST_WEAR | BMA423_SINGLE_TAP | BMA423_DOUBLE_TAP, 1, &bma);
ret = bma423_feature_enable(0xff, 1, &bma);
ASSERT(ret == BMA4_OK);
//ret = bma423_map_interrupt(BMA4_INTR1_MAP, BMA423_SINGLE_TAP_INT | BMA423_STEP_CNTR_INT | BMA423_ACTIVITY_INT | BMA423_WRIST_WEAR_INT | BMA423_DOUBLE_TAP_INT | BMA423_ANY_MOT_INT | BMA423_NO_MOT_INT| BMA423_ERROR_INT, 1,&bma);
ret = bma423_map_interrupt(BMA4_INTR1_MAP, BMA423_STEP_CNTR_INT, 1,&bma);
ASSERT(ret == BMA4_OK);
bma423_step_detector_enable(0, &bma);
bma423_any_no_mot_config motConfig;
motConfig.threshold = 0xaa;
motConfig.axes_en = 3;
motConfig.duration = 1;
bma423_set_any_mot_config(&motConfig, &bma);
ret = bma4_set_accel_enable(1, &bma);
ASSERT(ret == BMA4_OK);
ret = bma4_set_accel_config(&accel_conf, &bma);
ASSERT(ret == BMA4_OK);
}
void Bma421::Reset() {
uint8_t data = 0xb6;
twiMaster.Write(deviceAddress, 0x7E, &data, 1);
}
void Bma421::Read(uint8_t registerAddress, uint8_t *buffer, size_t size) {
twiMaster.Read(deviceAddress, registerAddress, buffer, size);
}
void Bma421::Write(uint8_t registerAddress, const uint8_t *data, size_t size) {
twiMaster.Write(deviceAddress, registerAddress, data, size);
}
Bma421::Values Bma421::Process() {
struct bma4_accel data;
bma4_read_accel_xyz(&data, &bma);
uint32_t steps = 0;
bma423_step_counter_output(&steps, &bma);
int32_t temperature;
bma4_get_temperature(&temperature, BMA4_DEG, &bma);
temperature = temperature / 1000;
uint8_t activity = 0;
bma423_activity_output(&activity, &bma);
NRF_LOG_INFO("MOTION : %d - %d/%d/%d", steps, data.x, data.y, data.z);
return {steps, data.x, data.y, data.z};
}

43
src/drivers/Bma421.h Normal file
View file

@ -0,0 +1,43 @@
#pragma once
#include <drivers/Bma421_C/bma4_defs.h>
namespace Pinetime {
namespace Drivers {
class TwiMaster;
class Bma421 {
public:
struct Values {
uint32_t steps;
int16_t x;
int16_t y;
int16_t z;
};
Bma421(TwiMaster& twiMaster, uint8_t twiAddress);
Bma421(const Bma421&) = delete;
Bma421& operator=(const Bma421&) = delete;
Bma421(Bma421&&) = delete;
Bma421& operator=(Bma421&&) = delete;
void Init();
void Reset();
Values Process();
void Read(uint8_t registerAddress, uint8_t *buffer, size_t size);
void Write(uint8_t registerAddress, const uint8_t *data, size_t size);
void OnIrq();
uint32_t GetNbInterrupts() const {return nbInterrupts;}
private:
TwiMaster& twiMaster;
uint8_t twiAddress;
struct bma4_dev bma;
struct bma4_accel_config accel_conf;
static constexpr uint8_t deviceAddress = 0x18;
uint32_t nbInterrupts = 0;
};
}
}

5689
src/drivers/Bma421_C/bma4.c Normal file

File diff suppressed because it is too large Load diff

2281
src/drivers/Bma421_C/bma4.h Normal file

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -26,6 +26,7 @@
#include <task.h>
#include <timers.h>
#include <drivers/Hrs3300.h>
#include <drivers/Bma421.h>
#include "components/battery/BatteryController.h"
#include "components/ble/BleController.h"
@ -60,6 +61,7 @@ static constexpr uint8_t pinLcdDataCommand = 18;
static constexpr uint8_t pinTwiScl = 7;
static constexpr uint8_t pinTwiSda = 6;
static constexpr uint8_t touchPanelTwiAddress = 0x15;
static constexpr uint8_t motionSensorTwiAddress = 0x18;
static constexpr uint8_t heartRateSensorTwiAddress = 0x44;
Pinetime::Drivers::SpiMaster spi{Pinetime::Drivers::SpiMaster::SpiModule::SPI0, {
@ -98,7 +100,7 @@ static constexpr bool isFactory = false;
Pinetime::Components::LittleVgl lvgl {lcd, touchPanel};
#endif
Pinetime::Drivers::Bma421 motionSensor{twiMaster, motionSensorTwiAddress};
Pinetime::Drivers::Hrs3300 heartRateSensor {twiMaster, heartRateSensorTwiAddress};
@ -257,7 +259,7 @@ int main(void) {
debounceTimer = xTimerCreate ("debounceTimer", 200, pdFALSE, (void *) 0, DebounceTimerCallback);
systemTask = std::make_unique<Pinetime::System::SystemTask>(spi, lcd, spiNorFlash, twiMaster, touchPanel, lvgl, batteryController, bleController,
dateTimeController, motorController, heartRateSensor, settingsController);
dateTimeController, motorController, heartRateSensor, motionSensor, settingsController);
systemTask->Start();
nimble_port_init();

View file

@ -43,13 +43,14 @@ SystemTask::SystemTask(Drivers::SpiMaster &spi, Drivers::St7789 &lcd,
Controllers::DateTime &dateTimeController,
Pinetime::Controllers::MotorController& motorController,
Pinetime::Drivers::Hrs3300& heartRateSensor,
Pinetime::Drivers::Bma421& motionSensor,
Controllers::Settings &settingsController) :
spi{spi}, lcd{lcd}, spiNorFlash{spiNorFlash},
twiMaster{twiMaster}, touchPanel{touchPanel}, lvgl{lvgl}, batteryController{batteryController},
heartRateController{*this},
bleController{bleController}, dateTimeController{dateTimeController},
watchdog{}, watchdogView{watchdog},
motorController{motorController}, heartRateSensor{heartRateSensor},
motorController{motorController}, heartRateSensor{heartRateSensor}, motionSensor{motionSensor},
settingsController{settingsController},
nimbleController(*this, bleController,dateTimeController, notificationManager, batteryController, spiNorFlash, heartRateController) {
systemTasksMsgQueue = xQueueCreate(10, 1);
@ -84,13 +85,14 @@ void SystemTask::Work() {
touchPanel.Init();
batteryController.Init();
motorController.Init();
motionSensor.Init();
settingsController.Init();
displayApp = std::make_unique<Pinetime::Applications::DisplayApp>(lcd, lvgl, touchPanel, batteryController, bleController,
dateTimeController, watchdogView, *this, notificationManager,
heartRateController, settingsController);
heartRateController, settingsController, motionController);
displayApp->Start();
batteryController.Update();
@ -132,8 +134,10 @@ void SystemTask::Work() {
#pragma clang diagnostic push
#pragma ide diagnostic ignored "EndlessLoop"
while(true) {
UpdateMotion();
uint8_t msg;
if (xQueueReceive(systemTasksMsgQueue, &msg, isSleeping ? 2500 : 1000)) {
if (xQueueReceive(systemTasksMsgQueue, &msg, 100)) {
batteryController.Update();
Messages message = static_cast<Messages >(msg);
switch(message) {
@ -230,6 +234,23 @@ void SystemTask::Work() {
// Clear diagnostic suppression
#pragma clang diagnostic pop
}
void SystemTask::UpdateMotion() {
if(isGoingToSleep or isWakingUp) return;
if(isSleeping)
twiMaster.Wakeup();
auto motionValues = motionSensor.Process();
if(isSleeping)
twiMaster.Sleep();
motionController.Update(motionValues.y,
motionValues.x,
motionValues.z,
motionValues.steps);
if (motionController.ShouldWakeUp(isSleeping)) {
GoToRunning();
}
}
void SystemTask::OnButtonPushed() {
if(isGoingToSleep) return;
@ -247,6 +268,7 @@ void SystemTask::OnButtonPushed() {
}
void SystemTask::GoToRunning() {
if(isGoingToSleep or (not isSleeping) or isWakingUp) return;
isWakingUp = true;
PushMessage(Messages::GoToRunning);
}

View file

@ -8,6 +8,8 @@
#include <heartratetask/HeartRateTask.h>
#include <components/heartrate/HeartRateController.h>
#include <components/settings/Settings.h>
#include <drivers/Bma421.h>
#include <components/motion/MotionController.h>
#include "SystemMonitor.h"
#include "components/battery/BatteryController.h"
@ -49,6 +51,7 @@ namespace Pinetime {
Controllers::DateTime &dateTimeController,
Pinetime::Controllers::MotorController& motorController,
Pinetime::Drivers::Hrs3300& heartRateSensor,
Pinetime::Drivers::Bma421& motionSensor,
Controllers::Settings &settingsController);
@ -87,9 +90,11 @@ namespace Pinetime {
Pinetime::Controllers::NotificationManager notificationManager;
Pinetime::Controllers::MotorController& motorController;
Pinetime::Drivers::Hrs3300& heartRateSensor;
Pinetime::Drivers::Bma421& motionSensor;
Pinetime::Controllers::Settings& settingsController;
Pinetime::Controllers::NimbleController nimbleController;
Controllers::BrightnessController brightnessController;
Pinetime::Controllers::MotionController motionController;
static constexpr uint8_t pinSpiSck = 2;
static constexpr uint8_t pinSpiMosi = 3;
@ -109,6 +114,7 @@ namespace Pinetime {
bool doNotGoToSleep = false;
void GoToRunning();
void UpdateMotion();
#if configUSE_TRACE_FACILITY == 1
SystemMonitor<FreeRtosMonitor> monitor;