double tap wakeup error fix

battery nonblocking read
main
Joaquim 2021-04-04 13:51:22 +07:00
parent 1d3742e14f
commit bb7531e208
7 changed files with 89 additions and 68 deletions

@ -1,16 +1,38 @@
#include "BatteryController.h" #include "BatteryController.h"
#include <hal/nrf_gpio.h> #include <hal/nrf_gpio.h>
#include <nrfx_saadc.h>
#include <libraries/log/nrf_log.h> #include <libraries/log/nrf_log.h>
#include <algorithm> #include <algorithm>
#include <math.h>
using namespace Pinetime::Controllers; using namespace Pinetime::Controllers;
#define SAMPLES_IN_BUFFER 1
static nrf_saadc_value_t m_buffer_pool[2][SAMPLES_IN_BUFFER];
static float voltage = 0.0f;
static int percentRemaining = -1;
void Battery::Init() { void Battery::Init() {
nrf_gpio_cfg_input(chargingPin, (nrf_gpio_pin_pull_t)GPIO_PIN_CNF_PULL_Pullup); nrf_gpio_cfg_input(chargingPin, (nrf_gpio_pin_pull_t)GPIO_PIN_CNF_PULL_Pullup);
nrf_gpio_cfg_input(powerPresentPin, (nrf_gpio_pin_pull_t)GPIO_PIN_CNF_PULL_Pullup); nrf_gpio_cfg_input(powerPresentPin, (nrf_gpio_pin_pull_t)GPIO_PIN_CNF_PULL_Pullup);
}
void Battery::Update() {
isCharging = !nrf_gpio_pin_read(chargingPin);
isPowerPresent = !nrf_gpio_pin_read(powerPresentPin);
// Non blocking read
SaadcInit();
nrfx_saadc_sample();
}
void Battery::SaadcInit() {
nrfx_saadc_config_t adcConfig = NRFX_SAADC_DEFAULT_CONFIG; nrfx_saadc_config_t adcConfig = NRFX_SAADC_DEFAULT_CONFIG;
nrfx_saadc_init(&adcConfig, SaadcEventHandler); APP_ERROR_CHECK(nrfx_saadc_init(&adcConfig, SaadcEventHandler));
nrf_saadc_channel_config_t adcChannelConfig = { nrf_saadc_channel_config_t adcChannelConfig = {
.resistor_p = NRF_SAADC_RESISTOR_DISABLED, .resistor_p = NRF_SAADC_RESISTOR_DISABLED,
.resistor_n = NRF_SAADC_RESISTOR_DISABLED, .resistor_n = NRF_SAADC_RESISTOR_DISABLED,
@ -18,32 +40,50 @@ void Battery::Init() {
.reference = NRF_SAADC_REFERENCE_INTERNAL, .reference = NRF_SAADC_REFERENCE_INTERNAL,
.acq_time = NRF_SAADC_ACQTIME_3US, .acq_time = NRF_SAADC_ACQTIME_3US,
.mode = NRF_SAADC_MODE_SINGLE_ENDED, .mode = NRF_SAADC_MODE_SINGLE_ENDED,
.burst = NRF_SAADC_BURST_DISABLED, .burst = NRF_SAADC_BURST_ENABLED,
.pin_p = batteryVoltageAdcInput, .pin_p = batteryVoltageAdcInput,
.pin_n = NRF_SAADC_INPUT_DISABLED .pin_n = NRF_SAADC_INPUT_DISABLED
}; };
nrfx_saadc_channel_init(0, &adcChannelConfig); APP_ERROR_CHECK(nrfx_saadc_channel_init(0, &adcChannelConfig));
APP_ERROR_CHECK(nrfx_saadc_buffer_convert(m_buffer_pool[0],SAMPLES_IN_BUFFER));
APP_ERROR_CHECK(nrfx_saadc_buffer_convert(m_buffer_pool[1],SAMPLES_IN_BUFFER));
} }
void Battery::Update() { void Battery::SaadcEventHandler(nrfx_saadc_evt_t const * p_event) {
isCharging = !nrf_gpio_pin_read(chargingPin); int avg_sample = 0;
isPowerPresent = !nrf_gpio_pin_read(powerPresentPin); int i = 0;
nrf_saadc_value_t value = 0; const float battery_max = 4.18; //maximum voltage of battery ( max charging voltage is 4.21 )
nrfx_saadc_sample_convert(0, &value); const float battery_min = 3.20; //minimum voltage of battery before shutdown ( depends on the battery )
if (p_event->type == NRFX_SAADC_EVT_DONE) {
APP_ERROR_CHECK(nrfx_saadc_buffer_convert(p_event->data.done.p_buffer, SAMPLES_IN_BUFFER));
for (i = 0; i < SAMPLES_IN_BUFFER; i++) {
avg_sample += p_event->data.done.p_buffer[i]; // take N samples in a row
}
avg_sample /= i; // average all the samples out
voltage = (static_cast<float>(avg_sample) * 2.04f) / (1024 / 3.0f);
voltage = roundf(voltage * 100) / 100;
percentRemaining = static_cast<int>(((voltage - battery_min) / (battery_max - battery_min)) * 100);
// see https://forum.pine64.org/showthread.php?tid=8147
voltage = (value * 2.0f) / (1024/3.0f);
int percentRemaining = ((voltage - 3.55f)*100.0f)*3.9f;
percentRemaining = std::max(percentRemaining, 0); percentRemaining = std::max(percentRemaining, 0);
percentRemaining = std::min(percentRemaining, 100); percentRemaining = std::min(percentRemaining, 100);
percentRemainingBuffer.insert(percentRemaining); nrfx_saadc_uninit();
// NRF_LOG_INFO("BATTERY " NRF_LOG_FLOAT_MARKER " %% - " NRF_LOG_FLOAT_MARKER " v", NRF_LOG_FLOAT(percentRemaining), NRF_LOG_FLOAT(voltage)); }
// NRF_LOG_INFO("POWER Charging : %d - Power : %d", isCharging, isPowerPresent);
} }
void Battery::SaadcEventHandler(nrfx_saadc_evt_t const * event) {
int Battery::PercentRemaining() {
return percentRemaining;
}
float Battery::Voltage() {
return voltage;
} }

@ -6,44 +6,16 @@
namespace Pinetime { namespace Pinetime {
namespace Controllers { namespace Controllers {
/** A simple circular buffer that can be used to average
out the sensor values. The total capacity of the CircBuffer
is given as the template parameter N.
*/
template <int N>
class CircBuffer {
public:
CircBuffer() : arr{}, sz{}, cap{N}, head{} {}
/**
insert member function overwrites the next data to the current
HEAD and moves the HEAD to the newly inserted value.
*/
void insert(const int num) {
head %= cap;
arr[head++] = num;
if (sz != cap) {
sz++;
}
}
int GetAverage() const {
int sum = std::accumulate(arr.begin(), arr.end(), 0);
return (sum / sz);
}
private:
std::array<int, N> arr; /**< internal array used to store the values*/
uint8_t sz; /**< The current size of the array.*/
uint8_t cap; /**< Total capacity of the CircBuffer.*/
uint8_t head; /**< The current head of the CircBuffer*/
};
class Battery { class Battery {
public: public:
void Init(); void Init();
void Update(); void Update();
int PercentRemaining() const { return percentRemainingBuffer.GetAverage(); }
float Voltage() const { return voltage; } int PercentRemaining();
float Voltage();
bool IsCharging() const { return isCharging; } bool IsCharging() const { return isCharging; }
bool IsPowerPresent() const { return isPowerPresent; } bool IsPowerPresent() const { return isPowerPresent; }
@ -51,12 +23,13 @@ namespace Pinetime {
static constexpr uint32_t chargingPin = 12; static constexpr uint32_t chargingPin = 12;
static constexpr uint32_t powerPresentPin = 19; static constexpr uint32_t powerPresentPin = 19;
static constexpr nrf_saadc_input_t batteryVoltageAdcInput = NRF_SAADC_INPUT_AIN7; static constexpr nrf_saadc_input_t batteryVoltageAdcInput = NRF_SAADC_INPUT_AIN7;
static constexpr uint8_t percentRemainingSamples = 10;
static void SaadcEventHandler(nrfx_saadc_evt_t const * p_event);
CircBuffer<percentRemainingSamples> percentRemainingBuffer {};
float voltage = 0.0f;
bool isCharging = false; bool isCharging = false;
bool isPowerPresent = false; bool isPowerPresent = false;
static void SaadcEventHandler(nrfx_saadc_evt_t const * p_event);
void SaadcInit();
}; };
} }
} }

@ -56,6 +56,8 @@ bool InfiniPaint::OnTouchEvent(Pinetime::Applications::TouchEvents event) {
std::fill(b, b + bufferSize, selectColor); std::fill(b, b + bufferSize, selectColor);
color++; color++;
return true; return true;
default:
return true;
} }
return true; return true;
} }

@ -117,7 +117,7 @@ bool Notifications::OnTouchEvent(Pinetime::Applications::TouchEvents event) {
} }
return true; return true;
case Pinetime::Applications::TouchEvents::LongTap: { case Pinetime::Applications::TouchEvents::LongTap: {
notificationManager.ToggleVibrations(); //notificationManager.ToggleVibrations();
return true; return true;
} }
default: default:
@ -214,6 +214,7 @@ namespace {
lv_obj_set_size(bt_accept, (LV_HOR_RES / 3) - 5, 80); lv_obj_set_size(bt_accept, (LV_HOR_RES / 3) - 5, 80);
label_accept = lv_label_create(bt_accept, nullptr); label_accept = lv_label_create(bt_accept, nullptr);
lv_label_set_text(label_accept, Symbols::phone); lv_label_set_text(label_accept, Symbols::phone);
lv_obj_set_style_local_bg_color(bt_accept, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_GREEN);
bt_reject = lv_btn_create(callBtnContainer, nullptr); bt_reject = lv_btn_create(callBtnContainer, nullptr);
bt_reject->user_data = this; bt_reject->user_data = this;
@ -221,6 +222,7 @@ namespace {
lv_obj_set_size(bt_reject, (LV_HOR_RES / 3) - 5, 80); lv_obj_set_size(bt_reject, (LV_HOR_RES / 3) - 5, 80);
label_reject = lv_label_create(bt_reject, nullptr); label_reject = lv_label_create(bt_reject, nullptr);
lv_label_set_text(label_reject, Symbols::phoneSlash); lv_label_set_text(label_reject, Symbols::phoneSlash);
lv_obj_set_style_local_bg_color(bt_reject, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_RED);
bt_mute = lv_btn_create(callBtnContainer, nullptr); bt_mute = lv_btn_create(callBtnContainer, nullptr);
bt_mute->user_data = this; bt_mute->user_data = this;
@ -228,6 +230,7 @@ namespace {
lv_obj_set_size(bt_mute, (LV_HOR_RES / 3) - 5, 80); lv_obj_set_size(bt_mute, (LV_HOR_RES / 3) - 5, 80);
label_mute = lv_label_create(bt_mute, nullptr); label_mute = lv_label_create(bt_mute, nullptr);
lv_label_set_text(label_mute, Symbols::volumMute); lv_label_set_text(label_mute, Symbols::volumMute);
lv_obj_set_style_local_bg_color(bt_mute, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_GRAY);
} }
break; break;
} }

@ -10,6 +10,7 @@ using namespace Pinetime::Drivers;
TwiMaster::TwiMaster(const Modules module, const Parameters& params) : module{module}, params{params} { TwiMaster::TwiMaster(const Modules module, const Parameters& params) : module{module}, params{params} {
mutex = xSemaphoreCreateBinary(); mutex = xSemaphoreCreateBinary();
ASSERT(mutex != NULL);
} }
void TwiMaster::Init() { void TwiMaster::Init() {
@ -61,9 +62,11 @@ void TwiMaster::Init() {
} }
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); // this is causing an error when came from sleep
//xSemaphoreTake(mutex, portMAX_DELAY);
auto ret = ReadWithRetry(deviceAddress, registerAddress, data, size); auto ret = ReadWithRetry(deviceAddress, registerAddress, data, size);
xSemaphoreGive(mutex); //xSemaphoreGive(mutex);
return ret; return ret;
} }

@ -74,7 +74,7 @@ typedef int16_t lv_coord_t;
#define LV_MEM_CUSTOM 0 #define LV_MEM_CUSTOM 0
#if LV_MEM_CUSTOM == 0 #if LV_MEM_CUSTOM == 0
/* Size of the memory used by `lv_mem_alloc` in bytes (>= 2kB)*/ /* Size of the memory used by `lv_mem_alloc` in bytes (>= 2kB)*/
#define LV_MEM_SIZE (12U * 1024U) #define LV_MEM_SIZE (14U * 1024U)
/* Complier prefix for a big array declaration */ /* Complier prefix for a big array declaration */
#define LV_MEM_ATTR #define LV_MEM_ATTR

@ -148,8 +148,12 @@ void SystemTask::Work() {
break; break;
case Messages::GoToRunning: case Messages::GoToRunning:
spi.Wakeup(); spi.Wakeup();
//twiMaster.Wakeup();
//touchPanel.Wakeup(); // Double Tap needs the touch screen to be in normal mode
if ( settingsController.getWakeUpMode() != Pinetime::Controllers::Settings::WakeUpMode::DoubleTap ) {
twiMaster.Wakeup();
touchPanel.Wakeup();
}
nimbleController.StartAdvertising(); nimbleController.StartAdvertising();
xTimerStart(idleTimer, 0); xTimerStart(idleTimer, 0);
@ -212,12 +216,8 @@ void SystemTask::Work() {
// Double Tap needs the touch screen to be in normal mode // Double Tap needs the touch screen to be in normal mode
if ( settingsController.getWakeUpMode() != Pinetime::Controllers::Settings::WakeUpMode::DoubleTap ) { if ( settingsController.getWakeUpMode() != Pinetime::Controllers::Settings::WakeUpMode::DoubleTap ) {
//touchPanel.Sleep(); touchPanel.Sleep();
} twiMaster.Sleep();
// No Wake uo mode, we can put the twi to sleep
if ( settingsController.getWakeUpMode() == Pinetime::Controllers::Settings::WakeUpMode::None ) {
//twiMaster.Sleep();
} }
isSleeping = true; isSleeping = true;
@ -281,10 +281,10 @@ void SystemTask::OnTouchEvent() {
GoToRunning(); GoToRunning();
} else if( settingsController.getWakeUpMode() == Pinetime::Controllers::Settings::WakeUpMode::DoubleTap ) { } else if( settingsController.getWakeUpMode() == Pinetime::Controllers::Settings::WakeUpMode::DoubleTap ) {
// error // error
/*auto info = touchPanel.GetTouchInfo(); auto info = touchPanel.GetTouchInfo();
if( info.isTouch and info.gesture == Pinetime::Drivers::Cst816S::Gestures::DoubleTap ) { if( info.isTouch and info.gesture == Pinetime::Drivers::Cst816S::Gestures::DoubleTap ) {
GoToRunning(); GoToRunning();
}*/ }
} }
} }
} }