diff options
Diffstat (limited to 'src/components')
-rw-r--r-- | src/components/battery/BatteryController.cpp | 66 | ||||
-rw-r--r-- | src/components/battery/BatteryController.h | 79 | ||||
-rw-r--r-- | src/components/brightness/BrightnessController.cpp | 28 | ||||
-rw-r--r-- | src/components/brightness/BrightnessController.h | 4 | ||||
-rw-r--r-- | src/components/motor/MotorController.cpp | 7 | ||||
-rw-r--r-- | src/components/motor/MotorController.h | 3 | ||||
-rw-r--r-- | src/components/settings/Settings.cpp | 110 | ||||
-rw-r--r-- | src/components/settings/Settings.h | 87 |
8 files changed, 321 insertions, 63 deletions
diff --git a/src/components/battery/BatteryController.cpp b/src/components/battery/BatteryController.cpp index aaa245e4..4a7a2345 100644 --- a/src/components/battery/BatteryController.cpp +++ b/src/components/battery/BatteryController.cpp @@ -1,16 +1,38 @@ #include "BatteryController.h" #include <hal/nrf_gpio.h> +#include <nrfx_saadc.h> #include <libraries/log/nrf_log.h> #include <algorithm> +#include <math.h> using namespace Pinetime::Controllers; +Battery *Battery::instance = nullptr; + +Battery::Battery() { + instance = this; +} + void Battery::Init() { 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); +} + +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_init(&adcConfig, SaadcEventHandler); + APP_ERROR_CHECK(nrfx_saadc_init(&adcConfig, adcCallbackStatic)); + nrf_saadc_channel_config_t adcChannelConfig = { .resistor_p = NRF_SAADC_RESISTOR_DISABLED, .resistor_n = NRF_SAADC_RESISTOR_DISABLED, @@ -18,32 +40,38 @@ void Battery::Init() { .reference = NRF_SAADC_REFERENCE_INTERNAL, .acq_time = NRF_SAADC_ACQTIME_3US, .mode = NRF_SAADC_MODE_SINGLE_ENDED, - .burst = NRF_SAADC_BURST_DISABLED, + .burst = NRF_SAADC_BURST_ENABLED, .pin_p = batteryVoltageAdcInput, .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(&saadc_value, 1)); + } -void Battery::Update() { - isCharging = !nrf_gpio_pin_read(chargingPin); - isPowerPresent = !nrf_gpio_pin_read(powerPresentPin); +void Battery::SaadcEventHandler(nrfx_saadc_evt_t const * p_event) { - nrf_saadc_value_t value = 0; - nrfx_saadc_sample_convert(0, &value); + const float battery_max = 4.18; // maximum voltage of battery ( max charging voltage is 4.21 ) + const float battery_min = 3.20; // minimum voltage of battery before shutdown ( depends on the battery ) - // 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::min(percentRemaining, 100); + if (p_event->type == NRFX_SAADC_EVT_DONE) { + + APP_ERROR_CHECK(nrfx_saadc_buffer_convert(&saadc_value, 1)); - percentRemainingBuffer.insert(percentRemaining); + voltage = (static_cast<float>(p_event->data.done.p_buffer[0]) * 2.04f) / (1024 / 3.0f); + voltage = roundf(voltage * 100) / 100; -// 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); -} + percentRemaining = static_cast<int>(((voltage - battery_min) / (battery_max - battery_min)) * 100); + + percentRemaining = std::max(percentRemaining, 0); + percentRemaining = std::min(percentRemaining, 100); -void Battery::SaadcEventHandler(nrfx_saadc_evt_t const * event) { + percentRemainingBuffer.insert(percentRemaining); -}
\ No newline at end of file + nrfx_saadc_uninit(); + } + } + +void Battery::adcCallbackStatic(nrfx_saadc_evt_t const *event) { + instance->SaadcEventHandler(event); +} diff --git a/src/components/battery/BatteryController.h b/src/components/battery/BatteryController.h index 86250a57..2776687b 100644 --- a/src/components/battery/BatteryController.h +++ b/src/components/battery/BatteryController.h @@ -6,57 +6,74 @@ namespace Pinetime { 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++; + + /** 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); - } + 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*/ - }; + 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 { public: + + Battery(); + void Init(); void Update(); + int PercentRemaining() const { return percentRemainingBuffer.GetAverage(); } + float Voltage() const { return voltage; } + bool IsCharging() const { return isCharging; } bool IsPowerPresent() const { return isPowerPresent; } private: + static Battery *instance; + nrf_saadc_value_t saadc_value; + + static constexpr uint8_t percentRemainingSamples = 10; + CircBuffer<percentRemainingSamples> percentRemainingBuffer {}; + static constexpr uint32_t chargingPin = 12; static constexpr uint32_t powerPresentPin = 19; 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; + int percentRemaining = -1; + bool isCharging = false; bool isPowerPresent = false; + + void SaadcInit(); + + void SaadcEventHandler(nrfx_saadc_evt_t const * p_event); + static void adcCallbackStatic(nrfx_saadc_evt_t const *event); }; } }
\ No newline at end of file diff --git a/src/components/brightness/BrightnessController.cpp b/src/components/brightness/BrightnessController.cpp index 78c461d7..0d8f366a 100644 --- a/src/components/brightness/BrightnessController.cpp +++ b/src/components/brightness/BrightnessController.cpp @@ -1,5 +1,6 @@ #include "BrightnessController.h" #include <hal/nrf_gpio.h> +#include "displayapp/screens/Symbols.h" using namespace Pinetime::Controllers; @@ -68,3 +69,30 @@ void BrightnessController::Restore() { Set(backupLevel); } +void BrightnessController::Step() { + switch(level) { + case Levels::Low: Set(Levels::Medium); break; + case Levels::Medium: Set(Levels::High); break; + case Levels::High: Set(Levels::Low); break; + default: break; + } +} + +const char* BrightnessController::GetIcon() { + switch(level) { + case Levels::Medium: return Applications::Screens::Symbols::brightnessMedium; + case Levels::High: return Applications::Screens::Symbols::brightnessHigh; + default: break; + } + return Applications::Screens::Symbols::brightnessLow; +} + +const char* BrightnessController::ToString() { + switch(level) { + case Levels::Off: return "Off"; + case Levels::Low: return "Low"; + case Levels::Medium: return "Medium"; + case Levels::High: return "High"; + default : return "???"; + } +}
\ No newline at end of file diff --git a/src/components/brightness/BrightnessController.h b/src/components/brightness/BrightnessController.h index b8354ec0..efff7e81 100644 --- a/src/components/brightness/BrightnessController.h +++ b/src/components/brightness/BrightnessController.h @@ -13,10 +13,14 @@ namespace Pinetime { Levels Level() const; void Lower(); void Higher(); + void Step(); void Backup(); void Restore(); + const char* GetIcon(); + const char* ToString(); + private: static constexpr uint8_t pinLcdBacklight1 = 14; static constexpr uint8_t pinLcdBacklight2 = 22; diff --git a/src/components/motor/MotorController.cpp b/src/components/motor/MotorController.cpp index 7f53fbf7..345234b3 100644 --- a/src/components/motor/MotorController.cpp +++ b/src/components/motor/MotorController.cpp @@ -7,6 +7,8 @@ APP_TIMER_DEF(vibTimer); using namespace Pinetime::Controllers; +MotorController::MotorController( Controllers::Settings &settingsController ) : settingsController{settingsController} {} + void MotorController::Init() { nrf_gpio_cfg_output(pinMotor); nrf_gpio_pin_set(pinMotor); @@ -14,7 +16,10 @@ void MotorController::Init() { app_timer_create(&vibTimer, APP_TIMER_MODE_SINGLE_SHOT, vibrate); } -void MotorController::SetDuration(uint8_t motorDuration) { +void MotorController::SetDuration(uint8_t motorDuration) { + + if ( settingsController.GetVibrationStatus() == Controllers::Settings::Vibration::OFF ) return; + nrf_gpio_pin_clear(pinMotor); /* Start timer for motorDuration miliseconds and timer triggers vibrate() when it finishes*/ app_timer_start(vibTimer, APP_TIMER_TICKS(motorDuration), NULL); diff --git a/src/components/motor/MotorController.h b/src/components/motor/MotorController.h index bdc20c0c..2f2e0343 100644 --- a/src/components/motor/MotorController.h +++ b/src/components/motor/MotorController.h @@ -2,6 +2,7 @@ #include <cstdint> #include "app_timer.h" +#include "components/settings/Settings.h" namespace Pinetime { namespace Controllers { @@ -9,10 +10,12 @@ namespace Pinetime { class MotorController { public: + MotorController( Controllers::Settings &settingsController ); void Init(); void SetDuration(uint8_t motorDuration); private: + Controllers::Settings& settingsController; static void vibrate(void * p_context); }; } diff --git a/src/components/settings/Settings.cpp b/src/components/settings/Settings.cpp index 0c6cf610..454df577 100644 --- a/src/components/settings/Settings.cpp +++ b/src/components/settings/Settings.cpp @@ -1,16 +1,114 @@ #include "Settings.h" +#include <cstdlib> +#include <cstring> using namespace Pinetime::Controllers; +struct SettingsHeader { + uint8_t isActive; // 0xF1 = Block is active, 0xF0 = Block is inactive + uint16_t version; // Current version, to verify if the saved data is for the current Version +}; + +#define HEADER_SIZE sizeof(SettingsHeader) + + +Settings::Settings( Pinetime::Drivers::SpiNorFlash &spiNorFlash ) : spiNorFlash{spiNorFlash} {} -// TODO (team): -// Read and write the settings to Flash -// void Settings::Init() { - // default Clock face - clockFace = 0; - clockType = ClockType::H24; + // Load default settings from Flash + LoadSettingsFromFlash(); + +} + +void Settings::SaveSettings() { + + // verify if is necessary to save + if ( settingsChanged ) { + SaveSettingsToFlash(); + } + settingsChanged = false; +} + + +bool Settings::FindHeader() { + SettingsHeader settingsHeader; + uint8_t bufferHead[sizeof(settingsHeader)]; + + for (uint8_t block = 0; block < 10; block++) { + + spiNorFlash.Read( settingsBaseAddr + (block * 0x1000), bufferHead, sizeof(settingsHeader) ); + std::memcpy(&settingsHeader, bufferHead, sizeof(settingsHeader)); + if ( settingsHeader.isActive == 0xF1 && settingsHeader.version == settingsVersion ) { + settingsFlashBlock = block; + return true; + } + } + return false; +} + +void Settings::ReadSettingsData() { + uint8_t bufferSettings[sizeof(settings)]; + spiNorFlash.Read( settingsBaseAddr + (settingsFlashBlock * 0x1000) + HEADER_SIZE, bufferSettings, sizeof(settings) ); + std::memcpy(&settings, bufferSettings, sizeof(settings)); +} + +void Settings::EraseBlock() { + spiNorFlash.SectorErase(settingsBaseAddr + (settingsFlashBlock * 0x1000)); } +void Settings::SetHeader( bool state ) { + SettingsHeader settingsHeader; + uint8_t bufferHead[sizeof(settingsHeader)]; + settingsHeader.isActive = state ? 0xF1 : 0xF0; + settingsHeader.version = settingsVersion; + + std::memcpy(bufferHead, &settingsHeader, sizeof(settingsHeader)); + spiNorFlash.Write(settingsBaseAddr + (settingsFlashBlock * 0x1000), bufferHead, sizeof(settingsHeader)); + +} + +void Settings::SaveSettingsData() { + uint8_t bufferSettings[sizeof(settings)]; + std::memcpy(bufferSettings, &settings, sizeof(settings)); + spiNorFlash.Write(settingsBaseAddr + (settingsFlashBlock * 0x1000) + HEADER_SIZE, bufferSettings, sizeof(settings)); +} + +void Settings::LoadSettingsFromFlash() { + + if ( settingsFlashBlock == 99 ) { + // Find current Block, if can't find use default settings and set block to 0 ans save ! + if ( FindHeader() ) { + ReadSettingsData(); + } else { + SaveSettingsToFlash(); + } + } else { + // Read Settings from flash... + // never used :) + ReadSettingsData(); + } + +} + +void Settings::SaveSettingsToFlash() { + + // calculate where to save... + // mark current to inactive + // erase the new location and save + // set settingsFlashBlock + + // if first time hever, only saves to block 0 and set settingsFlashBlock + + if ( settingsFlashBlock != 99 ) { + SetHeader( false ); + } + + settingsFlashBlock++; + if ( settingsFlashBlock > 9 ) settingsFlashBlock = 0; + + EraseBlock(); + SetHeader( true ); + SaveSettingsData(); +} diff --git a/src/components/settings/Settings.h b/src/components/settings/Settings.h index fa67f35e..9cbbee62 100644 --- a/src/components/settings/Settings.h +++ b/src/components/settings/Settings.h @@ -1,29 +1,104 @@ #pragma once #include <cstdint> +#include "components/datetime/DateTimeController.h" +#include "components/brightness/BrightnessController.h" +#include "drivers/SpiNorFlash.h" +#include "drivers/Cst816s.h" namespace Pinetime { namespace Controllers { class Settings { public: enum class ClockType {H24, H12}; + enum class Vibration {ON, OFF}; + enum class WakeUpMode {None, SingleTap, DoubleTap, RaiseWrist}; + + Settings( Pinetime::Drivers::SpiNorFlash &spiNorFlash ); void Init(); + void SaveSettings(); - void SetClockFace( uint8_t face ) { clockFace = face; }; - uint8_t GetClockFace() { return clockFace; }; + void SetClockFace( uint8_t face ) { + if ( face != settings.clockFace ) settingsChanged = true; + settings.clockFace = face; + }; + uint8_t GetClockFace() const { return settings.clockFace; }; void SetAppMenu( uint8_t menu ) { appMenu = menu; }; uint8_t GetAppMenu() { return appMenu; }; - void SetClockType( ClockType clocktype ) { clockType = clocktype; }; - ClockType GetClockType() { return clockType; }; + void SetSettingsMenu( uint8_t menu ) { settingsMenu = menu; }; + uint8_t GetSettingsMenu() const { return settingsMenu; }; + + void SetClockType( ClockType clocktype ) { + if ( clocktype != settings.clockType ) settingsChanged = true; + settings.clockType = clocktype; + }; + ClockType GetClockType() const { return settings.clockType; }; + + void SetVibrationStatus( Vibration status ) { + if ( status != settings.vibrationStatus ) settingsChanged = true; + settings.vibrationStatus = status; + }; + Vibration GetVibrationStatus() const { return settings.vibrationStatus; }; + + void SetScreenTimeOut( uint32_t timeout ) { + if ( timeout != settings.screenTimeOut ) settingsChanged = true; + settings.screenTimeOut = timeout; + }; + uint32_t GetScreenTimeOut() const { return settings.screenTimeOut; }; + void setWakeUpMode( WakeUpMode wakeUp ) { + if ( wakeUp != settings.wakeUpMode ) settingsChanged = true; + settings.wakeUpMode = wakeUp; + }; + WakeUpMode getWakeUpMode() const { return settings.wakeUpMode; }; + + void SetBrightness( Controllers::BrightnessController::Levels level ) { + if ( level != settings.brightLevel ) settingsChanged = true; + settings.brightLevel = level; + }; + Controllers::BrightnessController::Levels GetBrightness() const { return settings.brightLevel; }; private: - uint8_t clockFace = 0; + + Pinetime::Drivers::SpiNorFlash& spiNorFlash; + struct SettingsData { + + ClockType clockType = ClockType::H24; + Vibration vibrationStatus = Vibration::ON; + + uint8_t clockFace = 0; + + uint32_t stepsGoal = 1000; + uint32_t screenTimeOut = 15000; + + WakeUpMode wakeUpMode = WakeUpMode::None; + + Controllers::BrightnessController::Levels brightLevel = Controllers::BrightnessController::Levels::Medium; + + }; + + SettingsData settings; + bool settingsChanged = false; + uint8_t appMenu = 0; + uint8_t settingsMenu = 0; + + // There are 10 blocks of reserved flash to save settings + // to minimize wear, the recording is done in a rotating way by the 10 blocks + uint8_t settingsFlashBlock = 99; // default to indicate it needs to find the active block + + static constexpr uint32_t settingsBaseAddr = 0x3F6000; // Flash Settings Location + static constexpr uint16_t settingsVersion = 0x0100; // Flash Settings Version - ClockType clockType = ClockType::H24; + bool FindHeader(); + void ReadSettingsData(); + void EraseBlock(); + void SetHeader( bool state ); + void SaveSettingsData(); + void LoadSettingsFromFlash(); + void SaveSettingsToFlash(); }; } |