From 319030d9e16e833cf8bff569a9ecfa452165ea27 Mon Sep 17 00:00:00 2001 From: "James A. Jerkins" Date: Thu, 23 Dec 2021 20:30:14 -0600 Subject: Add airplane mode feature Implements 'Airplane mode' feature to disable and enable bluetooth/ble Adds airplaneMode as a non-persisted setting Adds a setting menu for switching airplane mode on and off Displays an airplane symbol on the Digital watch face and the PineTimeStyle watch face when airplane mode is enabled Always enables bluetooth/ble on boot (disable airplane mode) Alphabetizes the settings menu options Style cleanups Closes #632 diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 809544c..ae8eece 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -448,6 +448,7 @@ list(APPEND SOURCE_FILES displayapp/screens/settings/SettingPineTimeStyle.cpp displayapp/screens/settings/SettingSetDate.cpp displayapp/screens/settings/SettingSetTime.cpp + displayapp/screens/settings/SettingAirplaneMode.cpp ## Watch faces displayapp/icons/bg_clock.c diff --git a/src/components/ble/BleController.cpp b/src/components/ble/BleController.cpp index a80c971..0e1c5d7 100644 --- a/src/components/ble/BleController.cpp +++ b/src/components/ble/BleController.cpp @@ -2,12 +2,12 @@ using namespace Pinetime::Controllers; -void Ble::Connect() { - isConnected = true; +void Ble::SetConnectState(Ble::ConnectStates newState) { + connectionState = newState; } -void Ble::Disconnect() { - isConnected = false; +Ble::ConnectStates Ble::GetConnectState() const { + return connectionState; } void Ble::StartFirmwareUpdate() { diff --git a/src/components/ble/BleController.h b/src/components/ble/BleController.h index 72b8766..2714c0c 100644 --- a/src/components/ble/BleController.h +++ b/src/components/ble/BleController.h @@ -10,13 +10,14 @@ namespace Pinetime { using BleAddress = std::array; enum class FirmwareUpdateStates { Idle, Running, Validated, Error }; enum class AddressTypes { Public, Random, RPA_Public, RPA_Random }; + enum class ConnectStates { Disconnected, Connected, Airplane }; Ble() = default; bool IsConnected() const { - return isConnected; + return (connectionState == ConnectStates::Connected); } - void Connect(); - void Disconnect(); + void SetConnectState(ConnectStates newState); + ConnectStates GetConnectState() const; void StartFirmwareUpdate(); void StopFirmwareUpdate(); @@ -56,7 +57,7 @@ namespace Pinetime { } private: - bool isConnected = false; + ConnectStates connectionState = ConnectStates::Disconnected; bool isFirmwareUpdating = false; uint32_t firmwareUpdateTotalBytes = 0; uint32_t firmwareUpdateCurrentBytes = 0; diff --git a/src/components/ble/NimbleController.cpp b/src/components/ble/NimbleController.cpp index d8510bd..d85ec5d 100644 --- a/src/components/ble/NimbleController.cpp +++ b/src/components/ble/NimbleController.cpp @@ -23,14 +23,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}, @@ -184,7 +184,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.GetConnectState() == Ble::ConnectStates::Disconnected) { + StartAdvertising(); + } break; case BLE_GAP_EVENT_CONNECT: @@ -197,12 +199,12 @@ int NimbleController::OnGAPEvent(ble_gap_event* event) { currentTimeClient.Reset(); alertNotificationClient.Reset(); connectionHandle = BLE_HS_CONN_HANDLE_NONE; - bleController.Disconnect(); + bleController.SetConnectState(Ble::ConnectStates::Disconnected); fastAdvCount = 0; StartAdvertising(); } else { connectionHandle = event->connect.conn_handle; - bleController.Connect(); + bleController.SetConnectState(Ble::ConnectStates::Connected); systemTask.PushMessage(Pinetime::System::Messages::BleConnected); // Service discovery is deferred via systemtask } @@ -220,9 +222,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.GetConnectState() == Ble::ConnectStates::Connected) { + bleController.SetConnectState(Ble::ConnectStates::Disconnected); + fastAdvCount = 0; + StartAdvertising(); + } break; case BLE_GAP_EVENT_CONN_UPDATE: @@ -376,6 +380,22 @@ void NimbleController::NotifyBatteryLevel(uint8_t level) { } } +void NimbleController::SwitchAirplaneMode(bool enabled) { + if (enabled) { + if (bleController.IsConnected()) { + bleController.SetConnectState(Ble::ConnectStates::Airplane); + ble_gap_terminate(connectionHandle, BLE_ERR_REM_USER_CONN_TERM); + } else { + bleController.SetConnectState(Ble::ConnectStates::Airplane); + ble_gap_adv_stop(); + } + } else { + bleController.SetConnectState(Ble::ConnectStates::Disconnected); + fastAdvCount = 0; + StartAdvertising(); + } +} + 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..7219ba6 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,18 +42,19 @@ 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); + /* these are not implemented yet 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); @@ -62,6 +63,7 @@ namespace Pinetime { const ble_gatt_error* error, uint16_t characteristicValueHandle, const ble_gatt_dsc* descriptor); + */ void StartDiscovery(); @@ -83,7 +85,9 @@ namespace Pinetime { void RestartFastAdv() { fastAdvCount = 0; - } + }; + + void SwitchAirplaneMode(bool enabled); private: void PersistBond(struct ble_gap_conn_desc& desc); @@ -91,12 +95,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/settings/Settings.h b/src/components/settings/Settings.h index 2d7973d..a1529fe 100644 --- a/src/components/settings/Settings.h +++ b/src/components/settings/Settings.h @@ -17,7 +17,23 @@ namespace Pinetime { RaiseWrist = 2, }; 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; @@ -146,18 +162,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 SetAirplaneMode(bool mode) { + airplaneMode = mode; + }; + + bool GetAirplaneMode() const { + return airplaneMode; + }; private: Pinetime::Controllers::FS& fs; @@ -185,6 +212,10 @@ namespace Pinetime { uint8_t appMenu = 0; uint8_t settingsMenu = 0; + /* airplaneMode 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 airplaneMode = false; void LoadSettingsFromFile(); void SaveSettingsToFile(); diff --git a/src/displayapp/Apps.h b/src/displayapp/Apps.h index b2f55cc..971c36b 100644 --- a/src/displayapp/Apps.h +++ b/src/displayapp/Apps.h @@ -37,7 +37,8 @@ namespace Pinetime { SettingPineTimeStyle, SettingSetDate, SettingSetTime, - Error, + SettingAirplaneMode, + Error }; } } diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp index 233f433..d3896b1 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -48,6 +48,7 @@ #include "displayapp/screens/settings/SettingPineTimeStyle.h" #include "displayapp/screens/settings/SettingSetDate.h" #include "displayapp/screens/settings/SettingSetTime.h" +#include "displayapp/screens/settings/SettingAirplaneMode.h" #include "libs/lv_conf.h" @@ -289,6 +290,9 @@ void DisplayApp::Refresh() { case Messages::BleFirmwareUpdateStarted: LoadApp(Apps::FirmwareUpdate, DisplayApp::FullRefreshDirections::Down); break; + case Messages::AirplaneModeToggle: + PushMessageToSystemTask(System::Messages::AirplaneModeToggle); + break; case Messages::UpdateDateTime: // Added to remove warning // What should happen here? @@ -420,6 +424,10 @@ void DisplayApp::LoadApp(Apps app, DisplayApp::FullRefreshDirections direction) currentScreen = std::make_unique(this, settingsController); ReturnApp(Apps::Settings, FullRefreshDirections::Down, TouchEvents::SwipeDown); break; + case Apps::SettingAirplaneMode: + currentScreen = std::make_unique(this, settingsController); + ReturnApp(Apps::Settings, FullRefreshDirections::Down, TouchEvents::SwipeDown); + break; case Apps::BatteryInfo: currentScreen = std::make_unique(this, batteryController); ReturnApp(Apps::Settings, FullRefreshDirections::Down, TouchEvents::SwipeDown); diff --git a/src/displayapp/Messages.h b/src/displayapp/Messages.h index b22d6c3..4d52df2 100644 --- a/src/displayapp/Messages.h +++ b/src/displayapp/Messages.h @@ -20,7 +20,8 @@ namespace Pinetime { DimScreen, RestoreBrightness, ShowPairingKey, - AlarmTriggered + AlarmTriggered, + AirplaneModeToggle }; } } diff --git a/src/displayapp/fonts/README.md b/src/displayapp/fonts/README.md index 8a26084..40ecd3e 100644 --- a/src/displayapp/fonts/README.md +++ b/src/displayapp/fonts/README.md @@ -13,7 +13,7 @@ * Do not enable font compression and horizontal subpixel hinting * Load the file `JetBrainsMono-Bold.tff` (use the file in this repo to ensure the version matches) and specify the following range : `0x20-0x7f, 0x410-0x44f` * Add a 2nd font, load the file `FontAwesome5-Solid+Brands+Regular.woff` and specify the following - range : `0xf293, 0xf294, 0xf244, 0xf240, 0xf242, 0xf243, 0xf241, 0xf54b, 0xf21e, 0xf1e6, 0xf54b, 0xf017, 0xf129, 0xf03a, 0xf185, 0xf560, 0xf001, 0xf3fd, 0xf069, 0xf1fc, 0xf45d, 0xf59f, 0xf5a0, 0xf029, 0xf027, 0xf028, 0xf6a9, 0xf04b, 0xf04c, 0xf048, 0xf051, 0xf095, 0xf3dd, 0xf04d, 0xf2f2, 0xf024, 0xf252, 0xf569, 0xf201, 0xf06e, 0xf015` + range : `0xf293, 0xf294, 0xf244, 0xf240, 0xf242, 0xf243, 0xf241, 0xf54b, 0xf21e, 0xf1e6, 0xf54b, 0xf017, 0xf129, 0xf03a, 0xf185, 0xf560, 0xf001, 0xf3fd, 0xf069, 0xf1fc, 0xf45d, 0xf59f, 0xf5a0, 0xf029, 0xf027, 0xf028, 0xf6a9, 0xf04b, 0xf04c, 0xf048, 0xf051, 0xf095, 0xf3dd, 0xf04d, 0xf2f2, 0xf024, 0xf252, 0xf569, 0xf201, 0xf06e, 0xf015, 0xf072` * Click on Convert, and download the file `jetbrains_mono_bold_20.c` and copy it in `src/DisplayApp/Fonts` * Add the font .c file path to src/CMakeLists.txt * Add an LV_FONT_DECLARE line in src/libs/lv_conf.h diff --git a/src/displayapp/fonts/jetbrains_mono_bold_20.c b/src/displayapp/fonts/jetbrains_mono_bold_20.c index d870552..944e47a 100644 --- a/src/displayapp/fonts/jetbrains_mono_bold_20.c +++ b/src/displayapp/fonts/jetbrains_mono_bold_20.c @@ -840,6 +840,16 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = { 0xf8, 0xf, 0x80, 0xf8, 0x3e, 0x0, 0xff, 0xf0, 0x0, 0x3f, 0x80, 0x0, + /* U+F072 "" */ + 0x1, 0xc0, 0x0, 0x7, 0xc0, 0x0, 0x7, 0x80, + 0x0, 0xf, 0x80, 0x0, 0x1f, 0x0, 0x0, 0x1f, + 0x0, 0x38, 0x3e, 0x0, 0x78, 0x7e, 0x0, 0x7f, + 0xff, 0xe0, 0xff, 0xff, 0xf9, 0xff, 0xff, 0xf3, + 0xff, 0xff, 0xe7, 0xff, 0xff, 0xdf, 0xff, 0xfc, + 0x3c, 0x3f, 0x0, 0x70, 0x7c, 0x0, 0x1, 0xf0, + 0x0, 0x3, 0xe0, 0x0, 0x7, 0x80, 0x0, 0xf, + 0x0, 0x0, 0x1c, 0x0, 0x0, + /* U+F095 "" */ 0x0, 0x0, 0x0, 0x0, 0x3e, 0x0, 0x7, 0xf0, 0x0, 0x7f, 0x0, 0x7, 0xf0, 0x0, 0xff, 0x0, @@ -1220,31 +1230,32 @@ static const lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] = { {.bitmap_index = 3028, .adv_w = 280, .box_w = 13, .box_h = 17, .ofs_x = 2, .ofs_y = -1}, {.bitmap_index = 3056, .adv_w = 320, .box_w = 19, .box_h = 20, .ofs_x = 0, .ofs_y = -3}, {.bitmap_index = 3104, .adv_w = 360, .box_w = 23, .box_h = 15, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 3148, .adv_w = 320, .box_w = 20, .box_h = 21, .ofs_x = 0, .ofs_y = -3}, - {.bitmap_index = 3201, .adv_w = 120, .box_w = 8, .box_h = 19, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 3220, .adv_w = 320, .box_w = 20, .box_h = 20, .ofs_x = 0, .ofs_y = -3}, - {.bitmap_index = 3270, .adv_w = 240, .box_w = 15, .box_h = 19, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 3306, .adv_w = 320, .box_w = 20, .box_h = 19, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 3354, .adv_w = 320, .box_w = 21, .box_h = 15, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 3394, .adv_w = 320, .box_w = 20, .box_h = 17, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 3437, .adv_w = 400, .box_w = 25, .box_h = 12, .ofs_x = 0, .ofs_y = 1}, - {.bitmap_index = 3475, .adv_w = 400, .box_w = 25, .box_h = 12, .ofs_x = 0, .ofs_y = 1}, - {.bitmap_index = 3513, .adv_w = 400, .box_w = 25, .box_h = 12, .ofs_x = 0, .ofs_y = 1}, - {.bitmap_index = 3551, .adv_w = 400, .box_w = 25, .box_h = 12, .ofs_x = 0, .ofs_y = 1}, - {.bitmap_index = 3589, .adv_w = 400, .box_w = 25, .box_h = 12, .ofs_x = 0, .ofs_y = 1}, - {.bitmap_index = 3627, .adv_w = 240, .box_w = 15, .box_h = 19, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 3663, .adv_w = 280, .box_w = 15, .box_h = 20, .ofs_x = 1, .ofs_y = -3}, - {.bitmap_index = 3701, .adv_w = 200, .box_w = 11, .box_h = 21, .ofs_x = 0, .ofs_y = -3}, - {.bitmap_index = 3730, .adv_w = 280, .box_w = 16, .box_h = 19, .ofs_x = 1, .ofs_y = -2}, - {.bitmap_index = 3768, .adv_w = 400, .box_w = 25, .box_h = 21, .ofs_x = 0, .ofs_y = -3}, - {.bitmap_index = 3834, .adv_w = 360, .box_w = 23, .box_h = 17, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 3883, .adv_w = 320, .box_w = 20, .box_h = 20, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 3933, .adv_w = 400, .box_w = 25, .box_h = 19, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 3993, .adv_w = 320, .box_w = 20, .box_h = 21, .ofs_x = 0, .ofs_y = -3}, - {.bitmap_index = 4046, .adv_w = 360, .box_w = 23, .box_h = 21, .ofs_x = 0, .ofs_y = -3}, - {.bitmap_index = 4107, .adv_w = 360, .box_w = 22, .box_h = 20, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 4162, .adv_w = 360, .box_w = 22, .box_h = 19, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 4215, .adv_w = 320, .box_w = 20, .box_h = 15, .ofs_x = 0, .ofs_y = 0} + {.bitmap_index = 3148, .adv_w = 360, .box_w = 23, .box_h = 21, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 3209, .adv_w = 320, .box_w = 20, .box_h = 21, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 3262, .adv_w = 120, .box_w = 8, .box_h = 19, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 3281, .adv_w = 320, .box_w = 20, .box_h = 20, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 3331, .adv_w = 240, .box_w = 15, .box_h = 19, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 3367, .adv_w = 320, .box_w = 20, .box_h = 19, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 3415, .adv_w = 320, .box_w = 21, .box_h = 15, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 3455, .adv_w = 320, .box_w = 20, .box_h = 17, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 3498, .adv_w = 400, .box_w = 25, .box_h = 12, .ofs_x = 0, .ofs_y = 1}, + {.bitmap_index = 3536, .adv_w = 400, .box_w = 25, .box_h = 12, .ofs_x = 0, .ofs_y = 1}, + {.bitmap_index = 3574, .adv_w = 400, .box_w = 25, .box_h = 12, .ofs_x = 0, .ofs_y = 1}, + {.bitmap_index = 3612, .adv_w = 400, .box_w = 25, .box_h = 12, .ofs_x = 0, .ofs_y = 1}, + {.bitmap_index = 3650, .adv_w = 400, .box_w = 25, .box_h = 12, .ofs_x = 0, .ofs_y = 1}, + {.bitmap_index = 3688, .adv_w = 240, .box_w = 15, .box_h = 19, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 3724, .adv_w = 280, .box_w = 15, .box_h = 20, .ofs_x = 1, .ofs_y = -3}, + {.bitmap_index = 3762, .adv_w = 200, .box_w = 11, .box_h = 21, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 3791, .adv_w = 280, .box_w = 16, .box_h = 19, .ofs_x = 1, .ofs_y = -2}, + {.bitmap_index = 3829, .adv_w = 400, .box_w = 25, .box_h = 21, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 3895, .adv_w = 360, .box_w = 23, .box_h = 17, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 3944, .adv_w = 320, .box_w = 20, .box_h = 20, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 3994, .adv_w = 400, .box_w = 25, .box_h = 19, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 4054, .adv_w = 320, .box_w = 20, .box_h = 21, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 4107, .adv_w = 360, .box_w = 23, .box_h = 21, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 4168, .adv_w = 360, .box_w = 22, .box_h = 20, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 4223, .adv_w = 360, .box_w = 22, .box_h = 19, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 4276, .adv_w = 320, .box_w = 20, .box_h = 15, .ofs_x = 0, .ofs_y = 0} }; /*--------------------- @@ -1253,10 +1264,11 @@ static const lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] = { static const uint16_t unicode_list_2[] = { 0x0, 0x14, 0x16, 0x23, 0x26, 0x27, 0x28, 0x39, - 0x47, 0x4a, 0x4b, 0x4c, 0x50, 0x68, 0x6d, 0x94, - 0x128, 0x184, 0x1e5, 0x1fb, 0x200, 0x21d, 0x23f, 0x240, - 0x241, 0x242, 0x243, 0x251, 0x292, 0x293, 0x2f1, 0x3dc, - 0x3fc, 0x45c, 0x54a, 0x55f, 0x568, 0x59e, 0x59f, 0x6a8 + 0x47, 0x4a, 0x4b, 0x4c, 0x50, 0x68, 0x6d, 0x71, + 0x94, 0x128, 0x184, 0x1e5, 0x1fb, 0x200, 0x21d, 0x23f, + 0x240, 0x241, 0x242, 0x243, 0x251, 0x292, 0x293, 0x2f1, + 0x3dc, 0x3fc, 0x45c, 0x54a, 0x55f, 0x568, 0x59e, 0x59f, + 0x6a8 }; /*Collect the unicode lists and glyph_id offsets*/ @@ -1272,7 +1284,7 @@ static const lv_font_fmt_txt_cmap_t cmaps[] = }, { .range_start = 61441, .range_length = 1705, .glyph_id_start = 160, - .unicode_list = unicode_list_2, .glyph_id_ofs_list = NULL, .list_length = 40, .type = LV_FONT_FMT_TXT_CMAP_SPARSE_TINY + .unicode_list = unicode_list_2, .glyph_id_ofs_list = NULL, .list_length = 41, .type = LV_FONT_FMT_TXT_CMAP_SPARSE_TINY } }; @@ -1321,7 +1333,7 @@ lv_font_t jetbrains_mono_bold_20 = { #if !(LVGL_VERSION_MAJOR == 6 && LVGL_VERSION_MINOR == 0) .subpx = LV_FONT_SUBPX_NONE, #endif -#if LV_VERSION_CHECK(7, 4, 0) +#if LV_VERSION_CHECK(7, 4, 0) || LVGL_VERSION_MAJOR >= 8 .underline_position = -3, .underline_thickness = 1, #endif diff --git a/src/displayapp/screens/BleIcon.cpp b/src/displayapp/screens/BleIcon.cpp index 5058f3e..a30d23b 100644 --- a/src/displayapp/screens/BleIcon.cpp +++ b/src/displayapp/screens/BleIcon.cpp @@ -2,9 +2,11 @@ #include "displayapp/screens/Symbols.h" using namespace Pinetime::Applications::Screens; -const char* BleIcon::GetIcon(bool isConnected) { - if (isConnected) +const char* BleIcon::GetIcon(Pinetime::Controllers::Ble::ConnectStates state) { + if (state == Pinetime::Controllers::Ble::ConnectStates::Connected) return Symbols::bluetooth; + else if (state == Pinetime::Controllers::Ble::ConnectStates::Airplane) + return Symbols::airplane; else - return ""; -} \ No newline at end of file + return Symbols::none; +} diff --git a/src/displayapp/screens/BleIcon.h b/src/displayapp/screens/BleIcon.h index c1398d2..d7410ea 100644 --- a/src/displayapp/screens/BleIcon.h +++ b/src/displayapp/screens/BleIcon.h @@ -1,12 +1,14 @@ #pragma once +#include "components/ble/BleController.h" + namespace Pinetime { namespace Applications { namespace Screens { class BleIcon { public: - static const char* GetIcon(bool isConnected); + static const char* GetIcon(Pinetime::Controllers::Ble::ConnectStates state); }; } } -} \ No newline at end of file +} diff --git a/src/displayapp/screens/PineTimeStyle.cpp b/src/displayapp/screens/PineTimeStyle.cpp index d436869..e7b1f39 100644 --- a/src/displayapp/screens/PineTimeStyle.cpp +++ b/src/displayapp/screens/PineTimeStyle.cpp @@ -208,10 +208,10 @@ void PineTimeStyle::SetBatteryIcon() { } void PineTimeStyle::AlignIcons() { - if (notificationState.Get() && bleState.Get()) { + if (notificationState.Get() && bleState.Get() != Pinetime::Controllers::Ble::ConnectStates::Disconnected) { lv_obj_align(bleIcon, sidebar, LV_ALIGN_IN_TOP_MID, 8, 25); lv_obj_align(notificationIcon, sidebar, LV_ALIGN_IN_TOP_MID, -8, 25); - } else if (notificationState.Get() && !bleState.Get()) { + } else if (notificationState.Get() && bleState.Get() == Pinetime::Controllers::Ble::ConnectStates::Disconnected) { lv_obj_align(notificationIcon, sidebar, LV_ALIGN_IN_TOP_MID, 0, 25); } else { lv_obj_align(bleIcon, sidebar, LV_ALIGN_IN_TOP_MID, 0, 25); @@ -234,7 +234,7 @@ void PineTimeStyle::Refresh() { } } - bleState = bleController.IsConnected(); + bleState = bleController.GetConnectState(); if (bleState.IsUpdated()) { lv_label_set_text(bleIcon, BleIcon::GetIcon(bleState.Get())); AlignIcons(); diff --git a/src/displayapp/screens/PineTimeStyle.h b/src/displayapp/screens/PineTimeStyle.h index 8382c53..c5136fc 100644 --- a/src/displayapp/screens/PineTimeStyle.h +++ b/src/displayapp/screens/PineTimeStyle.h @@ -6,6 +6,7 @@ #include #include "displayapp/screens/Screen.h" #include "components/datetime/DateTimeController.h" +#include "components/ble/BleController.h" namespace Pinetime { namespace Controllers { @@ -36,13 +37,13 @@ namespace Pinetime { char displayedChar[5]; uint16_t currentYear = 1970; - Pinetime::Controllers::DateTime::Months currentMonth = Pinetime::Controllers::DateTime::Months::Unknown; - Pinetime::Controllers::DateTime::Days currentDayOfWeek = Pinetime::Controllers::DateTime::Days::Unknown; + Controllers::DateTime::Months currentMonth = Pinetime::Controllers::DateTime::Months::Unknown; + Controllers::DateTime::Days currentDayOfWeek = Pinetime::Controllers::DateTime::Days::Unknown; uint8_t currentDay = 0; DirtyValue batteryPercentRemaining {}; DirtyValue isCharging {}; - DirtyValue bleState {}; + DirtyValue bleState {}; DirtyValue> currentDateTime {}; DirtyValue motionSensorOk {}; DirtyValue stepCount {}; diff --git a/src/displayapp/screens/Symbols.h b/src/displayapp/screens/Symbols.h index e68a7af..5ba8f95 100644 --- a/src/displayapp/screens/Symbols.h +++ b/src/displayapp/screens/Symbols.h @@ -44,6 +44,7 @@ namespace Pinetime { static constexpr const char* chartLine = "\xEF\x88\x81"; static constexpr const char* eye = "\xEF\x81\xAE"; static constexpr const char* home = "\xEF\x80\x95"; + static constexpr const char* airplane = "\xEF\x81\xB2"; // lv_font_sys_48.c static constexpr const char* settings = "\xEE\xA4\x82"; // e902 diff --git a/src/displayapp/screens/WatchFaceDigital.cpp b/src/displayapp/screens/WatchFaceDigital.cpp index 8769579..8f06553 100644 --- a/src/displayapp/screens/WatchFaceDigital.cpp +++ b/src/displayapp/screens/WatchFaceDigital.cpp @@ -119,7 +119,7 @@ void WatchFaceDigital::Refresh() { lv_label_set_text(batteryIcon, BatteryIcon::GetBatteryIcon(batteryPercent)); } - bleState = bleController.IsConnected(); + bleState = bleController.GetConnectState(); if (bleState.IsUpdated()) { lv_label_set_text(bleIcon, BleIcon::GetIcon(bleState.Get())); } diff --git a/src/displayapp/screens/WatchFaceDigital.h b/src/displayapp/screens/WatchFaceDigital.h index 627154c..addb539 100644 --- a/src/displayapp/screens/WatchFaceDigital.h +++ b/src/displayapp/screens/WatchFaceDigital.h @@ -6,6 +6,7 @@ #include #include "displayapp/screens/Screen.h" #include "components/datetime/DateTimeController.h" +#include "components/ble/BleController.h" namespace Pinetime { namespace Controllers { @@ -38,13 +39,13 @@ namespace Pinetime { char displayedChar[5] {}; uint16_t currentYear = 1970; - Pinetime::Controllers::DateTime::Months currentMonth = Pinetime::Controllers::DateTime::Months::Unknown; - Pinetime::Controllers::DateTime::Days currentDayOfWeek = Pinetime::Controllers::DateTime::Days::Unknown; + Controllers::DateTime::Months currentMonth = Pinetime::Controllers::DateTime::Months::Unknown; + Controllers::DateTime::Days currentDayOfWeek = Pinetime::Controllers::DateTime::Days::Unknown; uint8_t currentDay = 0; DirtyValue batteryPercentRemaining {}; DirtyValue powerPresent {}; - DirtyValue bleState {}; + DirtyValue bleState {}; DirtyValue> currentDateTime {}; DirtyValue motionSensorOk {}; DirtyValue stepCount {}; diff --git a/src/displayapp/screens/settings/SettingAirplaneMode.cpp b/src/displayapp/screens/settings/SettingAirplaneMode.cpp new file mode 100644 index 0000000..0a364de --- /dev/null +++ b/src/displayapp/screens/settings/SettingAirplaneMode.cpp @@ -0,0 +1,89 @@ +#include "displayapp/screens/settings/SettingAirplaneMode.h" +#include +#include "displayapp/DisplayApp.h" +#include "displayapp/Messages.h" +#include "displayapp/screens/Styles.h" +#include "displayapp/screens/Screen.h" +#include "displayapp/screens/Symbols.h" + +using namespace Pinetime::Applications::Screens; + +namespace { + static void event_handler(lv_obj_t* obj, lv_event_t event) { + SettingAirplaneMode* screen = static_cast(obj->user_data); + screen->UpdateSelected(obj, event); + } +} + +constexpr std::array SettingAirplaneMode::options; + +SettingAirplaneMode::SettingAirplaneMode(Pinetime::Applications::DisplayApp* app, Pinetime::Controllers::Settings& settingsController) + : Screen(app), settingsController {settingsController} { + + lv_obj_t* 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, 10, 60); + lv_obj_set_width(container1, LV_HOR_RES - 20); + lv_obj_set_height(container1, LV_VER_RES - 50); + lv_cont_set_layout(container1, LV_LAYOUT_COLUMN_LEFT); + + lv_obj_t* title = lv_label_create(lv_scr_act(), nullptr); + lv_label_set_text_static(title, "Airplane mode"); + lv_label_set_align(title, LV_LABEL_ALIGN_CENTER); + lv_obj_align(title, lv_scr_act(), LV_ALIGN_IN_TOP_MID, 15, 15); + + lv_obj_t* icon = lv_label_create(lv_scr_act(), nullptr); + lv_obj_set_style_local_text_color(icon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_ORANGE); + lv_label_set_text_static(icon, Symbols::airplane); + lv_label_set_align(icon, LV_LABEL_ALIGN_CENTER); + lv_obj_align(icon, title, LV_ALIGN_OUT_LEFT_MID, -10, 0); + + for (unsigned int i = 0; i < options.size(); i++) { + cbOption[i] = lv_checkbox_create(container1, nullptr); + lv_checkbox_set_text(cbOption[i], options[i]); + cbOption[i]->user_data = this; + lv_obj_set_event_cb(cbOption[i], event_handler); + SetRadioButtonStyle(cbOption[i]); + } + + if (settingsController.GetAirplaneMode() == false) { + lv_checkbox_set_checked(cbOption[0], true); + priorMode = false; + } else { + lv_checkbox_set_checked(cbOption[1], true); + priorMode = true; + } +} + +SettingAirplaneMode::~SettingAirplaneMode() { + lv_obj_clean(lv_scr_act()); + // Do not call SaveSettings - see src/components/settings/Settings.h + if (priorMode != settingsController.GetAirplaneMode()) { + app->PushMessage(Pinetime::Applications::Display::Messages::AirplaneModeToggle); + } +} + +void SettingAirplaneMode::UpdateSelected(lv_obj_t* object, lv_event_t event) { + if (event == LV_EVENT_VALUE_CHANGED) { + for (unsigned int i = 0; i < options.size(); i++) { + if (object == cbOption[i]) { + lv_checkbox_set_checked(cbOption[i], true); + + if (i == 0) { + settingsController.SetAirplaneMode(false); + }; + if (i == 1) { + settingsController.SetAirplaneMode(true); + }; + + } else { + lv_checkbox_set_checked(cbOption[i], false); + } + } + } +} diff --git a/src/displayapp/screens/settings/SettingAirplaneMode.h b/src/displayapp/screens/settings/SettingAirplaneMode.h new file mode 100644 index 0000000..fcc0222 --- /dev/null +++ b/src/displayapp/screens/settings/SettingAirplaneMode.h @@ -0,0 +1,30 @@ +#pragma once + +#include +#include +#include + +#include "components/settings/Settings.h" +#include "displayapp/screens/Screen.h" + +namespace Pinetime { + + namespace Applications { + namespace Screens { + + class SettingAirplaneMode : public Screen { + public: + SettingAirplaneMode(DisplayApp* app, Pinetime::Controllers::Settings& settingsController); + ~SettingAirplaneMode() override; + + void UpdateSelected(lv_obj_t* object, lv_event_t event); + + private: + static constexpr std::array options = {" No", " Yes"}; + Controllers::Settings& settingsController; + lv_obj_t* cbOption[options.size()]; + bool priorMode; + }; + } + } +} diff --git a/src/displayapp/screens/settings/Settings.cpp b/src/displayapp/screens/settings/Settings.cpp index 392c12e..6be00f5 100644 --- a/src/displayapp/screens/settings/Settings.cpp +++ b/src/displayapp/screens/settings/Settings.cpp @@ -36,10 +36,10 @@ bool Settings::OnTouchEvent(Pinetime::Applications::TouchEvents event) { std::unique_ptr Settings::CreateScreen1() { std::array applications {{ - {Symbols::sun, "Display", Apps::SettingDisplay}, - {Symbols::eye, "Wake Up", Apps::SettingWakeUp}, - {Symbols::clock, "Time format", Apps::SettingTimeFormat}, - {Symbols::home, "Watch face", Apps::SettingWatchFace}, + {Symbols::list, "About", Apps::SysInfo}, + {Symbols::airplane, "Airplane mode", Apps::SettingAirplaneMode}, + {Symbols::batteryHalf, "Battery", Apps::BatteryInfo}, + {Symbols::sun, "Display", Apps::SettingDisplay} }}; return std::make_unique(0, 3, app, settingsController, applications); @@ -48,10 +48,10 @@ std::unique_ptr Settings::CreateScreen1() { std::unique_ptr Settings::CreateScreen2() { std::array applications {{ - {Symbols::shoe, "Steps", Apps::SettingSteps}, + {Symbols::check, "Firmware", Apps::FirmwareValidation}, + {Symbols::paintbrush, "PTS colors", Apps::SettingPineTimeStyle}, {Symbols::clock, "Set date", Apps::SettingSetDate}, - {Symbols::clock, "Set time", Apps::SettingSetTime}, - {Symbols::batteryHalf, "Battery", Apps::BatteryInfo} + {Symbols::clock, "Set time", Apps::SettingSetTime} }}; return std::make_unique(1, 3, app, settingsController, applications); @@ -60,10 +60,10 @@ std::unique_ptr Settings::CreateScreen2() { std::unique_ptr Settings::CreateScreen3() { std::array applications {{ - {Symbols::paintbrush, "PTS Colors", Apps::SettingPineTimeStyle}, - {Symbols::check, "Firmware", Apps::FirmwareValidation}, - {Symbols::list, "About", Apps::SysInfo}, - {Symbols::none, "None", Apps::None}, + {Symbols::shoe, "Steps", Apps::SettingSteps}, + {Symbols::clock, "Time format", Apps::SettingTimeFormat}, + {Symbols::eye, "Wake up", Apps::SettingWakeUp}, + {Symbols::home, "Watch face", Apps::SettingWatchFace} }}; return std::make_unique(2, 3, app, settingsController, applications); diff --git a/src/systemtask/Messages.h b/src/systemtask/Messages.h index cc30fdc..886505b 100644 --- a/src/systemtask/Messages.h +++ b/src/systemtask/Messages.h @@ -29,6 +29,7 @@ namespace Pinetime { BatteryPercentageUpdated, StartFileTransfer, StopFileTransfer, + AirplaneModeToggle }; } } diff --git a/src/systemtask/SystemTask.cpp b/src/systemtask/SystemTask.cpp index a95d479..5ce223a 100644 --- a/src/systemtask/SystemTask.cpp +++ b/src/systemtask/SystemTask.cpp @@ -261,7 +261,7 @@ void SystemTask::Work() { displayApp.PushMessage(Pinetime::Applications::Display::Messages::GoToRunning); heartRateApp.PushMessage(Pinetime::Applications::HeartRateTask::Messages::WakeUp); - if (!bleController.IsConnected()) { + if (bleController.GetConnectState() == Controllers::Ble::ConnectStates::Disconnected) { nimbleController.RestartFastAdv(); } @@ -424,7 +424,9 @@ void SystemTask::Work() { motorController.RunForDuration(35); displayApp.PushMessage(Pinetime::Applications::Display::Messages::ShowPairingKey); break; - + case Messages::AirplaneModeToggle: + nimbleController.SwitchAirplaneMode(settingsController.GetAirplaneMode()); + break; default: break; } -- cgit v0.10.2