diff options
| author | JF <jf@codingfield.com> | 2022-04-02 14:34:53 (GMT) |
|---|---|---|
| committer | Gitea <gitea@fake.local> | 2022-04-02 14:34:53 (GMT) |
| commit | 187ea0f06d93c7f7df5779cb321a28ad040234ee (patch) | |
| tree | 3d6d1b2f60573045734153d975e9b0aa1b327394 /src/components | |
| parent | adc7909c9823c5cd9fc9888a84e84f9182b9088f (diff) | |
| parent | b498e1d633522eed975d78b04508834b7a79befe (diff) | |
Merge branch 'develop' of JF/PineTime into master
Diffstat (limited to 'src/components')
| -rw-r--r-- | src/components/ble/AlertNotificationClient.cpp | 1 | ||||
| -rw-r--r-- | src/components/ble/BleController.cpp | 16 | ||||
| -rw-r--r-- | src/components/ble/BleController.h | 9 | ||||
| -rw-r--r-- | src/components/ble/DfuService.cpp | 1 | ||||
| -rw-r--r-- | src/components/ble/HeartRateService.cpp | 1 | ||||
| -rw-r--r-- | src/components/ble/MotionService.cpp | 1 | ||||
| -rw-r--r-- | src/components/ble/MusicService.cpp | 21 | ||||
| -rw-r--r-- | src/components/ble/NimbleController.cpp | 66 | ||||
| -rw-r--r-- | src/components/ble/NimbleController.h | 37 | ||||
| -rw-r--r-- | src/components/datetime/DateTimeController.cpp | 30 | ||||
| -rw-r--r-- | src/components/datetime/DateTimeController.h | 9 | ||||
| -rw-r--r-- | src/components/heartrate/Ppg.h | 2 | ||||
| -rw-r--r-- | src/components/motor/MotorController.h | 2 | ||||
| -rw-r--r-- | src/components/settings/Settings.cpp | 4 | ||||
| -rw-r--r-- | src/components/settings/Settings.h | 40 |
15 files changed, 189 insertions, 51 deletions
diff --git a/src/components/ble/AlertNotificationClient.cpp b/src/components/ble/AlertNotificationClient.cpp index 0f85087..335845e 100644 --- a/src/components/ble/AlertNotificationClient.cpp +++ b/src/components/ble/AlertNotificationClient.cpp @@ -2,6 +2,7 @@ #include <algorithm> #include "components/ble/NotificationManager.h" #include "systemtask/SystemTask.h" +#include <nrf_log.h> using namespace Pinetime::Controllers; constexpr ble_uuid16_t AlertNotificationClient::ansServiceUuid; diff --git a/src/components/ble/BleController.cpp b/src/components/ble/BleController.cpp index a80c971..b6b7383 100644 --- a/src/components/ble/BleController.cpp +++ b/src/components/ble/BleController.cpp @@ -2,6 +2,10 @@ using namespace Pinetime::Controllers; +bool Ble::IsConnected() const { + return isConnected; +} + void Ble::Connect() { isConnected = true; } @@ -10,6 +14,18 @@ void Ble::Disconnect() { isConnected = false; } +bool Ble::IsRadioEnabled() const { + return isRadioEnabled; +} + +void Ble::EnableRadio() { + isRadioEnabled = true; +} + +void Ble::DisableRadio() { + isRadioEnabled = false; +} + void Ble::StartFirmwareUpdate() { isFirmwareUpdating = true; } diff --git a/src/components/ble/BleController.h b/src/components/ble/BleController.h index 72b8766..675ede2 100644 --- a/src/components/ble/BleController.h +++ b/src/components/ble/BleController.h @@ -12,12 +12,14 @@ namespace Pinetime { enum class AddressTypes { Public, Random, RPA_Public, RPA_Random }; Ble() = default; - bool IsConnected() const { - return isConnected; - } + bool IsConnected() const; void Connect(); void Disconnect(); + bool IsRadioEnabled() const; + void EnableRadio(); + void DisableRadio(); + void StartFirmwareUpdate(); void StopFirmwareUpdate(); void FirmwareUpdateTotalBytes(uint32_t totalBytes); @@ -57,6 +59,7 @@ namespace Pinetime { private: bool isConnected = false; + bool isRadioEnabled = true; bool isFirmwareUpdating = false; uint32_t firmwareUpdateTotalBytes = 0; uint32_t firmwareUpdateCurrentBytes = 0; diff --git a/src/components/ble/DfuService.cpp b/src/components/ble/DfuService.cpp index 71dcc7e..cf99f01 100644 --- a/src/components/ble/DfuService.cpp +++ b/src/components/ble/DfuService.cpp @@ -3,6 +3,7 @@ #include "components/ble/BleController.h" #include "drivers/SpiNorFlash.h" #include "systemtask/SystemTask.h" +#include <nrf_log.h> using namespace Pinetime::Controllers; diff --git a/src/components/ble/HeartRateService.cpp b/src/components/ble/HeartRateService.cpp index f178af7..4824a6b 100644 --- a/src/components/ble/HeartRateService.cpp +++ b/src/components/ble/HeartRateService.cpp @@ -1,6 +1,7 @@ #include "components/ble/HeartRateService.h" #include "components/heartrate/HeartRateController.h" #include "systemtask/SystemTask.h" +#include <nrf_log.h> using namespace Pinetime::Controllers; diff --git a/src/components/ble/MotionService.cpp b/src/components/ble/MotionService.cpp index 6381915..87923c2 100644 --- a/src/components/ble/MotionService.cpp +++ b/src/components/ble/MotionService.cpp @@ -1,6 +1,7 @@ #include "components/ble/MotionService.h" #include "components/motion/MotionController.h" #include "systemtask/SystemTask.h" +#include <nrf_log.h> using namespace Pinetime::Controllers; diff --git a/src/components/ble/MusicService.cpp b/src/components/ble/MusicService.cpp index 3457ce4..c99aa1e 100644 --- a/src/components/ble/MusicService.cpp +++ b/src/components/ble/MusicService.cpp @@ -17,6 +17,7 @@ */ #include "components/ble/MusicService.h" #include "systemtask/SystemTask.h" +#include <cstring> namespace { // 0000yyxx-78fc-48fe-8e23-433b3a1942d0 @@ -47,6 +48,8 @@ namespace { constexpr ble_uuid128_t msRepeatCharUuid {CharUuid(0x0b, 0x00)}; constexpr ble_uuid128_t msShuffleCharUuid {CharUuid(0x0c, 0x00)}; + constexpr uint8_t MaxStringSize {40}; + int MusicCallback(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt* ctxt, void* arg) { return static_cast<Pinetime::Controllers::MusicService*>(arg)->OnCommand(conn_handle, attr_handle, ctxt); } @@ -125,9 +128,21 @@ void Pinetime::Controllers::MusicService::Init() { int Pinetime::Controllers::MusicService::OnCommand(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt* ctxt) { if (ctxt->op == BLE_GATT_ACCESS_OP_WRITE_CHR) { size_t notifSize = OS_MBUF_PKTLEN(ctxt->om); - char data[notifSize + 1]; - data[notifSize] = '\0'; - os_mbuf_copydata(ctxt->om, 0, notifSize, data); + size_t bufferSize = notifSize; + if (notifSize > MaxStringSize) { + bufferSize = MaxStringSize; + } + + char data[bufferSize + 1]; + os_mbuf_copydata(ctxt->om, 0, bufferSize, data); + + if (notifSize > bufferSize) { + data[bufferSize-1] = '.'; + data[bufferSize-2] = '.'; + data[bufferSize-3] = '.'; + } + data[bufferSize] = '\0'; + char* s = &data[0]; if (ble_uuid_cmp(ctxt->chr->uuid, &msArtistCharUuid.u) == 0) { artistName = s; diff --git a/src/components/ble/NimbleController.cpp b/src/components/ble/NimbleController.cpp index d8510bd..10eb429 100644 --- a/src/components/ble/NimbleController.cpp +++ b/src/components/ble/NimbleController.cpp @@ -2,6 +2,7 @@ #include <cstring> #include <hal/nrf_rtc.h> +#include <nrf_log.h> #define min // workaround: nimble's min/max macros conflict with libstdc++ #define max #include <host/ble_gap.h> @@ -23,14 +24,14 @@ using namespace Pinetime::Controllers; NimbleController::NimbleController(Pinetime::System::SystemTask& systemTask, - Pinetime::Controllers::Ble& bleController, + Ble& bleController, DateTime& dateTimeController, - Pinetime::Controllers::NotificationManager& notificationManager, - Controllers::Battery& batteryController, + NotificationManager& notificationManager, + Battery& batteryController, Pinetime::Drivers::SpiNorFlash& spiNorFlash, - Controllers::HeartRateController& heartRateController, - Controllers::MotionController& motionController, - Controllers::FS& fs) + HeartRateController& heartRateController, + MotionController& motionController, + FS& fs) : systemTask {systemTask}, bleController {bleController}, dateTimeController {dateTimeController}, @@ -76,6 +77,7 @@ int GAPEventCallback(struct ble_gap_event* event, void* arg) { void NimbleController::Init() { while (!ble_hs_synced()) { + vTaskDelay(10); } nptr = this; @@ -184,7 +186,9 @@ int NimbleController::OnGAPEvent(ble_gap_event* event) { case BLE_GAP_EVENT_ADV_COMPLETE: NRF_LOG_INFO("Advertising event : BLE_GAP_EVENT_ADV_COMPLETE"); NRF_LOG_INFO("reason=%d; status=%0X", event->adv_complete.reason, event->connect.status); - StartAdvertising(); + if (bleController.IsRadioEnabled() && !bleController.IsConnected()) { + StartAdvertising(); + } break; case BLE_GAP_EVENT_CONNECT: @@ -220,9 +224,11 @@ int NimbleController::OnGAPEvent(ble_gap_event* event) { currentTimeClient.Reset(); alertNotificationClient.Reset(); connectionHandle = BLE_HS_CONN_HANDLE_NONE; - bleController.Disconnect(); - fastAdvCount = 0; - StartAdvertising(); + if(bleController.IsConnected()) { + bleController.Disconnect(); + fastAdvCount = 0; + StartAdvertising(); + } break; case BLE_GAP_EVENT_CONN_UPDATE: @@ -278,7 +284,28 @@ int NimbleController::OnGAPEvent(ble_gap_event* event) { if (event->passkey.params.action == BLE_SM_IOACT_DISP) { struct ble_sm_io pkey = {0}; pkey.action = event->passkey.params.action; - pkey.passkey = ble_ll_rand() % 1000000; + + /* + * Passkey is a 6 digits code (1'000'000 possibilities). + * It is important every possible value has an equal probability + * of getting generated. Simply applying a modulo creates a bias + * since 2^32 is not a multiple of 1'000'000. + * To prevent that, we can reject values greater than 999'999. + * + * Rejecting values would happen a lot since 2^32-1 is way greater + * than 1'000'000. An optimisation is to use a multiple of 1'000'000. + * The greatest multiple of 1'000'000 lesser than 2^32-1 is + * 4'294'000'000. + * + * Great explanation at: + * https://research.kudelskisecurity.com/2020/07/28/the-definitive-guide-to-modulo-bias-and-how-to-avoid-it/ + */ + uint32_t passkey_rand; + do { + passkey_rand = ble_ll_rand(); + } while (passkey_rand > 4293999999); + pkey.passkey = passkey_rand % 1000000; + bleController.SetPairingKey(pkey.passkey); systemTask.PushMessage(Pinetime::System::Messages::OnPairing); ble_sm_inject_io(event->passkey.conn_handle, &pkey); @@ -376,6 +403,23 @@ void NimbleController::NotifyBatteryLevel(uint8_t level) { } } +void NimbleController::EnableRadio() { + bleController.EnableRadio(); + bleController.Disconnect(); + fastAdvCount = 0; + StartAdvertising(); +} + +void NimbleController::DisableRadio() { + bleController.DisableRadio(); + if (bleController.IsConnected()) { + ble_gap_terminate(connectionHandle, BLE_ERR_REM_USER_CONN_TERM); + bleController.Disconnect(); + } else { + ble_gap_adv_stop(); + } +} + void NimbleController::PersistBond(struct ble_gap_conn_desc& desc) { union ble_store_key key; union ble_store_value our_sec, peer_sec, peer_cccd_set[MYNEWT_VAL(BLE_STORE_MAX_CCCDS)] = {0}; diff --git a/src/components/ble/NimbleController.h b/src/components/ble/NimbleController.h index 2b300e6..ad19421 100644 --- a/src/components/ble/NimbleController.h +++ b/src/components/ble/NimbleController.h @@ -14,6 +14,7 @@ #include "components/ble/CurrentTimeService.h" #include "components/ble/DeviceInformationService.h" #include "components/ble/DfuService.h" +#include "components/ble/FSService.h" #include "components/ble/HeartRateService.h" #include "components/ble/ImmediateAlertService.h" #include "components/ble/MusicService.h" @@ -22,7 +23,6 @@ #include "components/ble/MotionService.h" #include "components/ble/weather/WeatherService.h" #include "components/fs/FS.h" -#include "components/ble/FSService.h" namespace Pinetime { namespace Drivers { @@ -42,27 +42,17 @@ namespace Pinetime { public: NimbleController(Pinetime::System::SystemTask& systemTask, - Pinetime::Controllers::Ble& bleController, + Ble& bleController, DateTime& dateTimeController, - Pinetime::Controllers::NotificationManager& notificationManager, - Controllers::Battery& batteryController, + NotificationManager& notificationManager, + Battery& batteryController, Pinetime::Drivers::SpiNorFlash& spiNorFlash, - Controllers::HeartRateController& heartRateController, - Controllers::MotionController& motionController, - Pinetime::Controllers::FS& fs); + HeartRateController& heartRateController, + MotionController& motionController, + FS& fs); void Init(); void StartAdvertising(); int OnGAPEvent(ble_gap_event* event); - - int OnDiscoveryEvent(uint16_t i, const ble_gatt_error* pError, const ble_gatt_svc* pSvc); - int OnCTSCharacteristicDiscoveryEvent(uint16_t connectionHandle, const ble_gatt_error* error, const ble_gatt_chr* characteristic); - int OnANSCharacteristicDiscoveryEvent(uint16_t connectionHandle, const ble_gatt_error* error, const ble_gatt_chr* characteristic); - int OnCurrentTimeReadResult(uint16_t connectionHandle, const ble_gatt_error* error, ble_gatt_attr* attribute); - int OnANSDescriptorDiscoveryEventCallback(uint16_t connectionHandle, - const ble_gatt_error* error, - uint16_t characteristicValueHandle, - const ble_gatt_dsc* descriptor); - void StartDiscovery(); Pinetime::Controllers::MusicService& music() { @@ -83,7 +73,10 @@ namespace Pinetime { void RestartFastAdv() { fastAdvCount = 0; - } + }; + + void EnableRadio(); + void DisableRadio(); private: void PersistBond(struct ble_gap_conn_desc& desc); @@ -91,12 +84,12 @@ namespace Pinetime { static constexpr const char* deviceName = "InfiniTime"; Pinetime::System::SystemTask& systemTask; - Pinetime::Controllers::Ble& bleController; + Ble& bleController; DateTime& dateTimeController; - Pinetime::Controllers::NotificationManager& notificationManager; + NotificationManager& notificationManager; Pinetime::Drivers::SpiNorFlash& spiNorFlash; - Pinetime::Controllers::FS& fs; - Pinetime::Controllers::DfuService dfuService; + FS& fs; + DfuService dfuService; DeviceInformationService deviceInformationService; CurrentTimeClient currentTimeClient; diff --git a/src/components/datetime/DateTimeController.cpp b/src/components/datetime/DateTimeController.cpp index 673903c..3bfbdc7 100644 --- a/src/components/datetime/DateTimeController.cpp +++ b/src/components/datetime/DateTimeController.cpp @@ -11,6 +11,9 @@ namespace { char const* MonthsStringLow[] = {"--", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; } +DateTime::DateTime(Controllers::Settings& settingsController) : settingsController {settingsController} { +} + void DateTime::SetCurrentTime(std::chrono::time_point<std::chrono::system_clock, std::chrono::nanoseconds> t) { this->currentDateTime = t; UpdateTime(previousSystickCounter); // Update internal state without updating the time @@ -36,6 +39,8 @@ void DateTime::SetTime( UpdateTime(systickCounter); NRF_LOG_INFO("* %d %d %d ", this->hour, this->minute, this->second); NRF_LOG_INFO("* %d %d %d ", this->day, this->month, this->year); + + systemTask->PushMessage(System::Messages::OnNewTime); } void DateTime::UpdateTime(uint32_t systickCounter) { @@ -103,11 +108,11 @@ void DateTime::UpdateTime(uint32_t systickCounter) { } } -const char* DateTime::MonthShortToString() { +const char* DateTime::MonthShortToString() const { return MonthsString[static_cast<uint8_t>(month)]; } -const char* DateTime::DayOfWeekShortToString() { +const char* DateTime::DayOfWeekShortToString() const { return DaysStringShort[static_cast<uint8_t>(dayOfWeek)]; } @@ -118,3 +123,24 @@ const char* DateTime::MonthShortToStringLow(Months month) { void DateTime::Register(Pinetime::System::SystemTask* systemTask) { this->systemTask = systemTask; } + +using ClockType = Pinetime::Controllers::Settings::ClockType; +std::string DateTime::FormattedTime() { + // Return time as a string in 12- or 24-hour format + char buff[9]; + if (settingsController.GetClockType() == ClockType::H12) { + uint8_t hour12; + const char* amPmStr; + if (hour < 12) { + hour12 = (hour == 0) ? 12 : hour; + amPmStr = "AM"; + } else { + hour12 = (hour == 12) ? 12 : hour - 12; + amPmStr = "PM"; + } + sprintf(buff, "%i:%02i %s", hour12, minute, amPmStr); + } else { + sprintf(buff, "%02i:%02i", hour, minute); + } + return std::string(buff); +} diff --git a/src/components/datetime/DateTimeController.h b/src/components/datetime/DateTimeController.h index cbc8044..00bbc2e 100644 --- a/src/components/datetime/DateTimeController.h +++ b/src/components/datetime/DateTimeController.h @@ -2,6 +2,8 @@ #include <cstdint> #include <chrono> +#include <string> +#include "components/settings/Settings.h" namespace Pinetime { namespace System { @@ -10,6 +12,7 @@ namespace Pinetime { namespace Controllers { class DateTime { public: + DateTime(Controllers::Settings& settingsController); enum class Days : uint8_t { Unknown, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday }; enum class Months : uint8_t { Unknown, @@ -58,8 +61,8 @@ namespace Pinetime { return second; } - const char* MonthShortToString(); - const char* DayOfWeekShortToString(); + const char* MonthShortToString() const; + const char* DayOfWeekShortToString() const; static const char* MonthShortToStringLow(Months month); std::chrono::time_point<std::chrono::system_clock, std::chrono::nanoseconds> CurrentDateTime() const { @@ -71,6 +74,7 @@ namespace Pinetime { void Register(System::SystemTask* systemTask); void SetCurrentTime(std::chrono::time_point<std::chrono::system_clock, std::chrono::nanoseconds> t); + std::string FormattedTime(); private: uint16_t year = 0; @@ -89,6 +93,7 @@ namespace Pinetime { bool isHourAlreadyNotified = true; bool isHalfHourAlreadyNotified = true; System::SystemTask* systemTask = nullptr; + Controllers::Settings& settingsController; }; } } diff --git a/src/components/heartrate/Ppg.h b/src/components/heartrate/Ppg.h index ed79b08..7000c87 100644 --- a/src/components/heartrate/Ppg.h +++ b/src/components/heartrate/Ppg.h @@ -1,6 +1,8 @@ #pragma once #include <array> +#include <cstddef> +#include <cstdint> #include "components/heartrate/Biquad.h" #include "components/heartrate/Ptagc.h" diff --git a/src/components/motor/MotorController.h b/src/components/motor/MotorController.h index c9326d5..b5a592b 100644 --- a/src/components/motor/MotorController.h +++ b/src/components/motor/MotorController.h @@ -12,7 +12,7 @@ namespace Pinetime { void Init(); void RunForDuration(uint8_t motorDuration); void StartRinging(); - static void StopRinging(); + void StopRinging(); private: static void Ring(void* p_context); diff --git a/src/components/settings/Settings.cpp b/src/components/settings/Settings.cpp index ef73ad1..fee62da 100644 --- a/src/components/settings/Settings.cpp +++ b/src/components/settings/Settings.cpp @@ -26,7 +26,7 @@ void Settings::LoadSettingsFromFile() { SettingsData bufferSettings; lfs_file_t settingsFile; - if ( fs.FileOpen(&settingsFile, "/settings.dat", LFS_O_RDWR | LFS_O_CREAT) != LFS_ERR_OK) { + if ( fs.FileOpen(&settingsFile, "/settings.dat", LFS_O_RDONLY) != LFS_ERR_OK) { return; } fs.FileRead(&settingsFile, reinterpret_cast<uint8_t*>(&bufferSettings), sizeof(settings)); @@ -39,7 +39,7 @@ void Settings::LoadSettingsFromFile() { void Settings::SaveSettingsToFile() { lfs_file_t settingsFile; - if ( fs.FileOpen(&settingsFile, "/settings.dat", LFS_O_RDWR | LFS_O_CREAT) != LFS_ERR_OK) { + if ( fs.FileOpen(&settingsFile, "/settings.dat", LFS_O_WRONLY | LFS_O_CREAT) != LFS_ERR_OK) { return; } fs.FileWrite(&settingsFile, reinterpret_cast<uint8_t*>(&settings), sizeof(settings)); diff --git a/src/components/settings/Settings.h b/src/components/settings/Settings.h index 6de44aa..44a1a85 100644 --- a/src/components/settings/Settings.h +++ b/src/components/settings/Settings.h @@ -1,7 +1,6 @@ #pragma once #include <cstdint> #include <bitset> -#include "components/datetime/DateTimeController.h" #include "components/brightness/BrightnessController.h" #include "components/fs/FS.h" @@ -19,7 +18,23 @@ namespace Pinetime { Shake = 3, }; enum class Colors : uint8_t { - White, Silver, Gray, Black, Red, Maroon, Yellow, Olive, Lime, Green, Cyan, Teal, Blue, Navy, Magenta, Purple, Orange + White, + Silver, + Gray, + Black, + Red, + Maroon, + Yellow, + Olive, + Lime, + Green, + Cyan, + Teal, + Blue, + Navy, + Magenta, + Purple, + Orange }; struct PineTimeStyle { Colors ColorTime = Colors::Teal; @@ -171,18 +186,29 @@ namespace Pinetime { } settings.brightLevel = level; }; + Controllers::BrightnessController::Levels GetBrightness() const { return settings.brightLevel; }; - void SetStepsGoal( uint32_t goal ) { - if ( goal != settings.stepsGoal ) { + void SetStepsGoal(uint32_t goal) { + if (goal != settings.stepsGoal) { settingsChanged = true; } settings.stepsGoal = goal; }; - uint32_t GetStepsGoal() const { return settings.stepsGoal; }; + uint32_t GetStepsGoal() const { + return settings.stepsGoal; + }; + + void SetBleRadioEnabled(bool enabled) { + bleRadioEnabled = enabled; + }; + + bool GetBleRadioEnabled() const { + return bleRadioEnabled; + }; private: Pinetime::Controllers::FS& fs; @@ -211,6 +237,10 @@ namespace Pinetime { uint8_t appMenu = 0; uint8_t settingsMenu = 0; + /* ble state is intentionally not saved with the other watch settings and initialized + * to off (false) on every boot because we always want ble to be enabled on startup + */ + bool bleRadioEnabled = true; void LoadSettingsFromFile(); void SaveSettingsToFile(); |
