Merge pull request #263 from joaquimorg/0.16.0Update
Fix Issue #262 for 0.16.0 version
This commit is contained in:
commit
36e27842e1
|
@ -63,7 +63,7 @@
|
||||||
#define configTICK_RATE_HZ 1024
|
#define configTICK_RATE_HZ 1024
|
||||||
#define configMAX_PRIORITIES ( 3 )
|
#define configMAX_PRIORITIES ( 3 )
|
||||||
#define configMINIMAL_STACK_SIZE ( 120 )
|
#define configMINIMAL_STACK_SIZE ( 120 )
|
||||||
#define configTOTAL_HEAP_SIZE ( 1024*15 )
|
#define configTOTAL_HEAP_SIZE ( 1024*16 )
|
||||||
#define configMAX_TASK_NAME_LEN ( 4 )
|
#define configMAX_TASK_NAME_LEN ( 4 )
|
||||||
#define configUSE_16_BIT_TICKS 0
|
#define configUSE_16_BIT_TICKS 0
|
||||||
#define configIDLE_SHOULD_YIELD 1
|
#define configIDLE_SHOULD_YIELD 1
|
||||||
|
@ -96,7 +96,7 @@
|
||||||
#define configUSE_TIMERS 1
|
#define configUSE_TIMERS 1
|
||||||
#define configTIMER_TASK_PRIORITY ( 0 )
|
#define configTIMER_TASK_PRIORITY ( 0 )
|
||||||
#define configTIMER_QUEUE_LENGTH 32
|
#define configTIMER_QUEUE_LENGTH 32
|
||||||
#define configTIMER_TASK_STACK_DEPTH ( 200 )
|
#define configTIMER_TASK_STACK_DEPTH ( 300 )
|
||||||
|
|
||||||
/* Tickless Idle configuration. */
|
/* Tickless Idle configuration. */
|
||||||
#define configEXPECTED_IDLE_TIME_BEFORE_SLEEP 2
|
#define configEXPECTED_IDLE_TIME_BEFORE_SLEEP 2
|
||||||
|
|
|
@ -23,12 +23,20 @@ void Battery::Update() {
|
||||||
isCharging = !nrf_gpio_pin_read(chargingPin);
|
isCharging = !nrf_gpio_pin_read(chargingPin);
|
||||||
isPowerPresent = !nrf_gpio_pin_read(powerPresentPin);
|
isPowerPresent = !nrf_gpio_pin_read(powerPresentPin);
|
||||||
|
|
||||||
|
if ( isReading ) return;
|
||||||
// Non blocking read
|
// Non blocking read
|
||||||
SaadcInit();
|
samples = 0;
|
||||||
nrfx_saadc_sample();
|
isReading = true;
|
||||||
|
SaadcInit();
|
||||||
|
|
||||||
|
nrfx_saadc_sample();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Battery::adcCallbackStatic(nrfx_saadc_evt_t const *event) {
|
||||||
|
instance->SaadcEventHandler(event);
|
||||||
|
}
|
||||||
|
|
||||||
void Battery::SaadcInit() {
|
void Battery::SaadcInit() {
|
||||||
nrfx_saadc_config_t adcConfig = NRFX_SAADC_DEFAULT_CONFIG;
|
nrfx_saadc_config_t adcConfig = NRFX_SAADC_DEFAULT_CONFIG;
|
||||||
APP_ERROR_CHECK(nrfx_saadc_init(&adcConfig, adcCallbackStatic));
|
APP_ERROR_CHECK(nrfx_saadc_init(&adcConfig, adcCallbackStatic));
|
||||||
|
@ -68,10 +76,13 @@ void Battery::SaadcEventHandler(nrfx_saadc_evt_t const * p_event) {
|
||||||
|
|
||||||
percentRemainingBuffer.insert(percentRemaining);
|
percentRemainingBuffer.insert(percentRemaining);
|
||||||
|
|
||||||
nrfx_saadc_uninit();
|
samples++;
|
||||||
|
if ( samples > percentRemainingSamples ) {
|
||||||
|
nrfx_saadc_uninit();
|
||||||
|
isReading = false;
|
||||||
|
} else {
|
||||||
|
nrfx_saadc_sample();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Battery::adcCallbackStatic(nrfx_saadc_evt_t const *event) {
|
|
||||||
instance->SaadcEventHandler(event);
|
|
||||||
}
|
|
||||||
|
|
|
@ -52,13 +52,13 @@ namespace Pinetime {
|
||||||
float Voltage() const { return voltage; }
|
float Voltage() const { return voltage; }
|
||||||
|
|
||||||
bool IsCharging() const { return isCharging; }
|
bool IsCharging() const { return isCharging; }
|
||||||
bool IsPowerPresent() const { return isPowerPresent; }
|
bool IsPowerPresent() const { return isPowerPresent; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static Battery *instance;
|
static Battery *instance;
|
||||||
nrf_saadc_value_t saadc_value;
|
nrf_saadc_value_t saadc_value;
|
||||||
|
|
||||||
static constexpr uint8_t percentRemainingSamples = 10;
|
static constexpr uint8_t percentRemainingSamples = 5;
|
||||||
CircBuffer<percentRemainingSamples> percentRemainingBuffer {};
|
CircBuffer<percentRemainingSamples> percentRemainingBuffer {};
|
||||||
|
|
||||||
static constexpr uint32_t chargingPin = 12;
|
static constexpr uint32_t chargingPin = 12;
|
||||||
|
@ -74,6 +74,9 @@ namespace Pinetime {
|
||||||
|
|
||||||
void SaadcEventHandler(nrfx_saadc_evt_t const * p_event);
|
void SaadcEventHandler(nrfx_saadc_evt_t const * p_event);
|
||||||
static void adcCallbackStatic(nrfx_saadc_evt_t const *event);
|
static void adcCallbackStatic(nrfx_saadc_evt_t const *event);
|
||||||
|
|
||||||
|
bool isReading = false;
|
||||||
|
uint8_t samples = 0;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -24,6 +24,7 @@
|
||||||
#include "displayapp/screens/Twos.h"
|
#include "displayapp/screens/Twos.h"
|
||||||
#include "displayapp/screens/FlashLight.h"
|
#include "displayapp/screens/FlashLight.h"
|
||||||
#include "displayapp/screens/BatteryInfo.h"
|
#include "displayapp/screens/BatteryInfo.h"
|
||||||
|
|
||||||
#include "drivers/Cst816s.h"
|
#include "drivers/Cst816s.h"
|
||||||
#include "drivers/St7789.h"
|
#include "drivers/St7789.h"
|
||||||
#include "drivers/Watchdog.h"
|
#include "drivers/Watchdog.h"
|
||||||
|
@ -131,7 +132,7 @@ void DisplayApp::Refresh() {
|
||||||
// clockScreen.SetBleConnectionState(bleController.IsConnected() ? Screens::Clock::BleConnectionStates::Connected : Screens::Clock::BleConnectionStates::NotConnected);
|
// clockScreen.SetBleConnectionState(bleController.IsConnected() ? Screens::Clock::BleConnectionStates::Connected : Screens::Clock::BleConnectionStates::NotConnected);
|
||||||
break;
|
break;
|
||||||
case Messages::UpdateBatteryLevel:
|
case Messages::UpdateBatteryLevel:
|
||||||
// clockScreen.SetBatteryPercentRemaining(batteryController.PercentRemaining());
|
batteryController.Update();
|
||||||
break;
|
break;
|
||||||
case Messages::NewNotification:
|
case Messages::NewNotification:
|
||||||
LoadApp( Apps::NotificationsPreview, DisplayApp::FullRefreshDirections::Down );
|
LoadApp( Apps::NotificationsPreview, DisplayApp::FullRefreshDirections::Down );
|
||||||
|
@ -307,7 +308,6 @@ void DisplayApp::LoadApp(Apps app, DisplayApp::FullRefreshDirections direction)
|
||||||
case Apps::Motion:
|
case Apps::Motion:
|
||||||
currentScreen = std::make_unique<Screens::Motion>(this, motionController);
|
currentScreen = std::make_unique<Screens::Motion>(this, motionController);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
currentApp = app;
|
currentApp = app;
|
||||||
}
|
}
|
||||||
|
|
|
@ -246,10 +246,10 @@ static void basic_init(void)
|
||||||
lv_style_set_border_color(&style_table_cell, LV_STATE_DEFAULT, LV_PINETIME_GRAY);
|
lv_style_set_border_color(&style_table_cell, LV_STATE_DEFAULT, LV_PINETIME_GRAY);
|
||||||
lv_style_set_border_width(&style_table_cell, LV_STATE_DEFAULT, 1);
|
lv_style_set_border_width(&style_table_cell, LV_STATE_DEFAULT, 1);
|
||||||
lv_style_set_border_side(&style_table_cell, LV_STATE_DEFAULT, LV_BORDER_SIDE_FULL);
|
lv_style_set_border_side(&style_table_cell, LV_STATE_DEFAULT, LV_BORDER_SIDE_FULL);
|
||||||
lv_style_set_pad_left(&style_table_cell, LV_STATE_DEFAULT, 12);
|
lv_style_set_pad_left(&style_table_cell, LV_STATE_DEFAULT, 5);
|
||||||
lv_style_set_pad_right(&style_table_cell, LV_STATE_DEFAULT, 12);
|
lv_style_set_pad_right(&style_table_cell, LV_STATE_DEFAULT, 5);
|
||||||
lv_style_set_pad_top(&style_table_cell, LV_STATE_DEFAULT, 12);
|
lv_style_set_pad_top(&style_table_cell, LV_STATE_DEFAULT, 2);
|
||||||
lv_style_set_pad_bottom(&style_table_cell, LV_STATE_DEFAULT, 12);
|
lv_style_set_pad_bottom(&style_table_cell, LV_STATE_DEFAULT, 2);
|
||||||
|
|
||||||
style_init_reset(&style_pad_small);
|
style_init_reset(&style_pad_small);
|
||||||
lv_style_int_t pad_small_value = 10;
|
lv_style_int_t pad_small_value = 10;
|
||||||
|
@ -356,6 +356,7 @@ static void theme_apply(lv_obj_t * obj, lv_theme_style_t name)
|
||||||
lv_obj_clean_style_list(obj, LV_OBJ_PART_MAIN);
|
lv_obj_clean_style_list(obj, LV_OBJ_PART_MAIN);
|
||||||
list = lv_obj_get_style_list(obj, LV_OBJ_PART_MAIN);
|
list = lv_obj_get_style_list(obj, LV_OBJ_PART_MAIN);
|
||||||
_lv_style_list_add_style(list, &style_bg);
|
_lv_style_list_add_style(list, &style_bg);
|
||||||
|
_lv_style_list_add_style(list, &style_label_white);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case LV_THEME_OBJ:
|
case LV_THEME_OBJ:
|
||||||
|
@ -499,6 +500,7 @@ static void theme_apply(lv_obj_t * obj, lv_theme_style_t name)
|
||||||
for(; idx <= LV_TABLE_CELL_STYLE_CNT; idx ++) {
|
for(; idx <= LV_TABLE_CELL_STYLE_CNT; idx ++) {
|
||||||
list = lv_obj_get_style_list(obj, idx);
|
list = lv_obj_get_style_list(obj, idx);
|
||||||
_lv_style_list_add_style(list, &style_table_cell);
|
_lv_style_list_add_style(list, &style_table_cell);
|
||||||
|
_lv_style_list_add_style(list, &style_label_white);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
|
@ -84,7 +84,7 @@ void BatteryInfo::UpdateAnim() {
|
||||||
batteryPercent = batteryController.PercentRemaining();
|
batteryPercent = batteryController.PercentRemaining();
|
||||||
|
|
||||||
if ( batteryPercent >= 0 ) {
|
if ( batteryPercent >= 0 ) {
|
||||||
if ( batteryController.IsCharging() ) {
|
if ( batteryController.IsCharging() and batteryPercent < 100 ) {
|
||||||
animation +=1;
|
animation +=1;
|
||||||
if (animation >= 100) {
|
if (animation >= 100) {
|
||||||
animation = 0;
|
animation = 0;
|
||||||
|
@ -111,12 +111,17 @@ void BatteryInfo::UpdateScreen() {
|
||||||
batteryVoltage = batteryController.Voltage();
|
batteryVoltage = batteryController.Voltage();
|
||||||
|
|
||||||
if ( batteryPercent >= 0 ) {
|
if ( batteryPercent >= 0 ) {
|
||||||
if ( batteryController.IsCharging() ) {
|
if ( batteryController.IsCharging() and batteryPercent < 100 ) {
|
||||||
lv_obj_set_style_local_bg_color(charging_bar, LV_BAR_PART_INDIC , LV_STATE_DEFAULT, lv_color_hex(0xFF0000));
|
lv_obj_set_style_local_bg_color(charging_bar, LV_BAR_PART_INDIC , LV_STATE_DEFAULT, LV_COLOR_RED);
|
||||||
lv_label_set_text_static(status,"Battery charging");
|
lv_label_set_text_static(status,"Battery charging");
|
||||||
|
} else if ( batteryPercent == 100 ) {
|
||||||
|
lv_obj_set_style_local_bg_color(charging_bar, LV_BAR_PART_INDIC , LV_STATE_DEFAULT, LV_COLOR_BLUE);
|
||||||
|
lv_label_set_text_static(status,"Battery is fully charged");
|
||||||
|
} else if ( batteryPercent < 10 ) {
|
||||||
|
lv_obj_set_style_local_bg_color(charging_bar, LV_BAR_PART_INDIC , LV_STATE_DEFAULT, LV_COLOR_YELLOW);
|
||||||
|
lv_label_set_text_static(status,"Battery is low");
|
||||||
} else {
|
} else {
|
||||||
lv_obj_set_style_local_bg_color(charging_bar, LV_BAR_PART_INDIC , LV_STATE_DEFAULT, lv_color_hex(0x00FF00));
|
lv_obj_set_style_local_bg_color(charging_bar, LV_BAR_PART_INDIC , LV_STATE_DEFAULT, LV_COLOR_GREEN);
|
||||||
lv_label_set_text_static(status,"Battery discharging");
|
lv_label_set_text_static(status,"Battery discharging");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -116,7 +116,7 @@ void List::OnButtonEvent(lv_obj_t * object, lv_event_t event) {
|
||||||
if ( event == LV_EVENT_RELEASED ) {
|
if ( event == LV_EVENT_RELEASED ) {
|
||||||
for(int i = 0; i < MAXLISTITEMS; i++) {
|
for(int i = 0; i < MAXLISTITEMS; i++) {
|
||||||
if ( apps[i] != Apps::None && object == itemApps[i] ) {
|
if ( apps[i] != Apps::None && object == itemApps[i] ) {
|
||||||
app->StartApp(apps[i], DisplayApp::FullRefreshDirections::Down);
|
app->StartApp(apps[i], DisplayApp::FullRefreshDirections::Up);
|
||||||
running = false;
|
running = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,8 @@ SystemInfo::SystemInfo(Pinetime::Applications::DisplayApp *app,
|
||||||
[this]() -> std::unique_ptr<Screen> { return CreateScreen1(); },
|
[this]() -> std::unique_ptr<Screen> { return CreateScreen1(); },
|
||||||
[this]() -> std::unique_ptr<Screen> { return CreateScreen2(); },
|
[this]() -> std::unique_ptr<Screen> { return CreateScreen2(); },
|
||||||
[this]() -> std::unique_ptr<Screen> { return CreateScreen3(); },
|
[this]() -> std::unique_ptr<Screen> { return CreateScreen3(); },
|
||||||
[this]() -> std::unique_ptr<Screen> { return CreateScreen4(); }
|
[this]() -> std::unique_ptr<Screen> { return CreateScreen4(); },
|
||||||
|
[this]() -> std::unique_ptr<Screen> { return CreateScreen5(); }
|
||||||
},
|
},
|
||||||
Screens::ScreenListModes::UpDown
|
Screens::ScreenListModes::UpDown
|
||||||
} {}
|
} {}
|
||||||
|
@ -37,7 +38,9 @@ SystemInfo::~SystemInfo() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SystemInfo::Refresh() {
|
bool SystemInfo::Refresh() {
|
||||||
screens.Refresh();
|
if (running) {
|
||||||
|
screens.Refresh();
|
||||||
|
}
|
||||||
return running;
|
return running;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,27 +53,8 @@ bool SystemInfo::OnTouchEvent(Pinetime::Applications::TouchEvents event) {
|
||||||
return screens.OnTouchEvent(event);
|
return screens.OnTouchEvent(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SystemInfo::CreateContainer() {
|
|
||||||
|
|
||||||
if ( container1 ) {
|
|
||||||
container1 = lv_cont_create(lv_scr_act(), nullptr);
|
|
||||||
|
|
||||||
lv_obj_set_style_local_bg_opa(container1, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_TRANSP);
|
|
||||||
lv_obj_set_style_local_pad_all(container1, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, 10);
|
|
||||||
lv_obj_set_style_local_pad_inner(container1, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, 5);
|
|
||||||
lv_obj_set_style_local_border_width(container1, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, 0);
|
|
||||||
|
|
||||||
lv_obj_set_pos(container1, 0, 0);
|
|
||||||
lv_obj_set_width(container1, LV_HOR_RES - 10);
|
|
||||||
lv_obj_set_height(container1, LV_VER_RES);
|
|
||||||
lv_cont_set_layout(container1, LV_LAYOUT_CENTER);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::unique_ptr<Screen> SystemInfo::CreateScreen1() {
|
std::unique_ptr<Screen> SystemInfo::CreateScreen1() {
|
||||||
CreateContainer();
|
lv_obj_t * label = lv_label_create(lv_scr_act(), nullptr);
|
||||||
|
|
||||||
lv_obj_t * label = lv_label_create(container1, nullptr);
|
|
||||||
lv_label_set_recolor(label, true);
|
lv_label_set_recolor(label, true);
|
||||||
lv_label_set_text_fmt(label,
|
lv_label_set_text_fmt(label,
|
||||||
"#FFFF00 InfiniTime#\n\n"
|
"#FFFF00 InfiniTime#\n\n"
|
||||||
|
@ -81,12 +65,11 @@ std::unique_ptr<Screen> SystemInfo::CreateScreen1() {
|
||||||
Version::Major(), Version::Minor(), Version::Patch(),
|
Version::Major(), Version::Minor(), Version::Patch(),
|
||||||
__DATE__, __TIME__);
|
__DATE__, __TIME__);
|
||||||
lv_label_set_align(label, LV_LABEL_ALIGN_CENTER);
|
lv_label_set_align(label, LV_LABEL_ALIGN_CENTER);
|
||||||
return std::unique_ptr<Screen>(new Screens::Label(0, 4, app, label));
|
lv_obj_align(label, lv_scr_act(), LV_ALIGN_CENTER, 0, 0);
|
||||||
|
return std::unique_ptr<Screen>(new Screens::Label(0, 5, app, label));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<Screen> SystemInfo::CreateScreen2() {
|
std::unique_ptr<Screen> SystemInfo::CreateScreen2() {
|
||||||
CreateContainer();
|
|
||||||
|
|
||||||
auto batteryPercent = static_cast<uint8_t>(batteryController.PercentRemaining());
|
auto batteryPercent = static_cast<uint8_t>(batteryController.PercentRemaining());
|
||||||
float batteryVoltage = batteryController.Voltage();
|
float batteryVoltage = batteryController.Voltage();
|
||||||
|
|
||||||
|
@ -126,7 +109,7 @@ std::unique_ptr<Screen> SystemInfo::CreateScreen2() {
|
||||||
batteryVoltageBytes[0] = static_cast<uint8_t>((batteryVoltage - batteryVoltageBytes[1]) * 100); //remove whole part of flt and shift 2 places over
|
batteryVoltageBytes[0] = static_cast<uint8_t>((batteryVoltage - batteryVoltageBytes[1]) * 100); //remove whole part of flt and shift 2 places over
|
||||||
//
|
//
|
||||||
|
|
||||||
lv_obj_t * label = lv_label_create(container1, nullptr);
|
lv_obj_t * label = lv_label_create(lv_scr_act(), nullptr);
|
||||||
lv_label_set_recolor(label, true);
|
lv_label_set_recolor(label, true);
|
||||||
lv_label_set_text_fmt(label,
|
lv_label_set_text_fmt(label,
|
||||||
"#444444 Date# %02d/%02d/%04d\n"
|
"#444444 Date# %02d/%02d/%04d\n"
|
||||||
|
@ -140,6 +123,7 @@ std::unique_ptr<Screen> SystemInfo::CreateScreen2() {
|
||||||
uptimeDays, uptimeHours, uptimeMinutes, uptimeSeconds,
|
uptimeDays, uptimeHours, uptimeMinutes, uptimeSeconds,
|
||||||
batteryPercent, batteryVoltageBytes[1], batteryVoltageBytes[0], brightnessController.ToString(), resetReason
|
batteryPercent, batteryVoltageBytes[1], batteryVoltageBytes[0], brightnessController.ToString(), resetReason
|
||||||
);
|
);
|
||||||
|
lv_obj_align(label, lv_scr_act(), LV_ALIGN_CENTER, 0, 0);
|
||||||
return std::unique_ptr<Screen>(new Screens::Label(1, 4, app, label));
|
return std::unique_ptr<Screen>(new Screens::Label(1, 4, app, label));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -147,9 +131,8 @@ std::unique_ptr<Screen> SystemInfo::CreateScreen2() {
|
||||||
std::unique_ptr<Screen> SystemInfo::CreateScreen3() {
|
std::unique_ptr<Screen> SystemInfo::CreateScreen3() {
|
||||||
lv_mem_monitor_t mon;
|
lv_mem_monitor_t mon;
|
||||||
lv_mem_monitor(&mon);
|
lv_mem_monitor(&mon);
|
||||||
CreateContainer();
|
|
||||||
|
lv_obj_t * label = lv_label_create(lv_scr_act(), nullptr);
|
||||||
lv_obj_t * label = lv_label_create(container1, nullptr);
|
|
||||||
lv_label_set_recolor(label, true);
|
lv_label_set_recolor(label, true);
|
||||||
auto& bleAddr = bleController.Address();
|
auto& bleAddr = bleController.Address();
|
||||||
lv_label_set_text_fmt(label,
|
lv_label_set_text_fmt(label,
|
||||||
|
@ -169,13 +152,46 @@ std::unique_ptr<Screen> SystemInfo::CreateScreen3() {
|
||||||
(int)mon.free_biggest_size,
|
(int)mon.free_biggest_size,
|
||||||
0
|
0
|
||||||
);
|
);
|
||||||
|
lv_obj_align(label, lv_scr_act(), LV_ALIGN_CENTER, 0, 0);
|
||||||
return std::unique_ptr<Screen>(new Screens::Label(2, 4, app, label));
|
return std::unique_ptr<Screen>(new Screens::Label(2, 5, app, label));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool sortById(const TaskStatus_t &lhs, const TaskStatus_t &rhs) { return lhs.xTaskNumber < rhs.xTaskNumber; }
|
||||||
|
|
||||||
std::unique_ptr<Screen> SystemInfo::CreateScreen4() {
|
std::unique_ptr<Screen> SystemInfo::CreateScreen4() {
|
||||||
CreateContainer();
|
TaskStatus_t tasksStatus[7];
|
||||||
lv_obj_t * label = lv_label_create(container1, nullptr);
|
lv_obj_t * infoTask = lv_table_create(lv_scr_act(), NULL);
|
||||||
|
lv_table_set_col_cnt(infoTask, 3);
|
||||||
|
lv_table_set_row_cnt(infoTask, 8);
|
||||||
|
lv_obj_set_pos(infoTask, 10, 10);
|
||||||
|
|
||||||
|
lv_table_set_cell_value(infoTask, 0, 0, "#");
|
||||||
|
lv_table_set_col_width(infoTask, 0, 50);
|
||||||
|
lv_table_set_cell_value(infoTask, 0, 1, "Task");
|
||||||
|
lv_table_set_col_width(infoTask, 1, 80);
|
||||||
|
lv_table_set_cell_value(infoTask, 0, 2, "Free");
|
||||||
|
lv_table_set_col_width(infoTask, 2, 90);
|
||||||
|
|
||||||
|
auto nb = uxTaskGetSystemState(tasksStatus, 7, nullptr);
|
||||||
|
std::sort(tasksStatus, tasksStatus + nb, sortById);
|
||||||
|
for (uint8_t i = 0; i < nb; i++) {
|
||||||
|
|
||||||
|
lv_table_set_cell_value(infoTask, i + 1, 0, std::to_string(tasksStatus[i].xTaskNumber).c_str());
|
||||||
|
lv_table_set_cell_value(infoTask, i + 1, 1, tasksStatus[i].pcTaskName);
|
||||||
|
if (tasksStatus[i].usStackHighWaterMark < 20) {
|
||||||
|
std::string str1 = std::to_string(tasksStatus[i].usStackHighWaterMark) + " low";
|
||||||
|
lv_table_set_cell_value(infoTask, i + 1, 2, str1.c_str());
|
||||||
|
} else {
|
||||||
|
lv_table_set_cell_value(infoTask, i + 1, 2, std::to_string(tasksStatus[i].usStackHighWaterMark).c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return std::unique_ptr<Screen>(new Screens::Label(3, 5, app, infoTask));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<Screen> SystemInfo::CreateScreen5() {
|
||||||
|
lv_obj_t * label = lv_label_create(lv_scr_act(), nullptr);
|
||||||
lv_label_set_recolor(label, true);
|
lv_label_set_recolor(label, true);
|
||||||
lv_label_set_text_static(label,
|
lv_label_set_text_static(label,
|
||||||
"Software Licensed\n"
|
"Software Licensed\n"
|
||||||
|
@ -186,5 +202,6 @@ std::unique_ptr<Screen> SystemInfo::CreateScreen4() {
|
||||||
"#FFFF00 https://github.com/#\n"
|
"#FFFF00 https://github.com/#\n"
|
||||||
"#FFFF00 JF002/InfiniTime#");
|
"#FFFF00 JF002/InfiniTime#");
|
||||||
lv_label_set_align(label, LV_LABEL_ALIGN_CENTER);
|
lv_label_set_align(label, LV_LABEL_ALIGN_CENTER);
|
||||||
return std::unique_ptr<Screen>(new Screens::Label(3, 4, app, label));
|
lv_obj_align(label, lv_scr_act(), LV_ALIGN_CENTER, 0, 0);
|
||||||
|
return std::unique_ptr<Screen>(new Screens::Label(4, 5, app, label));
|
||||||
}
|
}
|
|
@ -35,21 +35,19 @@ namespace Pinetime {
|
||||||
private:
|
private:
|
||||||
bool running = true;
|
bool running = true;
|
||||||
|
|
||||||
lv_obj_t* container1;
|
|
||||||
|
|
||||||
Pinetime::Controllers::DateTime& dateTimeController;
|
Pinetime::Controllers::DateTime& dateTimeController;
|
||||||
Pinetime::Controllers::Battery& batteryController;
|
Pinetime::Controllers::Battery& batteryController;
|
||||||
Pinetime::Controllers::BrightnessController& brightnessController;
|
Pinetime::Controllers::BrightnessController& brightnessController;
|
||||||
Pinetime::Controllers::Ble& bleController;
|
Pinetime::Controllers::Ble& bleController;
|
||||||
Pinetime::Drivers::WatchdogView& watchdog;
|
Pinetime::Drivers::WatchdogView& watchdog;
|
||||||
|
|
||||||
ScreenList<4> screens;
|
ScreenList<5> screens;
|
||||||
std::unique_ptr<Screen> CreateScreen1();
|
std::unique_ptr<Screen> CreateScreen1();
|
||||||
std::unique_ptr<Screen> CreateScreen2();
|
std::unique_ptr<Screen> CreateScreen2();
|
||||||
std::unique_ptr<Screen> CreateScreen3();
|
std::unique_ptr<Screen> CreateScreen3();
|
||||||
std::unique_ptr<Screen> CreateScreen4();
|
std::unique_ptr<Screen> CreateScreen4();
|
||||||
|
std::unique_ptr<Screen> CreateScreen5();
|
||||||
|
|
||||||
void CreateContainer();
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -128,7 +128,7 @@ bool Tile::Refresh() {
|
||||||
|
|
||||||
void Tile::OnObjectEvent(lv_obj_t *obj, lv_event_t event, uint32_t buttonId) {
|
void Tile::OnObjectEvent(lv_obj_t *obj, lv_event_t event, uint32_t buttonId) {
|
||||||
if(event == LV_EVENT_VALUE_CHANGED) {
|
if(event == LV_EVENT_VALUE_CHANGED) {
|
||||||
app->StartApp(apps[buttonId], DisplayApp::FullRefreshDirections::Down);
|
app->StartApp(apps[buttonId], DisplayApp::FullRefreshDirections::Up);
|
||||||
running = false;
|
running = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,28 +21,33 @@ Twos::Twos(Pinetime::Applications::DisplayApp *app) : Screen(app) {
|
||||||
lv_style_set_border_width(&style_cell1, LV_STATE_DEFAULT, 3);
|
lv_style_set_border_width(&style_cell1, LV_STATE_DEFAULT, 3);
|
||||||
lv_style_set_bg_opa(&style_cell1, LV_STATE_DEFAULT, LV_OPA_COVER);
|
lv_style_set_bg_opa(&style_cell1, LV_STATE_DEFAULT, LV_OPA_COVER);
|
||||||
lv_style_set_bg_color(&style_cell1, LV_STATE_DEFAULT, lv_color_hex(0xcdc0b4));
|
lv_style_set_bg_color(&style_cell1, LV_STATE_DEFAULT, lv_color_hex(0xcdc0b4));
|
||||||
|
lv_style_set_pad_top(&style_cell1, LV_STATE_DEFAULT, 25);
|
||||||
|
lv_style_set_text_color(&style_cell1, LV_STATE_DEFAULT, LV_COLOR_BLACK);
|
||||||
|
|
||||||
lv_style_set_border_color(&style_cell2, LV_STATE_DEFAULT, lv_color_hex(0xbbada0));
|
lv_style_set_border_color(&style_cell2, LV_STATE_DEFAULT, lv_color_hex(0xbbada0));
|
||||||
lv_style_set_border_width(&style_cell2, LV_STATE_DEFAULT, 3);
|
lv_style_set_border_width(&style_cell2, LV_STATE_DEFAULT, 3);
|
||||||
lv_style_set_bg_opa(&style_cell2, LV_STATE_DEFAULT, LV_OPA_COVER);
|
lv_style_set_bg_opa(&style_cell2, LV_STATE_DEFAULT, LV_OPA_COVER);
|
||||||
lv_style_set_bg_color(&style_cell2, LV_STATE_DEFAULT, lv_color_hex(0xefdfc6));
|
lv_style_set_bg_color(&style_cell2, LV_STATE_DEFAULT, lv_color_hex(0xefdfc6));
|
||||||
|
lv_style_set_pad_top(&style_cell2, LV_STATE_DEFAULT, 25);
|
||||||
|
lv_style_set_text_color(&style_cell2, LV_STATE_DEFAULT, LV_COLOR_BLACK);
|
||||||
|
|
||||||
lv_style_set_border_color(&style_cell3, LV_STATE_DEFAULT, lv_color_hex(0xbbada0));
|
lv_style_set_border_color(&style_cell3, LV_STATE_DEFAULT, lv_color_hex(0xbbada0));
|
||||||
lv_style_set_border_width(&style_cell3, LV_STATE_DEFAULT, 3);
|
lv_style_set_border_width(&style_cell3, LV_STATE_DEFAULT, 3);
|
||||||
lv_style_set_bg_opa(&style_cell3, LV_STATE_DEFAULT, LV_OPA_COVER);
|
lv_style_set_bg_opa(&style_cell3, LV_STATE_DEFAULT, LV_OPA_COVER);
|
||||||
lv_style_set_bg_color(&style_cell3, LV_STATE_DEFAULT, lv_color_hex(0xef9263));
|
lv_style_set_bg_color(&style_cell3, LV_STATE_DEFAULT, lv_color_hex(0xef9263));
|
||||||
|
lv_style_set_pad_top(&style_cell3, LV_STATE_DEFAULT, 25);
|
||||||
|
|
||||||
lv_style_set_border_color(&style_cell4, LV_STATE_DEFAULT, lv_color_hex(0xbbada0));
|
lv_style_set_border_color(&style_cell4, LV_STATE_DEFAULT, lv_color_hex(0xbbada0));
|
||||||
lv_style_set_border_width(&style_cell4, LV_STATE_DEFAULT, 3);
|
lv_style_set_border_width(&style_cell4, LV_STATE_DEFAULT, 3);
|
||||||
lv_style_set_bg_opa(&style_cell4, LV_STATE_DEFAULT, LV_OPA_COVER);
|
lv_style_set_bg_opa(&style_cell4, LV_STATE_DEFAULT, LV_OPA_COVER);
|
||||||
lv_style_set_bg_color(&style_cell4, LV_STATE_DEFAULT, lv_color_hex(0xf76142));
|
lv_style_set_bg_color(&style_cell4, LV_STATE_DEFAULT, lv_color_hex(0xf76142));
|
||||||
//lv_style_set_text_color(&style_cell4, LV_STATE_DEFAULT, LV_COLOR_WHITE);
|
lv_style_set_pad_top(&style_cell4, LV_STATE_DEFAULT, 25);
|
||||||
|
|
||||||
lv_style_set_border_color(&style_cell5, LV_STATE_DEFAULT, lv_color_hex(0xbbada0));
|
lv_style_set_border_color(&style_cell5, LV_STATE_DEFAULT, lv_color_hex(0xbbada0));
|
||||||
lv_style_set_border_width(&style_cell5, LV_STATE_DEFAULT, 3);
|
lv_style_set_border_width(&style_cell5, LV_STATE_DEFAULT, 3);
|
||||||
lv_style_set_bg_opa(&style_cell5, LV_STATE_DEFAULT, LV_OPA_COVER);
|
lv_style_set_bg_opa(&style_cell5, LV_STATE_DEFAULT, LV_OPA_COVER);
|
||||||
lv_style_set_bg_color(&style_cell5, LV_STATE_DEFAULT, lv_color_hex(0x007dc5));
|
lv_style_set_bg_color(&style_cell5, LV_STATE_DEFAULT, lv_color_hex(0x007dc5));
|
||||||
//lv_style_set_text_color(&style_cell5, LV_STATE_DEFAULT, LV_COLOR_WHITE);
|
lv_style_set_pad_top(&style_cell5, LV_STATE_DEFAULT, 25);
|
||||||
|
|
||||||
// format grid display
|
// format grid display
|
||||||
|
|
||||||
|
|
|
@ -227,13 +227,11 @@ bool WatchFaceDigital::Refresh() {
|
||||||
heartbeat = heartRateController.HeartRate();
|
heartbeat = heartRateController.HeartRate();
|
||||||
heartbeatRunning = heartRateController.State() != Controllers::HeartRateController::States::Stopped;
|
heartbeatRunning = heartRateController.State() != Controllers::HeartRateController::States::Stopped;
|
||||||
if(heartbeat.IsUpdated() || heartbeatRunning.IsUpdated()) {
|
if(heartbeat.IsUpdated() || heartbeatRunning.IsUpdated()) {
|
||||||
char heartbeatBuffer[4];
|
|
||||||
if(heartbeatRunning.Get())
|
if(heartbeatRunning.Get())
|
||||||
sprintf(heartbeatBuffer, "%d", heartbeat.Get());
|
lv_label_set_text_fmt(heartbeatValue, "%d", heartbeat.Get());
|
||||||
else
|
else
|
||||||
sprintf(heartbeatBuffer, "---");
|
lv_label_set_text_static(heartbeatValue, "---");
|
||||||
|
|
||||||
lv_label_set_text(heartbeatValue, heartbeatBuffer);
|
|
||||||
lv_obj_align(heartbeatIcon, lv_scr_act(), LV_ALIGN_IN_BOTTOM_LEFT, 5, -2);
|
lv_obj_align(heartbeatIcon, lv_scr_act(), LV_ALIGN_IN_BOTTOM_LEFT, 5, -2);
|
||||||
lv_obj_align(heartbeatValue, heartbeatIcon, LV_ALIGN_OUT_RIGHT_MID, 5, 0);
|
lv_obj_align(heartbeatValue, heartbeatIcon, LV_ALIGN_OUT_RIGHT_MID, 5, 0);
|
||||||
lv_obj_align(heartbeatBpm, heartbeatValue, LV_ALIGN_OUT_RIGHT_MID, 5, 0);
|
lv_obj_align(heartbeatBpm, heartbeatValue, LV_ALIGN_OUT_RIGHT_MID, 5, 0);
|
||||||
|
@ -242,12 +240,7 @@ bool WatchFaceDigital::Refresh() {
|
||||||
stepCount = motionController.NbSteps();
|
stepCount = motionController.NbSteps();
|
||||||
motionSensorOk = motionController.IsSensorOk();
|
motionSensorOk = motionController.IsSensorOk();
|
||||||
if(stepCount.IsUpdated() || motionSensorOk.IsUpdated()) {
|
if(stepCount.IsUpdated() || motionSensorOk.IsUpdated()) {
|
||||||
char stepBuffer[5];
|
lv_label_set_text_fmt(stepValue, "%lu", stepCount.Get());
|
||||||
if(motionSensorOk.Get())
|
|
||||||
sprintf(stepBuffer, "%lu", stepCount.Get());
|
|
||||||
else
|
|
||||||
sprintf(stepBuffer, "---", stepCount.Get());
|
|
||||||
lv_label_set_text(stepValue, stepBuffer);
|
|
||||||
lv_obj_align(stepValue, lv_scr_act(), LV_ALIGN_IN_BOTTOM_RIGHT, -5, -2);
|
lv_obj_align(stepValue, lv_scr_act(), LV_ALIGN_IN_BOTTOM_RIGHT, -5, -2);
|
||||||
lv_obj_align(stepIcon, stepValue, LV_ALIGN_OUT_LEFT_MID, -5, 0);
|
lv_obj_align(stepIcon, stepValue, LV_ALIGN_OUT_LEFT_MID, -5, 0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,7 @@ Bma421::Bma421(TwiMaster& twiMaster, uint8_t twiAddress) : twiMaster{twiMaster},
|
||||||
bma.variant = BMA42X_VARIANT;
|
bma.variant = BMA42X_VARIANT;
|
||||||
bma.intf_ptr = this;
|
bma.intf_ptr = this;
|
||||||
bma.delay_us = user_delay;
|
bma.delay_us = user_delay;
|
||||||
bma.read_write_len = 8;
|
bma.read_write_len = 16;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Bma421::Init() {
|
void Bma421::Init() {
|
||||||
|
|
|
@ -31,7 +31,8 @@ void Cst816S::Init() {
|
||||||
twiMaster.Read(twiAddress, 0x15, &dummy, 1);
|
twiMaster.Read(twiAddress, 0x15, &dummy, 1);
|
||||||
vTaskDelay(5);
|
vTaskDelay(5);
|
||||||
twiMaster.Read(twiAddress, 0xa7, &dummy, 1);
|
twiMaster.Read(twiAddress, 0xa7, &dummy, 1);
|
||||||
|
vTaskDelay(5);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
[2] EnConLR - Continuous operation can slide around
|
[2] EnConLR - Continuous operation can slide around
|
||||||
[1] EnConUD - Slide up and down to enable continuous operation
|
[1] EnConUD - Slide up and down to enable continuous operation
|
||||||
|
|
|
@ -53,7 +53,7 @@ namespace Pinetime {
|
||||||
static constexpr uint8_t touchStep = 6;
|
static constexpr uint8_t touchStep = 6;
|
||||||
static constexpr uint8_t gestureIndex = 1;
|
static constexpr uint8_t gestureIndex = 1;
|
||||||
|
|
||||||
uint8_t touchData[63];
|
uint8_t touchData[10];
|
||||||
TwiMaster& twiMaster;
|
TwiMaster& twiMaster;
|
||||||
uint8_t twiAddress;
|
uint8_t twiAddress;
|
||||||
};
|
};
|
||||||
|
|
|
@ -2,77 +2,167 @@
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <hal/nrf_gpio.h>
|
#include <hal/nrf_gpio.h>
|
||||||
#include <nrfx_log.h>
|
#include <nrfx_log.h>
|
||||||
#include <nrfx_twim.h>
|
|
||||||
#include <nrf_drv_twi.h>
|
|
||||||
using namespace Pinetime::Drivers;
|
using namespace Pinetime::Drivers;
|
||||||
|
|
||||||
// TODO use shortcut to automatically send STOP when receive LastTX, for example
|
// TODO use shortcut to automatically send STOP when receive LastTX, for example
|
||||||
// TODO use DMA/IRQ
|
// TODO use DMA/IRQ
|
||||||
|
|
||||||
TwiMaster::TwiMaster(const Modules module, const Parameters& params) : module{module}, params{params}, mutex{xSemaphoreCreateBinary()} {
|
TwiMaster::TwiMaster(const Modules module, const Parameters& params) : module{module}, params{params} {
|
||||||
ASSERT(mutex != nullptr);
|
mutex = xSemaphoreCreateBinary();
|
||||||
switch(module) {
|
|
||||||
case Modules::TWIM1:
|
|
||||||
default:
|
|
||||||
twim = NRFX_TWIM_INSTANCE(1);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TwiMaster::Init() {
|
void TwiMaster::Init() {
|
||||||
nrfx_twim_config_t config;
|
NRF_GPIO->PIN_CNF[params.pinScl] = ((uint32_t)GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos)
|
||||||
config.frequency = static_cast<nrf_twim_frequency_t>(params.frequency);
|
| ((uint32_t)GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos)
|
||||||
config.hold_bus_uninit = false;
|
| ((uint32_t)GPIO_PIN_CNF_PULL_Pullup << GPIO_PIN_CNF_PULL_Pos)
|
||||||
config.interrupt_priority = 0;
|
| ((uint32_t)GPIO_PIN_CNF_DRIVE_S0D1 << GPIO_PIN_CNF_DRIVE_Pos)
|
||||||
config.scl = params.pinScl;
|
| ((uint32_t)GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos);
|
||||||
config.sda = params.pinSda;
|
|
||||||
nrfx_twim_init(&twim,
|
NRF_GPIO->PIN_CNF[params.pinSda] = ((uint32_t)GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos)
|
||||||
&config,
|
| ((uint32_t)GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos)
|
||||||
nullptr,
|
| ((uint32_t)GPIO_PIN_CNF_PULL_Pullup << GPIO_PIN_CNF_PULL_Pos)
|
||||||
nullptr);
|
| ((uint32_t)GPIO_PIN_CNF_DRIVE_S0D1 << GPIO_PIN_CNF_DRIVE_Pos)
|
||||||
nrfx_twim_enable(&twim);
|
| ((uint32_t)GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos);
|
||||||
|
|
||||||
|
switch(module) {
|
||||||
|
case Modules::TWIM1: twiBaseAddress = NRF_TWIM1; break;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(static_cast<Frequencies>(params.frequency)) {
|
||||||
|
case Frequencies::Khz100 : twiBaseAddress->FREQUENCY = TWIM_FREQUENCY_FREQUENCY_K100; break;
|
||||||
|
case Frequencies::Khz250 : twiBaseAddress->FREQUENCY = TWIM_FREQUENCY_FREQUENCY_K250; break;
|
||||||
|
case Frequencies::Khz400 : twiBaseAddress->FREQUENCY = TWIM_FREQUENCY_FREQUENCY_K400; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
twiBaseAddress->PSEL.SCL = params.pinScl;
|
||||||
|
twiBaseAddress->PSEL.SDA = params.pinSda;
|
||||||
|
twiBaseAddress->EVENTS_LASTRX = 0;
|
||||||
|
twiBaseAddress->EVENTS_STOPPED = 0;
|
||||||
|
twiBaseAddress->EVENTS_LASTTX = 0;
|
||||||
|
twiBaseAddress->EVENTS_ERROR = 0;
|
||||||
|
twiBaseAddress->EVENTS_RXSTARTED = 0;
|
||||||
|
twiBaseAddress->EVENTS_SUSPENDED = 0;
|
||||||
|
twiBaseAddress->EVENTS_TXSTARTED = 0;
|
||||||
|
|
||||||
|
twiBaseAddress->ENABLE = (TWIM_ENABLE_ENABLE_Enabled << TWIM_ENABLE_ENABLE_Pos);
|
||||||
|
|
||||||
|
|
||||||
|
/* // IRQ
|
||||||
|
NVIC_ClearPendingIRQ(_IRQn);
|
||||||
|
NVIC_SetPriority(_IRQn, 2);
|
||||||
|
NVIC_EnableIRQ(_IRQn);
|
||||||
|
*/
|
||||||
|
|
||||||
xSemaphoreGive(mutex);
|
xSemaphoreGive(mutex);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TwiMaster::ErrorCodes TwiMaster::Read(uint8_t deviceAddress, uint8_t registerAddress, uint8_t *data, size_t size) {
|
TwiMaster::ErrorCodes TwiMaster::Read(uint8_t deviceAddress, uint8_t registerAddress, uint8_t *data, size_t size) {
|
||||||
xSemaphoreTake(mutex, portMAX_DELAY);
|
xSemaphoreTake(mutex, portMAX_DELAY);
|
||||||
TwiMaster::ErrorCodes ret;
|
auto ret = Write(deviceAddress, ®isterAddress, 1, false);
|
||||||
|
ret = Read(deviceAddress, data, size, true);
|
||||||
auto err = nrfx_twim_tx(&twim, deviceAddress, ®isterAddress, 1, false);
|
|
||||||
if(err != 0) {
|
|
||||||
return TwiMaster::ErrorCodes::TransactionFailed;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = nrfx_twim_rx(&twim, deviceAddress, data, size);
|
|
||||||
if(err != 0) {
|
|
||||||
return TwiMaster::ErrorCodes::TransactionFailed;
|
|
||||||
}
|
|
||||||
xSemaphoreGive(mutex);
|
xSemaphoreGive(mutex);
|
||||||
|
return ret;
|
||||||
return TwiMaster::ErrorCodes::NoError;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TwiMaster::ErrorCodes TwiMaster::Write(uint8_t deviceAddress, uint8_t registerAddress, const uint8_t *data, size_t size) {
|
TwiMaster::ErrorCodes TwiMaster::Write(uint8_t deviceAddress, uint8_t registerAddress, const uint8_t *data, size_t size) {
|
||||||
ASSERT(size <= maxDataSize);
|
ASSERT(size <= maxDataSize);
|
||||||
xSemaphoreTake(mutex, portMAX_DELAY);
|
xSemaphoreTake(mutex, portMAX_DELAY);
|
||||||
TwiMaster::ErrorCodes ret;
|
|
||||||
|
|
||||||
internalBuffer[0] = registerAddress;
|
internalBuffer[0] = registerAddress;
|
||||||
std::memcpy(internalBuffer+1, data, size);
|
std::memcpy(internalBuffer + 1, data, size);
|
||||||
auto err = nrfx_twim_tx(&twim, deviceAddress, internalBuffer , size+1, false);
|
auto ret = Write(deviceAddress, internalBuffer, size + 1, true);
|
||||||
if(err != 0){
|
xSemaphoreGive(mutex);
|
||||||
return TwiMaster::ErrorCodes::TransactionFailed;
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
TwiMaster::ErrorCodes TwiMaster::Read(uint8_t deviceAddress, uint8_t *buffer, size_t size, bool stop) {
|
||||||
|
twiBaseAddress->ADDRESS = deviceAddress;
|
||||||
|
twiBaseAddress->TASKS_RESUME = 0x1UL;
|
||||||
|
twiBaseAddress->RXD.PTR = (uint32_t)buffer;
|
||||||
|
twiBaseAddress->RXD.MAXCNT = size;
|
||||||
|
|
||||||
|
twiBaseAddress->TASKS_STARTRX = 1;
|
||||||
|
|
||||||
|
while(!twiBaseAddress->EVENTS_RXSTARTED && !twiBaseAddress->EVENTS_ERROR);
|
||||||
|
twiBaseAddress->EVENTS_RXSTARTED = 0x0UL;
|
||||||
|
|
||||||
|
txStartedCycleCount = DWT->CYCCNT;
|
||||||
|
uint32_t currentCycleCount;
|
||||||
|
while(!twiBaseAddress->EVENTS_LASTRX && !twiBaseAddress->EVENTS_ERROR) {
|
||||||
|
currentCycleCount = DWT->CYCCNT;
|
||||||
|
if ((currentCycleCount-txStartedCycleCount) > HwFreezedDelay) {
|
||||||
|
FixHwFreezed();
|
||||||
|
return ErrorCodes::TransactionFailed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
twiBaseAddress->EVENTS_LASTRX = 0x0UL;
|
||||||
|
|
||||||
|
if (stop || twiBaseAddress->EVENTS_ERROR) {
|
||||||
|
twiBaseAddress->TASKS_STOP = 0x1UL;
|
||||||
|
while(!twiBaseAddress->EVENTS_STOPPED);
|
||||||
|
twiBaseAddress->EVENTS_STOPPED = 0x0UL;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
twiBaseAddress->TASKS_SUSPEND = 0x1UL;
|
||||||
|
while(!twiBaseAddress->EVENTS_SUSPENDED);
|
||||||
|
twiBaseAddress->EVENTS_SUSPENDED = 0x0UL;
|
||||||
}
|
}
|
||||||
|
|
||||||
xSemaphoreGive(mutex);
|
if (twiBaseAddress->EVENTS_ERROR) {
|
||||||
return TwiMaster::ErrorCodes::NoError;
|
twiBaseAddress->EVENTS_ERROR = 0x0UL;
|
||||||
|
}
|
||||||
|
return ErrorCodes::NoError;
|
||||||
|
}
|
||||||
|
|
||||||
|
TwiMaster::ErrorCodes TwiMaster::Write(uint8_t deviceAddress, const uint8_t *data, size_t size, bool stop) {
|
||||||
|
twiBaseAddress->ADDRESS = deviceAddress;
|
||||||
|
twiBaseAddress->TASKS_RESUME = 0x1UL;
|
||||||
|
twiBaseAddress->TXD.PTR = (uint32_t)data;
|
||||||
|
twiBaseAddress->TXD.MAXCNT = size;
|
||||||
|
|
||||||
|
twiBaseAddress->TASKS_STARTTX = 1;
|
||||||
|
|
||||||
|
while(!twiBaseAddress->EVENTS_TXSTARTED && !twiBaseAddress->EVENTS_ERROR);
|
||||||
|
twiBaseAddress->EVENTS_TXSTARTED = 0x0UL;
|
||||||
|
|
||||||
|
txStartedCycleCount = DWT->CYCCNT;
|
||||||
|
uint32_t currentCycleCount;
|
||||||
|
while(!twiBaseAddress->EVENTS_LASTTX && !twiBaseAddress->EVENTS_ERROR) {
|
||||||
|
currentCycleCount = DWT->CYCCNT;
|
||||||
|
if ((currentCycleCount-txStartedCycleCount) > HwFreezedDelay) {
|
||||||
|
FixHwFreezed();
|
||||||
|
return ErrorCodes::TransactionFailed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
twiBaseAddress->EVENTS_LASTTX = 0x0UL;
|
||||||
|
|
||||||
|
if (stop || twiBaseAddress->EVENTS_ERROR) {
|
||||||
|
twiBaseAddress->TASKS_STOP = 0x1UL;
|
||||||
|
while(!twiBaseAddress->EVENTS_STOPPED);
|
||||||
|
twiBaseAddress->EVENTS_STOPPED = 0x0UL;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
twiBaseAddress->TASKS_SUSPEND = 0x1UL;
|
||||||
|
while(!twiBaseAddress->EVENTS_SUSPENDED);
|
||||||
|
twiBaseAddress->EVENTS_SUSPENDED = 0x0UL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (twiBaseAddress->EVENTS_ERROR) {
|
||||||
|
twiBaseAddress->EVENTS_ERROR = 0x0UL;
|
||||||
|
uint32_t error = twiBaseAddress->ERRORSRC;
|
||||||
|
twiBaseAddress->ERRORSRC = error;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ErrorCodes::NoError;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TwiMaster::Sleep() {
|
void TwiMaster::Sleep() {
|
||||||
nrfx_twim_disable(&twim);
|
while(twiBaseAddress->ENABLE != 0) {
|
||||||
nrfx_twim_uninit(&twim);
|
twiBaseAddress->ENABLE = (TWIM_ENABLE_ENABLE_Disabled << TWIM_ENABLE_ENABLE_Pos);
|
||||||
|
}
|
||||||
nrf_gpio_cfg_default(6);
|
nrf_gpio_cfg_default(6);
|
||||||
nrf_gpio_cfg_default(7);
|
nrf_gpio_cfg_default(7);
|
||||||
NRF_LOG_INFO("[TWIMASTER] Sleep");
|
NRF_LOG_INFO("[TWIMASTER] Sleep");
|
||||||
|
@ -82,3 +172,30 @@ void TwiMaster::Wakeup() {
|
||||||
Init();
|
Init();
|
||||||
NRF_LOG_INFO("[TWIMASTER] Wakeup");
|
NRF_LOG_INFO("[TWIMASTER] Wakeup");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Sometimes, the TWIM device just freeze and never set the event EVENTS_LASTTX.
|
||||||
|
* This method disable and re-enable the peripheral so that it works again.
|
||||||
|
* This is just a workaround, and it would be better if we could find a way to prevent
|
||||||
|
* this issue from happening.
|
||||||
|
* */
|
||||||
|
void TwiMaster::FixHwFreezed() {
|
||||||
|
NRF_LOG_INFO("I2C device frozen, reinitializing it!");
|
||||||
|
// Disable I²C
|
||||||
|
uint32_t twi_state = NRF_TWI1->ENABLE;
|
||||||
|
twiBaseAddress->ENABLE = TWIM_ENABLE_ENABLE_Disabled << TWI_ENABLE_ENABLE_Pos;
|
||||||
|
|
||||||
|
NRF_GPIO->PIN_CNF[params.pinScl] = ((uint32_t)GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos)
|
||||||
|
| ((uint32_t)GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos)
|
||||||
|
| ((uint32_t)GPIO_PIN_CNF_PULL_Pullup << GPIO_PIN_CNF_PULL_Pos)
|
||||||
|
| ((uint32_t)GPIO_PIN_CNF_DRIVE_S0S1 << GPIO_PIN_CNF_DRIVE_Pos)
|
||||||
|
| ((uint32_t)GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos);
|
||||||
|
|
||||||
|
NRF_GPIO->PIN_CNF[params.pinSda] = ((uint32_t)GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos)
|
||||||
|
| ((uint32_t)GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos)
|
||||||
|
| ((uint32_t)GPIO_PIN_CNF_PULL_Pullup << GPIO_PIN_CNF_PULL_Pos)
|
||||||
|
| ((uint32_t)GPIO_PIN_CNF_DRIVE_S0S1 << GPIO_PIN_CNF_DRIVE_Pos)
|
||||||
|
| ((uint32_t)GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos);
|
||||||
|
|
||||||
|
// Re-enable I²C
|
||||||
|
twiBaseAddress->ENABLE = twi_state;
|
||||||
|
}
|
|
@ -3,13 +3,13 @@
|
||||||
#include <semphr.h>
|
#include <semphr.h>
|
||||||
#include <drivers/include/nrfx_twi.h> // NRF_TWIM_Type
|
#include <drivers/include/nrfx_twi.h> // NRF_TWIM_Type
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <nrfx_twim.h>
|
|
||||||
|
|
||||||
namespace Pinetime {
|
namespace Pinetime {
|
||||||
namespace Drivers {
|
namespace Drivers {
|
||||||
class TwiMaster {
|
class TwiMaster {
|
||||||
public:
|
public:
|
||||||
enum class Modules { TWIM1 };
|
enum class Modules { TWIM1 };
|
||||||
|
enum class Frequencies {Khz100, Khz250, Khz400};
|
||||||
enum class ErrorCodes {NoError, TransactionFailed};
|
enum class ErrorCodes {NoError, TransactionFailed};
|
||||||
struct Parameters {
|
struct Parameters {
|
||||||
uint32_t frequency;
|
uint32_t frequency;
|
||||||
|
@ -27,13 +27,19 @@ namespace Pinetime {
|
||||||
void Wakeup();
|
void Wakeup();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
nrfx_twim_t twim;
|
|
||||||
|
ErrorCodes Read(uint8_t deviceAddress, uint8_t* buffer, size_t size, bool stop);
|
||||||
|
ErrorCodes Write(uint8_t deviceAddress, const uint8_t* data, size_t size, bool stop);
|
||||||
|
void FixHwFreezed();
|
||||||
|
NRF_TWIM_Type* twiBaseAddress;
|
||||||
|
SemaphoreHandle_t mutex;
|
||||||
const Modules module;
|
const Modules module;
|
||||||
const Parameters params;
|
const Parameters params;
|
||||||
SemaphoreHandle_t mutex;
|
static constexpr uint8_t maxDataSize{16};
|
||||||
static constexpr uint8_t maxDataSize{8};
|
|
||||||
static constexpr uint8_t registerSize{1};
|
static constexpr uint8_t registerSize{1};
|
||||||
uint8_t internalBuffer[maxDataSize + registerSize];
|
uint8_t internalBuffer[maxDataSize + registerSize];
|
||||||
|
uint32_t txStartedCycleCount = 0;
|
||||||
|
static constexpr uint32_t HwFreezedDelay{161000};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -98,7 +98,6 @@ void SystemTask::Work() {
|
||||||
heartRateController, settingsController, motionController);
|
heartRateController, settingsController, motionController);
|
||||||
displayApp->Start();
|
displayApp->Start();
|
||||||
|
|
||||||
batteryController.Update();
|
|
||||||
displayApp->PushMessage(Pinetime::Applications::Display::Messages::UpdateBatteryLevel);
|
displayApp->PushMessage(Pinetime::Applications::Display::Messages::UpdateBatteryLevel);
|
||||||
|
|
||||||
heartRateSensor.Init();
|
heartRateSensor.Init();
|
||||||
|
@ -106,7 +105,6 @@ void SystemTask::Work() {
|
||||||
heartRateApp = std::make_unique<Pinetime::Applications::HeartRateTask>(heartRateSensor, heartRateController);
|
heartRateApp = std::make_unique<Pinetime::Applications::HeartRateTask>(heartRateSensor, heartRateController);
|
||||||
heartRateApp->Start();
|
heartRateApp->Start();
|
||||||
|
|
||||||
|
|
||||||
nrf_gpio_cfg_sense_input(pinButton, (nrf_gpio_pin_pull_t)GPIO_PIN_CNF_PULL_Pulldown, (nrf_gpio_pin_sense_t)GPIO_PIN_CNF_SENSE_High);
|
nrf_gpio_cfg_sense_input(pinButton, (nrf_gpio_pin_pull_t)GPIO_PIN_CNF_PULL_Pulldown, (nrf_gpio_pin_sense_t)GPIO_PIN_CNF_SENSE_High);
|
||||||
nrf_gpio_cfg_output(15);
|
nrf_gpio_cfg_output(15);
|
||||||
nrf_gpio_pin_set(15);
|
nrf_gpio_pin_set(15);
|
||||||
|
@ -141,7 +139,14 @@ void SystemTask::Work() {
|
||||||
|
|
||||||
uint8_t msg;
|
uint8_t msg;
|
||||||
if (xQueueReceive(systemTasksMsgQueue, &msg, 100)) {
|
if (xQueueReceive(systemTasksMsgQueue, &msg, 100)) {
|
||||||
|
|
||||||
|
// call the battery controller or use the MSG in DisplayApp to get the battery status ???
|
||||||
|
// it is necessary to validate which is the most efficient
|
||||||
batteryController.Update();
|
batteryController.Update();
|
||||||
|
//displayApp->PushMessage(Pinetime::Applications::Display::Messages::UpdateBatteryLevel);
|
||||||
|
// analyze a more efficient way to do this refreshment
|
||||||
|
// this and the UpdateMotion(); can be called on a timer to be independent of the main process ???
|
||||||
|
|
||||||
Messages message = static_cast<Messages >(msg);
|
Messages message = static_cast<Messages >(msg);
|
||||||
switch(message) {
|
switch(message) {
|
||||||
case Messages::EnableSleeping:
|
case Messages::EnableSleeping:
|
||||||
|
|
Loading…
Reference in New Issue
Block a user