diff options
| author | JF <jf@codingfield.com> | 2020-09-26 15:09:24 (GMT) |
|---|---|---|
| committer | Gitea <gitea@fake.local> | 2020-09-26 15:09:24 (GMT) |
| commit | b6a910e52ed98b662e6586f45cfe9c6997f8f158 (patch) | |
| tree | d74185cbf682cde40e5de5bfa2f620ae201565a9 /src | |
| parent | be05997272b7b1d1b25b122c8162ac6f4c1c12a2 (diff) | |
| parent | 3e612e79ba82bac69258094d468c996c41b29612 (diff) | |
Merge branch 'develop' of JF/PineTime into master
Diffstat (limited to 'src')
59 files changed, 1440 insertions, 528 deletions
diff --git a/src/BlinkApp/BlinkApp.cpp b/src/BlinkApp/BlinkApp.cpp deleted file mode 100644 index a988dfd..0000000 --- a/src/BlinkApp/BlinkApp.cpp +++ /dev/null @@ -1,25 +0,0 @@ -#include "BlinkApp.h" -#include <FreeRTOS.h> -#include <task.h> -#include <libraries/log/nrf_log.h> -#include <boards.h> - -using namespace Pinetime::Applications; - -void BlinkApp::Start() { - if (pdPASS != xTaskCreate(BlinkApp::Process, "BlinkApp", 256, this, 0, &taskHandle)) - APP_ERROR_HANDLER(NRF_ERROR_NO_MEM); -} - -void BlinkApp::Process(void *instance) { - auto* app = static_cast<BlinkApp*>(instance); - - NRF_LOG_INFO("BlinkApp task started!"); - while (1) { -// NRF_LOG_INFO("BlinkApp task running!"); -// nrf_gpio_pin_toggle(22); -// nrf_gpio_pin_toggle(23); -// nrf_gpio_pin_toggle(14); - vTaskDelay(1000); - } -} diff --git a/src/BlinkApp/BlinkApp.h b/src/BlinkApp/BlinkApp.h deleted file mode 100644 index 15c863a..0000000 --- a/src/BlinkApp/BlinkApp.h +++ /dev/null @@ -1,15 +0,0 @@ -#pragma once -#include <FreeRTOS.h> -#include <task.h> - -namespace Pinetime { - namespace Applications { - class BlinkApp { - public: - void Start(); - private: - TaskHandle_t taskHandle; - static void Process(void* instance); - }; - } -} diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e60c2cf..4032d7e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -287,6 +287,8 @@ set(LVGL_SRC libs/lvgl/src/lv_objx/lv_bar.h libs/lvgl/src/lv_objx/lv_slider.h libs/lvgl/src/lv_objx/lv_slider.c + libs/lvgl/src/lv_objx/lv_ddlist.c + libs/lvgl/src/lv_objx/lv_ddlist.h ) list(APPEND IMAGE_FILES @@ -321,21 +323,24 @@ list(APPEND IMAGE_FILES list(APPEND SOURCE_FILES Logging/NrfLogger.cpp - BlinkApp/BlinkApp.cpp DisplayApp/DisplayApp.cpp DisplayApp/Screens/Screen.cpp DisplayApp/Screens/Clock.cpp - DisplayApp/Screens/Message.cpp DisplayApp/Screens/Tile.cpp DisplayApp/Screens/Meter.cpp DisplayApp/Screens/Gauge.cpp + DisplayApp/Screens/InfiniPaint.cpp + DisplayApp/Screens/DropDownDemo.cpp DisplayApp/Screens/Modal.cpp DisplayApp/Screens/BatteryIcon.cpp DisplayApp/Screens/BleIcon.cpp DisplayApp/Screens/Brightness.cpp - DisplayApp/Screens/ScreenList.cpp + DisplayApp/Screens/SystemInfo.cpp DisplayApp/Screens/Label.cpp DisplayApp/Screens/FirmwareUpdate.cpp + DisplayApp/Screens/Music.cpp + DisplayApp/Screens/FirmwareValidation.cpp + DisplayApp/Screens/ApplicationList.cpp main.cpp drivers/St7789.cpp drivers/SpiNorFlash.cpp @@ -356,15 +361,12 @@ list(APPEND SOURCE_FILES Components/Ble/DfuService.cpp Components/Ble/CurrentTimeService.cpp Components/Ble/AlertNotificationService.cpp + Components/Ble/MusicService.cpp + Components/FirmwareValidator/FirmwareValidator.cpp drivers/Cst816s.cpp FreeRTOS/port.c FreeRTOS/port_cmsis_systick.c FreeRTOS/port_cmsis.c - ${TINYCRYPT_SRC} - ${NIMBLE_SRC} - ${LVGL_SRC} - #${IMAGE_FILES} - ${SDK_SOURCE_FILES} DisplayApp/LittleVgl.cpp DisplayApp/Fonts/jetbrains_mono_extrabold_compressed.c @@ -375,8 +377,6 @@ list(APPEND SOURCE_FILES ) list(APPEND GRAPHICS_SOURCE_FILES - ${SDK_SOURCE_FILES} - # FreeRTOS FreeRTOS/port.c FreeRTOS/port_cmsis_systick.c @@ -397,22 +397,26 @@ list(APPEND GRAPHICS_SOURCE_FILES set(INCLUDE_FILES Logging/Logger.h Logging/NrfLogger.h - BlinkApp/BlinkApp.h DisplayApp/DisplayApp.h DisplayApp/TouchEvents.h DisplayApp/Screens/Screen.h DisplayApp/Screens/Clock.h - DisplayApp/Screens/Message.h DisplayApp/Screens/Tile.h DisplayApp/Screens/Meter.h DisplayApp/Screens/Gauge.h + DisplayApp/Screens/InfiniPaint.h + DisplayApp/Screens/DropDownDemo.h DisplayApp/Screens/Modal.h DisplayApp/Screens/BatteryIcon.h DisplayApp/Screens/BleIcon.cpp DisplayApp/Screens/Brightness.h + DisplayApp/Screens/SystemInfo.h DisplayApp/Screens/ScreenList.h DisplayApp/Screens/Label.h DisplayApp/Screens/FirmwareUpdate.h + DisplayApp/Screens/FirmwareValidation.h + DisplayApp/Screens/ApplicationList.h + DisplayApp/Apps.h drivers/St7789.h drivers/SpiNorFlash.h drivers/SpiMaster.h @@ -430,7 +434,8 @@ set(INCLUDE_FILES Components/Ble/CurrentTimeClient.h Components/Ble/AlertNotificationClient.h Components/Ble/DfuService.h - drivers/Cst816s.h + Components/FirmwareValidator/FirmwareValidator.h + drivers/Cst816s.h FreeRTOS/portmacro.h FreeRTOS/portmacro_cmsis.h libs/date/includes/date/tz.h @@ -558,10 +563,49 @@ if(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE "Release") endif() +# NRF SDK +add_library(nrf-sdk STATIC ${SDK_SOURCE_FILES}) +target_include_directories(nrf-sdk SYSTEM PUBLIC . ../) +target_include_directories(nrf-sdk SYSTEM PUBLIC ${INCLUDES_FROM_LIBS}) +target_compile_options(nrf-sdk PRIVATE + $<$<AND:$<COMPILE_LANGUAGE:C>,$<CONFIG:DEBUG>>: ${COMMON_FLAGS} -O0 -g3> + $<$<AND:$<COMPILE_LANGUAGE:C>,$<CONFIG:RELEASE>>: ${COMMON_FLAGS} -O3> + $<$<AND:$<COMPILE_LANGUAGE:CXX>,$<CONFIG:DEBUG>>: ${COMMON_FLAGS} -O0> + $<$<AND:$<COMPILE_LANGUAGE:CXX>,$<CONFIG:RELEASE>>: ${COMMON_FLAGS} -O3> + $<$<COMPILE_LANGUAGE:ASM>: -MP -MD -std=c99 -x assembler-with-cpp> + ) + +# NimBLE +add_library(nimble STATIC ${NIMBLE_SRC} ${TINYCRYPT_SRC}) +target_include_directories(nimble SYSTEM PUBLIC . ../) +target_include_directories(nimble SYSTEM PUBLIC ${INCLUDES_FROM_LIBS}) +target_compile_options(nimble PRIVATE + $<$<AND:$<COMPILE_LANGUAGE:C>,$<CONFIG:DEBUG>>: ${COMMON_FLAGS} -O0 -g3 -Wno-unused-but-set-variable -Wno-maybe-uninitialized> + $<$<AND:$<COMPILE_LANGUAGE:C>,$<CONFIG:RELEASE>>: ${COMMON_FLAGS} -O3 -Wno-unused-but-set-variable -Wno-maybe-uninitialized> + $<$<AND:$<COMPILE_LANGUAGE:CXX>,$<CONFIG:DEBUG>>: ${COMMON_FLAGS} -O0 -g3 -Wno-unused-but-set-variable -Wno-maybe-uninitialized> + $<$<AND:$<COMPILE_LANGUAGE:CXX>,$<CONFIG:RELEASE>>: ${COMMON_FLAGS} -O3 -Wno-unused-but-set-variable -Wno-maybe-uninitialized> + $<$<COMPILE_LANGUAGE:ASM>: -MP -MD -std=c99 -x assembler-with-cpp> + ) + +# lvgl +add_library(lvgl STATIC ${LVGL_SRC}) +target_include_directories(lvgl SYSTEM PUBLIC . ../) +target_include_directories(lvgl SYSTEM PUBLIC ${INCLUDES_FROM_LIBS}) +target_compile_options(lvgl PRIVATE + $<$<AND:$<COMPILE_LANGUAGE:C>,$<CONFIG:DEBUG>>: ${COMMON_FLAGS} -O0 -g3> + $<$<AND:$<COMPILE_LANGUAGE:C>,$<CONFIG:RELEASE>>: ${COMMON_FLAGS} -O3> + $<$<AND:$<COMPILE_LANGUAGE:CXX>,$<CONFIG:DEBUG>>: ${COMMON_FLAGS} -O0 -g3> + $<$<AND:$<COMPILE_LANGUAGE:CXX>,$<CONFIG:RELEASE>>: ${COMMON_FLAGS} -O3> + $<$<COMPILE_LANGUAGE:ASM>: -MP -MD -std=c99 -x assembler-with-cpp> + ) + # Build autonomous binary (without support for bootloader) set(EXECUTABLE_NAME "pinetime-app") +set(EXECUTABLE_FILE_NAME ${EXECUTABLE_NAME}-${pinetime_VERSION_MAJOR}.${pinetime_VERSION_MINOR}.${pinetime_VERSION_PATCH}) set(NRF5_LINKER_SCRIPT "${CMAKE_SOURCE_DIR}/gcc_nrf52.ld") add_executable(${EXECUTABLE_NAME} ${SOURCE_FILES}) +set_target_properties(${EXECUTABLE_NAME} PROPERTIES OUTPUT_NAME ${EXECUTABLE_FILE_NAME}) +target_link_libraries(${EXECUTABLE_NAME} nimble nrf-sdk lvgl) target_compile_options(${EXECUTABLE_NAME} PUBLIC $<$<AND:$<COMPILE_LANGUAGE:C>,$<CONFIG:DEBUG>>: ${COMMON_FLAGS} -O0 -g3> $<$<AND:$<COMPILE_LANGUAGE:C>,$<CONFIG:RELEASE>>: ${COMMON_FLAGS} -O3> @@ -572,24 +616,28 @@ target_compile_options(${EXECUTABLE_NAME} PUBLIC set_target_properties(${EXECUTABLE_NAME} PROPERTIES SUFFIX ".out" - LINK_FLAGS "-mthumb -mabi=aapcs -std=gnu++98 -std=c99 -L ${NRF5_SDK_PATH}/modules/nrfx/mdk -T${NRF5_LINKER_SCRIPT} -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 -Wl,--gc-sections --specs=nano.specs -lc -lnosys -lm -Wl,-Map=${EXECUTABLE_NAME}.map" + LINK_FLAGS "-mthumb -mabi=aapcs -std=gnu++98 -std=c99 -L ${NRF5_SDK_PATH}/modules/nrfx/mdk -T${NRF5_LINKER_SCRIPT} -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 -Wl,--gc-sections --specs=nano.specs -lc -lnosys -lm -Wl,-Map=${EXECUTABLE_FILE_NAME}.map" CXX_STANDARD 11 C_STANDARD 99 ) add_custom_command(TARGET ${EXECUTABLE_NAME} POST_BUILD - COMMAND ${CMAKE_SIZE_UTIL} ${EXECUTABLE_NAME}.out - COMMAND ${CMAKE_OBJCOPY} -O binary ${EXECUTABLE_NAME}.out "${EXECUTABLE_NAME}.bin" - COMMAND ${CMAKE_OBJCOPY} -O ihex ${EXECUTABLE_NAME}.out "${EXECUTABLE_NAME}.hex" - COMMENT "post build steps for ${EXECUTABLE_NAME}") + COMMAND ${CMAKE_SIZE_UTIL} ${EXECUTABLE_FILE_NAME}.out + COMMAND ${CMAKE_OBJCOPY} -O binary ${EXECUTABLE_FILE_NAME}.out "${EXECUTABLE_FILE_NAME}.bin" + COMMAND ${CMAKE_OBJCOPY} -O ihex ${EXECUTABLE_FILE_NAME}.out "${EXECUTABLE_FILE_NAME}.hex" + COMMENT "post build steps for ${EXECUTABLE_FILE_NAME}") # Build binary intended to be used by bootloader set(EXECUTABLE_MCUBOOT_NAME "pinetime-mcuboot-app") -set(EXECUTABLE_MCUBOOT_WITH_BOOTLOADER_NAME "pinetime-mcuboot-app-wth-bootloader") +set(EXECUTABLE_MCUBOOT_FILE_NAME ${EXECUTABLE_MCUBOOT_NAME}-${pinetime_VERSION_MAJOR}.${pinetime_VERSION_MINOR}.${pinetime_VERSION_PATCH}) +set(IMAGE_MCUBOOT_FILE_NAME image-${pinetime_VERSION_MAJOR}.${pinetime_VERSION_MINOR}.${pinetime_VERSION_PATCH}.bin) +set(DFU_FILE_NAME dfu-${pinetime_VERSION_MAJOR}.${pinetime_VERSION_MINOR}.${pinetime_VERSION_PATCH}.zip) set(NRF5_LINKER_SCRIPT_MCUBOOT "${CMAKE_SOURCE_DIR}/gcc_nrf52-mcuboot.ld") add_executable(${EXECUTABLE_MCUBOOT_NAME} ${SOURCE_FILES}) +target_link_libraries(${EXECUTABLE_MCUBOOT_NAME} nimble nrf-sdk lvgl) +set_target_properties(${EXECUTABLE_MCUBOOT_NAME} PROPERTIES OUTPUT_NAME ${EXECUTABLE_MCUBOOT_FILE_NAME}) target_compile_options(${EXECUTABLE_MCUBOOT_NAME} PUBLIC $<$<AND:$<COMPILE_LANGUAGE:C>,$<CONFIG:DEBUG>>: ${COMMON_FLAGS} -O0 -g3> $<$<AND:$<COMPILE_LANGUAGE:C>,$<CONFIG:RELEASE>>: ${COMMON_FLAGS} -O3> @@ -600,22 +648,25 @@ target_compile_options(${EXECUTABLE_MCUBOOT_NAME} PUBLIC set_target_properties(${EXECUTABLE_MCUBOOT_NAME} PROPERTIES SUFFIX ".out" - LINK_FLAGS "-mthumb -mabi=aapcs -std=gnu++98 -std=c99 -L ${NRF5_SDK_PATH}/modules/nrfx/mdk -T${NRF5_LINKER_SCRIPT_MCUBOOT} -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 -Wl,--gc-sections --specs=nano.specs -lc -lnosys -lm -Wl,-Map=${EXECUTABLE_MCUBOOT_NAME}.map" + LINK_FLAGS "-mthumb -mabi=aapcs -std=gnu++98 -std=c99 -L ${NRF5_SDK_PATH}/modules/nrfx/mdk -T${NRF5_LINKER_SCRIPT_MCUBOOT} -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 -Wl,--gc-sections --specs=nano.specs -lc -lnosys -lm -Wl,-Map=${EXECUTABLE_MCUBOOT_FILE_NAME}.map" CXX_STANDARD 11 C_STANDARD 99 ) add_custom_command(TARGET ${EXECUTABLE_MCUBOOT_NAME} POST_BUILD - COMMAND ${CMAKE_SIZE_UTIL} ${EXECUTABLE_MCUBOOT_NAME}.out - COMMAND ${CMAKE_OBJCOPY} -O binary ${EXECUTABLE_MCUBOOT_NAME}.out "${EXECUTABLE_MCUBOOT_NAME}.bin" - COMMAND ${CMAKE_OBJCOPY} -O ihex ${EXECUTABLE_MCUBOOT_NAME}.out "${EXECUTABLE_MCUBOOT_NAME}.hex" - COMMENT "post build steps for ${EXECUTABLE_MCUBOOT_NAME}" + COMMAND ${CMAKE_SIZE_UTIL} ${EXECUTABLE_MCUBOOT_FILE_NAME}.out + COMMAND ${CMAKE_OBJCOPY} -O binary ${EXECUTABLE_MCUBOOT_FILE_NAME}.out "${EXECUTABLE_MCUBOOT_FILE_NAME}.bin" + COMMAND ${CMAKE_OBJCOPY} -O ihex ${EXECUTABLE_MCUBOOT_FILE_NAME}.out "${EXECUTABLE_MCUBOOT_FILE_NAME}.hex" + COMMENT "post build steps for ${EXECUTABLE_MCUBOOT_FILE_NAME}" ) # Build binary that writes the graphic assets for the bootloader set(EXECUTABLE_GRAPHICS_NAME "pinetime-graphics") +set(EXECUTABLE_GRAPHICS_FILE_NAME ${EXECUTABLE_GRAPHICS_NAME}-${pinetime_VERSION_MAJOR}.${pinetime_VERSION_MINOR}.${pinetime_VERSION_PATCH}) add_executable(${EXECUTABLE_GRAPHICS_NAME} ${GRAPHICS_SOURCE_FILES}) +target_link_libraries(${EXECUTABLE_GRAPHICS_NAME} nrf-sdk) +set_target_properties(${EXECUTABLE_GRAPHICS_NAME} PROPERTIES OUTPUT_NAME ${EXECUTABLE_GRAPHICS_FILE_NAME}) target_compile_options(${EXECUTABLE_GRAPHICS_NAME} PUBLIC $<$<AND:$<COMPILE_LANGUAGE:C>,$<CONFIG:DEBUG>>: ${COMMON_FLAGS} -O0 -g3> $<$<AND:$<COMPILE_LANGUAGE:C>,$<CONFIG:RELEASE>>: ${COMMON_FLAGS} -O3> @@ -626,17 +677,17 @@ target_compile_options(${EXECUTABLE_GRAPHICS_NAME} PUBLIC set_target_properties(${EXECUTABLE_GRAPHICS_NAME} PROPERTIES SUFFIX ".out" - LINK_FLAGS "-mthumb -mabi=aapcs -std=gnu++98 -std=c99 -L ${NRF5_SDK_PATH}/modules/nrfx/mdk -T${NRF5_LINKER_SCRIPT} -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 -Wl,--gc-sections --specs=nano.specs -lc -lnosys -lm -Wl,-Map=${EXECUTABLE_GRAPHICS_NAME}.map" + LINK_FLAGS "-mthumb -mabi=aapcs -std=gnu++98 -std=c99 -L ${NRF5_SDK_PATH}/modules/nrfx/mdk -T${NRF5_LINKER_SCRIPT} -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 -Wl,--gc-sections --specs=nano.specs -lc -lnosys -lm -Wl,-Map=${EXECUTABLE_GRAPHICS_FILE_NAME}.map" CXX_STANDARD 11 C_STANDARD 99 ) add_custom_command(TARGET ${EXECUTABLE_GRAPHICS_NAME} POST_BUILD - COMMAND ${CMAKE_SIZE_UTIL} ${EXECUTABLE_GRAPHICS_NAME}.out - COMMAND ${CMAKE_OBJCOPY} -O binary ${EXECUTABLE_GRAPHICS_NAME}.out "${EXECUTABLE_GRAPHICS_NAME}.bin" - COMMAND ${CMAKE_OBJCOPY} -O ihex ${EXECUTABLE_GRAPHICS_NAME}.out "${EXECUTABLE_GRAPHICS_NAME}.hex" - COMMENT "post build steps for ${EXECUTABLE_GRAPHICS_NAME}" + COMMAND ${CMAKE_SIZE_UTIL} ${EXECUTABLE_GRAPHICS_FILE_NAME}.out + COMMAND ${CMAKE_OBJCOPY} -O binary ${EXECUTABLE_GRAPHICS_FILE_NAME}.out "${EXECUTABLE_GRAPHICS_FILE_NAME}.bin" + COMMAND ${CMAKE_OBJCOPY} -O ihex ${EXECUTABLE_GRAPHICS_FILE_NAME}.out "${EXECUTABLE_GRAPHICS_FILE_NAME}.hex" + COMMENT "post build steps for ${EXECUTABLE_GRAPHICS_FILE_NAME}" ) # FLASH @@ -675,3 +726,4 @@ elseif(USE_OPENOCD) ) endif() + diff --git a/src/Components/Ble/AlertNotificationClient.cpp b/src/Components/Ble/AlertNotificationClient.cpp index b65e019..3e4b495 100644 --- a/src/Components/Ble/AlertNotificationClient.cpp +++ b/src/Components/Ble/AlertNotificationClient.cpp @@ -116,7 +116,7 @@ void AlertNotificationClient::OnNotification(ble_gap_event *event) { char *s = (char *) &data[3]; auto messageSize = min(maxMessageSize, (bufferSize-3)); - for (int i = 0; i < messageSize-1; i++) { + for (uint i = 0; i < messageSize-1; i++) { if (s[i] == 0x00) { s[i] = 0x0A; } diff --git a/src/Components/Ble/AlertNotificationService.cpp b/src/Components/Ble/AlertNotificationService.cpp index 0faa17c..ce2f7dd 100644 --- a/src/Components/Ble/AlertNotificationService.cpp +++ b/src/Components/Ble/AlertNotificationService.cpp @@ -26,8 +26,8 @@ void AlertNotificationService::Init() { ASSERT(res == 0); } -AlertNotificationService::AlertNotificationService ( Pinetime::System::SystemTask& systemTask, Pinetime::Controllers::NotificationManager& notificationManager ) : m_systemTask{systemTask}, m_notificationManager{notificationManager}, - characteristicDefinition{ +AlertNotificationService::AlertNotificationService ( System::SystemTask& systemTask, NotificationManager& notificationManager ) + : characteristicDefinition{ { .uuid = (ble_uuid_t *) &ansCharUuid, .access_cb = AlertNotificationCallback, @@ -48,8 +48,7 @@ AlertNotificationService::AlertNotificationService ( Pinetime::System::SystemTas { 0 }, - } -{ + }, m_systemTask{systemTask}, m_notificationManager{notificationManager} { } int AlertNotificationService::OnAlert(uint16_t conn_handle, uint16_t attr_handle, @@ -67,7 +66,7 @@ int AlertNotificationService::OnAlert(uint16_t conn_handle, uint16_t attr_handle char *s = (char *) &data[3]; auto messageSize = min(maxMessageSize, (bufferSize-3)); - for (int i = 0; i < messageSize-1; i++) { + for (uint i = 0; i < messageSize-1; i++) { if (s[i] == 0x00) { s[i] = 0x0A; } diff --git a/src/Components/Ble/CurrentTimeService.cpp b/src/Components/Ble/CurrentTimeService.cpp index 80ad9c2..3a6264e 100644 --- a/src/Components/Ble/CurrentTimeService.cpp +++ b/src/Components/Ble/CurrentTimeService.cpp @@ -57,7 +57,7 @@ int CurrentTimeService::OnTimeAccessed(uint16_t conn_handle, uint16_t attr_handl return 0; } -CurrentTimeService::CurrentTimeService(DateTime &dateTimeController) : m_dateTimeController{dateTimeController}, +CurrentTimeService::CurrentTimeService(DateTime &dateTimeController) : characteristicDefinition{ { .uuid = (ble_uuid_t *) &ctChrUuid, @@ -80,8 +80,7 @@ CurrentTimeService::CurrentTimeService(DateTime &dateTimeController) : m_dateTim { 0 }, - } - { + }, m_dateTimeController{dateTimeController} { } diff --git a/src/Components/Ble/DeviceInformationService.cpp b/src/Components/Ble/DeviceInformationService.cpp index c1d5554..406db1c 100644 --- a/src/Components/Ble/DeviceInformationService.cpp +++ b/src/Components/Ble/DeviceInformationService.cpp @@ -8,6 +8,8 @@ constexpr ble_uuid16_t DeviceInformationService::serialNumberUuid; constexpr ble_uuid16_t DeviceInformationService::fwRevisionUuid; constexpr ble_uuid16_t DeviceInformationService::deviceInfoUuid; constexpr ble_uuid16_t DeviceInformationService::hwRevisionUuid; +constexpr ble_uuid16_t DeviceInformationService::swRevisionUuid; + int DeviceInformationCallback(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg) { auto deviceInformationService = static_cast<DeviceInformationService*>(arg); @@ -44,6 +46,9 @@ int DeviceInformationService::OnDeviceInfoRequested(uint16_t conn_handle, uint16 case hwRevisionId: str = hwRevision; break; + case swRevisionId: + str = swRevision; + break; default: return BLE_ATT_ERR_UNLIKELY; } @@ -85,6 +90,12 @@ DeviceInformationService::DeviceInformationService() : .flags = BLE_GATT_CHR_F_READ, }, { + .uuid = (ble_uuid_t *) &swRevisionUuid, + .access_cb = DeviceInformationCallback, + .arg = this, + .flags = BLE_GATT_CHR_F_READ, + }, + { 0 } }, diff --git a/src/Components/Ble/DeviceInformationService.h b/src/Components/Ble/DeviceInformationService.h index d768da8..25ab840 100644 --- a/src/Components/Ble/DeviceInformationService.h +++ b/src/Components/Ble/DeviceInformationService.h @@ -3,6 +3,7 @@ #include <array> #include <host/ble_gap.h> +#include <Version.h> namespace Pinetime { namespace Controllers { @@ -21,12 +22,15 @@ namespace Pinetime { static constexpr uint16_t serialNumberId {0x2a25}; static constexpr uint16_t fwRevisionId {0x2a26}; static constexpr uint16_t hwRevisionId {0x2a27}; + static constexpr uint16_t swRevisionId {0x2a28}; + + static constexpr const char* manufacturerName = "PINE64"; + static constexpr const char* modelNumber = "PineTime"; + static constexpr const char* hwRevision = "1.0.0"; + static constexpr const char* serialNumber = "0"; + static constexpr const char* fwRevision = Version::VersionString(); + static constexpr const char* swRevision = "InfiniTime"; - static constexpr char* manufacturerName = "Codingfield"; - static constexpr char* modelNumber = "1"; - static constexpr char* serialNumber = "9.8.7.6.5.4"; - static constexpr char* fwRevision = "0.7.0"; - static constexpr char* hwRevision = "1.0.0"; static constexpr ble_uuid16_t deviceInfoUuid { .u { .type = BLE_UUID_TYPE_16 }, @@ -58,7 +62,12 @@ namespace Pinetime { .value = hwRevisionId }; - struct ble_gatt_chr_def characteristicDefinition[6]; + static constexpr ble_uuid16_t swRevisionUuid { + .u {.type = BLE_UUID_TYPE_16}, + .value = swRevisionId + }; + + struct ble_gatt_chr_def characteristicDefinition[7]; struct ble_gatt_svc_def serviceDefinition[2]; diff --git a/src/Components/Ble/DfuService.cpp b/src/Components/Ble/DfuService.cpp index c6d8493..fcbefdd 100644 --- a/src/Components/Ble/DfuService.cpp +++ b/src/Components/Ble/DfuService.cpp @@ -394,14 +394,14 @@ void DfuService::DfuImage::WriteMagicNumber() { } void DfuService::DfuImage::Erase() { - for (int erased = 0; erased < maxSize; erased += 0x1000) { + for (size_t erased = 0; erased < maxSize; erased += 0x1000) { spiNorFlash.SectorErase(writeOffset + erased); } } bool DfuService::DfuImage::Validate() { uint32_t chunkSize = 200; - int currentOffset = 0; + size_t currentOffset = 0; uint16_t crc = 0; bool first = true; diff --git a/src/Components/Ble/MusicService.cpp b/src/Components/Ble/MusicService.cpp new file mode 100644 index 0000000..b5fa535 --- /dev/null +++ b/src/Components/Ble/MusicService.cpp @@ -0,0 +1,129 @@ +#include <SystemTask/SystemTask.h> +#include "MusicService.h" + +int MSCallback(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg) { + auto musicService = static_cast<Pinetime::Controllers::MusicService*>(arg); + return musicService->OnCommand(conn_handle, attr_handle, ctxt); +} + +Pinetime::Controllers::MusicService::MusicService(Pinetime::System::SystemTask &system) : m_system(system) +{ + msUuid.value[11] = msId[0]; + msUuid.value[12] = msId[1]; + msEventCharUuid.value[11] = msEventCharId[0]; + msEventCharUuid.value[12] = msEventCharId[1]; + msStatusCharUuid.value[11] = msStatusCharId[0]; + msStatusCharUuid.value[12] = msStatusCharId[1]; + msTrackCharUuid.value[11] = msTrackCharId[0]; + msTrackCharUuid.value[12] = msTrackCharId[1]; + msArtistCharUuid.value[11] = msArtistCharId[0]; + msArtistCharUuid.value[12] = msArtistCharId[1]; + msAlbumCharUuid.value[11] = msAlbumCharId[0]; + msAlbumCharUuid.value[12] = msAlbumCharId[1]; + + characteristicDefinition[0] = { .uuid = (ble_uuid_t*)(&msEventCharUuid), + .access_cb = MSCallback, + .arg = this, + .flags = BLE_GATT_CHR_F_NOTIFY, + .val_handle = &m_eventHandle + }; + characteristicDefinition[1] = { .uuid = (ble_uuid_t*)(&msStatusCharUuid), + .access_cb = MSCallback, + .arg = this, + .flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ + }; + characteristicDefinition[2] = { .uuid = (ble_uuid_t*)(&msTrackCharUuid), + .access_cb = MSCallback, + .arg = this, + .flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ + }; + characteristicDefinition[3] = { .uuid = (ble_uuid_t*)(&msArtistCharUuid), + .access_cb = MSCallback, + .arg = this, + .flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ + }; + characteristicDefinition[4] = { .uuid = (ble_uuid_t*)(&msAlbumCharUuid), + .access_cb = MSCallback, + .arg = this, + .flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ + }; + characteristicDefinition[5] = {0}; + + serviceDefinition[0] = { + .type = BLE_GATT_SVC_TYPE_PRIMARY, + .uuid = (ble_uuid_t *) &msUuid, + .characteristics = characteristicDefinition + }; + serviceDefinition[1] = {0}; + + m_artist = "Waiting for"; + m_album = ""; + m_track = "track information..."; +} + +void Pinetime::Controllers::MusicService::Init() +{ + int res = 0; + res = ble_gatts_count_cfg(serviceDefinition); + ASSERT(res == 0); + + res = ble_gatts_add_svcs(serviceDefinition); + ASSERT(res == 0); +} + +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); + uint8_t data[notifSize + 1]; + data[notifSize] = '\0'; + os_mbuf_copydata(ctxt->om, 0, notifSize, data); + char *s = (char *) &data[0]; + NRF_LOG_INFO("DATA : %s", s); + if (ble_uuid_cmp(ctxt->chr->uuid, (ble_uuid_t *)&msArtistCharUuid) == 0) { + m_artist = s; + } else if (ble_uuid_cmp(ctxt->chr->uuid, (ble_uuid_t *)&msTrackCharUuid) == 0) { + m_track = s; + } else if (ble_uuid_cmp(ctxt->chr->uuid, (ble_uuid_t *)&msAlbumCharUuid) == 0) { + m_album = s; + } else if (ble_uuid_cmp(ctxt->chr->uuid, (ble_uuid_t *)&msStatusCharUuid) == 0) { + m_status = s[0]; + } + } + return 0; +} + +std::string Pinetime::Controllers::MusicService::album() +{ + return m_album; +} + +std::string Pinetime::Controllers::MusicService::artist() +{ + return m_artist; +} + +std::string Pinetime::Controllers::MusicService::track() +{ + return m_track; +} + +unsigned char Pinetime::Controllers::MusicService::status() +{ + return m_status; +} + +void Pinetime::Controllers::MusicService::event(char event) +{ + auto *om = ble_hs_mbuf_from_flat(&event, 1); + + uint16_t connectionHandle = m_system.nimble().connHandle(); + + if (connectionHandle == 0 || connectionHandle == BLE_HS_CONN_HANDLE_NONE) { + return; + } + + ble_gattc_notify_custom(connectionHandle, m_eventHandle, om); +} + diff --git a/src/Components/Ble/MusicService.h b/src/Components/Ble/MusicService.h new file mode 100644 index 0000000..ab6db57 --- /dev/null +++ b/src/Components/Ble/MusicService.h @@ -0,0 +1,92 @@ +#pragma once + +#include <cstdint> +#include <array> +#include <host/ble_gap.h> +#include <host/ble_uuid.h> +#include <string> + +//c7e50000-78fc-48fe-8e23-43b37a1942d0 +#define MUSIC_SERVICE_UUID_BASE {0xd0, 0x42, 0x19, 0x3a, 0x3b, 0x43, 0x23, 0x8e, 0xfe, 0x48, 0xfc, 0x78, 0x00, 0x00, 0xe5, 0xc7} + +namespace Pinetime { + namespace System { + class SystemTask; + } + namespace Controllers { + + class MusicService { + public: + MusicService(Pinetime::System::SystemTask &system); + void Init(); + int OnCommand(uint16_t conn_handle, uint16_t attr_handle, + struct ble_gatt_access_ctxt *ctxt); + + std::string artist(); + std::string track(); + std::string album(); + unsigned char status(); + + void event(char event); + + static const char EVENT_MUSIC_OPEN = 0xe0; + static const char EVENT_MUSIC_PLAY = 0x00; + static const char EVENT_MUSIC_PAUSE = 0x01; + static const char EVENT_MUSIC_NEXT = 0x03; + static const char EVENT_MUSIC_PREV = 0x04; + static const char EVENT_MUSIC_VOLUP = 0x05; + static const char EVENT_MUSIC_VOLDOWN = 0x06; + static const char STATUS_MUSIC_PAUSED = 0x00; + static const char STATUS_MUSIC_PLAYING = 0x01; + + private: + static constexpr uint8_t msId[2] = {0x00, 0x01}; + static constexpr uint8_t msEventCharId[2] = {0x00, 0x02}; + static constexpr uint8_t msStatusCharId[2] = {0x00, 0x03}; + static constexpr uint8_t msArtistCharId[2] = {0x00, 0x04}; + static constexpr uint8_t msTrackCharId[2] = {0x00, 0x05}; + static constexpr uint8_t msAlbumCharId[2] = {0x00, 0x06}; + + ble_uuid128_t msUuid { + .u = { .type = BLE_UUID_TYPE_128 }, + .value = MUSIC_SERVICE_UUID_BASE + }; + + ble_uuid128_t msEventCharUuid { + .u = { .type = BLE_UUID_TYPE_128 }, + .value = MUSIC_SERVICE_UUID_BASE + }; + ble_uuid128_t msStatusCharUuid { + .u = { .type = BLE_UUID_TYPE_128 }, + .value = MUSIC_SERVICE_UUID_BASE + }; + ble_uuid128_t msArtistCharUuid { + .u = { .type = BLE_UUID_TYPE_128 }, + .value = MUSIC_SERVICE_UUID_BASE + }; + ble_uuid128_t msTrackCharUuid { + .u = { .type = BLE_UUID_TYPE_128 }, + .value = MUSIC_SERVICE_UUID_BASE + }; + ble_uuid128_t msAlbumCharUuid { + .u = { .type = BLE_UUID_TYPE_128 }, + .value = MUSIC_SERVICE_UUID_BASE + }; + + struct ble_gatt_chr_def characteristicDefinition[6]; + struct ble_gatt_svc_def serviceDefinition[2]; + + uint16_t m_eventHandle; + + std::string m_artist; + std::string m_album; + std::string m_track; + + unsigned char m_status; + + Pinetime::System::SystemTask& m_system; + + }; + } +} + diff --git a/src/Components/Ble/NimbleController.cpp b/src/Components/Ble/NimbleController.cpp index 561dbce..7dde9d0 100644 --- a/src/Components/Ble/NimbleController.cpp +++ b/src/Components/Ble/NimbleController.cpp @@ -6,6 +6,7 @@ #include <hal/nrf_rtc.h> #include "NimbleController.h" +#include "MusicService.h" #include <services/gatt/ble_svc_gatt.h> #include <services/gap/ble_svc_gap.h> #include <host/util/util.h> @@ -35,7 +36,8 @@ NimbleController::NimbleController(Pinetime::System::SystemTask& systemTask, currentTimeClient{dateTimeController}, anService{systemTask, notificationManager}, alertNotificationClient{systemTask, notificationManager}, - currentTimeService{dateTimeController} { + currentTimeService{dateTimeController}, + musicService{systemTask} { } @@ -80,6 +82,7 @@ void NimbleController::Init() { deviceInformationService.Init(); currentTimeClient.Init(); currentTimeService.Init(); + musicService.Init(); anService.Init(); @@ -104,7 +107,7 @@ void NimbleController::Init() { void NimbleController::StartAdvertising() { if(ble_gap_adv_active()) return; - ble_svc_gap_device_name_set("Pinetime-JF"); + ble_svc_gap_device_name_set(deviceName); /* set adv parameters */ struct ble_gap_adv_params adv_params; @@ -132,18 +135,17 @@ void NimbleController::StartAdvertising() { fields.uuids128_is_complete = 1; fields.tx_pwr_lvl = BLE_HS_ADV_TX_PWR_LVL_AUTO; - rsp_fields.name = (uint8_t *)"Pinetime-JF"; - rsp_fields.name_len = strlen("Pinetime-JF"); + rsp_fields.name = (uint8_t *)deviceName; + rsp_fields.name_len = strlen(deviceName); rsp_fields.name_is_complete = 1; - int res; - res = ble_gap_adv_set_fields(&fields); + ble_gap_adv_set_fields(&fields); // ASSERT(res == 0); // TODO this one sometimes fails with error 22 (notsync) - res = ble_gap_adv_rsp_set_fields(&rsp_fields); + ble_gap_adv_rsp_set_fields(&rsp_fields); // ASSERT(res == 0); - res = ble_gap_adv_start(addrType, NULL, 180000, + ble_gap_adv_start(addrType, NULL, 180000, &adv_params, GAPEventCallback, this); // ASSERT(res == 0);// TODO I've disabled these ASSERT as they sometime asserts and reset the mcu. // For now, the advertising is restarted as soon as it ends. There may be a race condition @@ -326,5 +328,7 @@ void NimbleController::StartDiscovery() { } - +uint16_t NimbleController::connHandle() { + return connectionHandle; +} diff --git a/src/Components/Ble/NimbleController.h b/src/Components/Ble/NimbleController.h index cf50d78..50b8b0b 100644 --- a/src/Components/Ble/NimbleController.h +++ b/src/Components/Ble/NimbleController.h @@ -7,6 +7,7 @@ #include "CurrentTimeClient.h" #include "DfuService.h" #include "CurrentTimeService.h" +#include "MusicService.h" #include <host/ble_gap.h> namespace Pinetime { @@ -15,6 +16,7 @@ namespace Pinetime { } namespace Controllers { class DateTime; + class NimbleController { public: @@ -35,8 +37,13 @@ namespace Pinetime { uint16_t characteristicValueHandle, const ble_gatt_dsc *descriptor); void StartDiscovery(); + + Pinetime::Controllers::MusicService& music() {return musicService;}; + + uint16_t connHandle(); + private: - static constexpr char* deviceName = "Pinetime-JF"; + static constexpr const char* deviceName = "InfiniTime"; Pinetime::System::SystemTask& systemTask; Pinetime::Controllers::Ble& bleController; DateTime& dateTimeController; @@ -49,9 +56,10 @@ namespace Pinetime { AlertNotificationService anService; AlertNotificationClient alertNotificationClient; CurrentTimeService currentTimeService; + MusicService musicService; uint8_t addrType; // 1 = Random, 0 = PUBLIC - uint16_t connectionHandle; + uint16_t connectionHandle = 0; ble_uuid128_t dfuServiceUuid { .u { .type = BLE_UUID_TYPE_128}, diff --git a/src/Components/FirmwareValidator/FirmwareValidator.cpp b/src/Components/FirmwareValidator/FirmwareValidator.cpp new file mode 100644 index 0000000..244d5c0 --- /dev/null +++ b/src/Components/FirmwareValidator/FirmwareValidator.cpp @@ -0,0 +1,20 @@ +#include <drivers/InternalFlash.h> +#include <hal/nrf_rtc.h> + +#include "FirmwareValidator.h" + +using namespace Pinetime::Controllers; + +bool FirmwareValidator::IsValidated() const { + auto* imageOkPtr = reinterpret_cast<uint32_t *>(validBitAdress); + return (*imageOkPtr) == validBitValue; +} + +void FirmwareValidator::Validate() { + if(!IsValidated()) + Pinetime::Drivers::InternalFlash::WriteWord(validBitAdress, validBitValue); +} + +void FirmwareValidator::Reset() { + NVIC_SystemReset(); +} diff --git a/src/Components/FirmwareValidator/FirmwareValidator.h b/src/Components/FirmwareValidator/FirmwareValidator.h new file mode 100644 index 0000000..aa576d8 --- /dev/null +++ b/src/Components/FirmwareValidator/FirmwareValidator.h @@ -0,0 +1,18 @@ +#pragma once + +#include <cstdint> + +namespace Pinetime { + namespace Controllers { + class FirmwareValidator { + public: + void Validate(); + bool IsValidated() const; + + void Reset(); + private: + static constexpr uint32_t validBitAdress {0x7BFE8}; + static constexpr uint32_t validBitValue {1}; + }; + } +} diff --git a/src/DisplayApp/Apps.h b/src/DisplayApp/Apps.h new file mode 100644 index 0000000..3842e4e --- /dev/null +++ b/src/DisplayApp/Apps.h @@ -0,0 +1,7 @@ +#pragma once + +namespace Pinetime { + namespace Applications { + enum class Apps {None, Launcher, Clock, SysInfo, Meter, Gauge, Brightness, Music, FirmwareValidation, Paint}; + } +}
\ No newline at end of file diff --git a/src/DisplayApp/DisplayApp.cpp b/src/DisplayApp/DisplayApp.cpp index 8e35ef5..f6138ec 100644 --- a/src/DisplayApp/DisplayApp.cpp +++ b/src/DisplayApp/DisplayApp.cpp @@ -2,21 +2,22 @@ #include <FreeRTOS.h> #include <task.h> #include <libraries/log/nrf_log.h> -#include <boards.h> #include <nrf_font.h> #include <queue.h> #include <Components/DateTime/DateTimeController.h> #include <drivers/Cst816s.h> #include <string> -#include <lvgl/lvgl.h> #include <DisplayApp/Screens/Tile.h> -#include <DisplayApp/Screens/Message.h> #include <DisplayApp/Screens/Meter.h> #include <DisplayApp/Screens/Gauge.h> #include <DisplayApp/Screens/Brightness.h> -#include <DisplayApp/Screens/ScreenList.h> +#include <DisplayApp/Screens/SystemInfo.h> +#include <DisplayApp/Screens/Music.h> #include <Components/Ble/NotificationManager.h> #include <DisplayApp/Screens/FirmwareUpdate.h> +#include <DisplayApp/Screens/ApplicationList.h> +#include <DisplayApp/Screens/FirmwareValidation.h> +#include <DisplayApp/Screens/InfiniPaint.h> #include "../SystemTask/SystemTask.h" using namespace Pinetime::Applications; @@ -79,6 +80,9 @@ void DisplayApp::Refresh() { RunningState(); queueTimeout = 20; break; + default: + queueTimeout = portMAX_DELAY; + break; } Messages msg; @@ -91,14 +95,10 @@ void DisplayApp::Refresh() { vTaskDelay(100); } lcd.DisplayOff(); - lcd.Sleep(); - touchPanel.Sleep(); + systemTask.PushMessage(System::SystemTask::Messages::OnDisplayTaskSleeping); state = States::Idle; break; case Messages::GoToRunning: - lcd.Wakeup(); - touchPanel.Wakeup(); - lcd.DisplayOn(); brightnessController.Restore(); state = States::Running; @@ -168,6 +168,15 @@ void DisplayApp::Refresh() { break; } } + + if(state != States::Idle && touchMode == TouchModes::Polling) { + auto info = touchPanel.GetTouchInfo(); + if(info.action == 2) {// 2 = contact + if(!currentScreen->OnTouchEvent(info.x, info.y)) { + lvgl.SetNewTapEvent(info.x, info.y); + } + } + } } void DisplayApp::RunningState() { @@ -179,16 +188,19 @@ void DisplayApp::RunningState() { onClockApp = false; switch(nextApp) { case Apps::None: - case Apps::Launcher: currentScreen.reset(new Screens::Tile(this)); break; + case Apps::Launcher: currentScreen.reset(new Screens::ApplicationList(this)); break; case Apps::Clock: currentScreen.reset(new Screens::Clock(this, dateTimeController, batteryController, bleController)); onClockApp = true; break; // case Apps::Test: currentScreen.reset(new Screens::Message(this)); break; - case Apps::SysInfo: currentScreen.reset(new Screens::ScreenList(this, dateTimeController, batteryController, brightnessController, bleController, watchdog)); break; + case Apps::SysInfo: currentScreen.reset(new Screens::SystemInfo(this, dateTimeController, batteryController, brightnessController, bleController, watchdog)); break; case Apps::Meter: currentScreen.reset(new Screens::Meter(this)); break; case Apps::Gauge: currentScreen.reset(new Screens::Gauge(this)); break; + case Apps::Paint: currentScreen.reset(new Screens::InfiniPaint(this, lvgl)); break; case Apps::Brightness : currentScreen.reset(new Screens::Brightness(this, brightnessController)); break; + case Apps::Music : currentScreen.reset(new Screens::Music(this, systemTask.nimble().music())); break; + case Apps::FirmwareValidation: currentScreen.reset(new Screens::FirmwareValidation(this, validator)); break; } nextApp = Apps::None; } @@ -214,7 +226,8 @@ TouchEvents DisplayApp::OnTouchEvent() { if(info.isTouch) { switch(info.gesture) { case Pinetime::Drivers::Cst816S::Gestures::SingleTap: - lvgl.SetNewTapEvent(info.x, info.y); + if(touchMode == TouchModes::Gestures) + lvgl.SetNewTapEvent(info.x, info.y); return TouchEvents::Tap; case Pinetime::Drivers::Cst816S::Gestures::LongPress: return TouchEvents::LongTap; @@ -236,7 +249,7 @@ TouchEvents DisplayApp::OnTouchEvent() { return TouchEvents::None; } -void DisplayApp::StartApp(DisplayApp::Apps app) { +void DisplayApp::StartApp(Apps app) { nextApp = app; } @@ -252,3 +265,7 @@ void DisplayApp::SetFullRefresh(DisplayApp::FullRefreshDirections direction) { } } + +void DisplayApp::SetTouchMode(DisplayApp::TouchModes mode) { + touchMode = mode; +} diff --git a/src/DisplayApp/DisplayApp.h b/src/DisplayApp/DisplayApp.h index 36f9315..345e06d 100644 --- a/src/DisplayApp/DisplayApp.h +++ b/src/DisplayApp/DisplayApp.h @@ -17,7 +17,9 @@ #include <drivers/Watchdog.h> #include <DisplayApp/Screens/Modal.h> #include <Components/Ble/NotificationManager.h> +#include <Components/FirmwareValidator/FirmwareValidator.h> #include "TouchEvents.h" +#include "Apps.h" namespace Pinetime { @@ -28,11 +30,11 @@ namespace Pinetime { class DisplayApp { public: enum class States {Idle, Running}; - enum class Messages : uint8_t {GoToSleep, GoToRunning, UpdateDateTime, UpdateBleConnection, UpdateBatteryLevel, TouchEvent, SwitchScreen,ButtonPushed, - NewNotification, BleFirmwareUpdateStarted, BleFirmwareUpdateFinished - }; - enum class FullRefreshDirections { None, Up, Down }; + enum class Messages : uint8_t {GoToSleep, GoToRunning, UpdateDateTime, UpdateBleConnection, UpdateBatteryLevel, TouchEvent, ButtonPushed, + NewNotification, BleFirmwareUpdateStarted }; + enum class FullRefreshDirections { None, Up, Down }; + enum class TouchModes { Gestures, Polling }; DisplayApp(Drivers::St7789 &lcd, Components::LittleVgl &lvgl, Drivers::Cst816S &, Controllers::Battery &batteryController, Controllers::Ble &bleController, @@ -42,10 +44,11 @@ namespace Pinetime { void Start(); void PushMessage(Messages msg); - enum class Apps {None, Launcher, Clock, SysInfo, Meter, Gauge, Brightness}; void StartApp(Apps app); void SetFullRefresh(FullRefreshDirections direction); + void SetTouchMode(TouchModes mode); + private: TaskHandle_t taskHandle; static void Process(void* instance); @@ -80,6 +83,8 @@ namespace Pinetime { Controllers::BrightnessController brightnessController; std::unique_ptr<Screens::Modal> modal; Pinetime::Controllers::NotificationManager& notificationManager; + Pinetime::Controllers::FirmwareValidator validator; + TouchModes touchMode = TouchModes::Gestures; }; } } diff --git a/src/DisplayApp/Fonts/Readme.md b/src/DisplayApp/Fonts/Readme.md index ddccc82..7ebf2e2 100644 --- a/src/DisplayApp/Fonts/Readme.md +++ b/src/DisplayApp/Fonts/Readme.md @@ -10,7 +10,7 @@ * Bpp : 1 bit-per-pixel * Do not enable font compression and horizontal subpixel hinting * Load the file `JetBrainsMono-Bold.woff` and specify the following range : `0x20-0x7f` - * 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` + * 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` * Click on Convert, and download the file `jetbrains_mono_bold_20.c` and copy it in `src/DisplayApp/Fonts` Add new symbols: diff --git a/src/DisplayApp/Fonts/jetbrains_mono_bold_20.c b/src/DisplayApp/Fonts/jetbrains_mono_bold_20.c index 96e13d6..27ad005 100644 --- a/src/DisplayApp/Fonts/jetbrains_mono_bold_20.c +++ b/src/DisplayApp/Fonts/jetbrains_mono_bold_20.c @@ -433,6 +433,15 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t gylph_bitmap[] = { /* U+7E "~" */ 0x78, 0xff, 0x3c, 0xff, 0x1e, + /* U+F001 "" */ + 0x0, 0x0, 0x70, 0x0, 0x7f, 0x0, 0x3f, 0xf0, + 0x1f, 0xff, 0x7, 0xff, 0xf0, 0x7f, 0xff, 0x7, + 0xfc, 0x70, 0x7e, 0x7, 0x7, 0x0, 0x70, 0x70, + 0x7, 0x7, 0x0, 0x70, 0x70, 0x7, 0x7, 0x0, + 0x70, 0x70, 0x7f, 0x7, 0xf, 0xf7, 0xf0, 0xff, + 0xff, 0x7, 0xef, 0xf0, 0x0, 0xff, 0x0, 0x3, + 0xc0, 0x0, + /* U+F017 "" */ 0x3, 0xf8, 0x1, 0xff, 0xc0, 0x7f, 0xfc, 0x1f, 0xff, 0xc7, 0xf1, 0xfc, 0xfe, 0x3f, 0x9f, 0xc7, @@ -449,6 +458,14 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t gylph_bitmap[] = { 0xf, 0x0, 0x0, 0xf3, 0xff, 0xff, 0x3f, 0xff, 0xf0, 0x0, 0x0, + /* U+F069 "" */ + 0x0, 0xe0, 0x0, 0x1c, 0x0, 0x3, 0x80, 0x0, + 0x70, 0x6, 0xe, 0xc, 0xf1, 0xc7, 0x9f, 0xbb, + 0xf1, 0xff, 0xfc, 0xf, 0xfe, 0x0, 0x7f, 0x0, + 0xf, 0xe0, 0x7, 0xff, 0x3, 0xff, 0xf8, 0xfd, + 0xdf, 0x9e, 0x38, 0xf3, 0x7, 0x6, 0x0, 0xe0, + 0x0, 0x1c, 0x0, 0x3, 0x80, 0x0, 0x70, 0x0, + /* U+F129 "" */ 0x3c, 0x7e, 0x7e, 0x7e, 0x3c, 0x0, 0x0, 0xfc, 0xfc, 0xfc, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, @@ -470,6 +487,14 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t gylph_bitmap[] = { 0x83, 0xfe, 0x3, 0xf8, 0x1, 0xc0, 0x3, 0x80, 0x7, 0x0, 0xe, 0x0, + /* U+F1FC "" */ + 0x0, 0x0, 0xf0, 0x0, 0x1f, 0x0, 0x3, 0xf0, + 0x0, 0x7e, 0x0, 0xf, 0xe0, 0x3, 0xfc, 0x0, + 0x7f, 0xc0, 0xf, 0xf8, 0x0, 0xff, 0x80, 0x1f, + 0xf0, 0x0, 0xfe, 0x0, 0xf, 0xe0, 0xe, 0x7c, + 0x1, 0xf8, 0x0, 0x9f, 0xc0, 0xf, 0xfc, 0x0, + 0x7f, 0xc0, 0x7, 0xf8, 0x0, 0x1f, 0x0, 0x0, + /* U+F21E "" */ 0x1e, 0x7, 0x83, 0xf9, 0xfe, 0x7f, 0xff, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xcf, 0xff, 0xfc, @@ -526,6 +551,15 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t gylph_bitmap[] = { 0x81, 0xf8, 0x6d, 0x99, 0x9a, 0x36, 0x7, 0x80, 0xe0, 0x18, 0x2, 0x0, 0x0, + /* U+F3FD "" */ + 0x0, 0xfe, 0x0, 0x7, 0xff, 0x0, 0x3f, 0xbf, + 0x80, 0xfe, 0x2f, 0x83, 0xfe, 0xcf, 0x8f, 0x3f, + 0x27, 0x9e, 0x7e, 0x4f, 0x3f, 0xfc, 0xfe, 0xff, + 0xf3, 0xff, 0xff, 0xe7, 0xff, 0xff, 0xcf, 0xff, + 0xfe, 0x3f, 0xfe, 0x78, 0x3c, 0xff, 0xf0, 0x7f, + 0xdf, 0xe0, 0xff, 0x3f, 0xff, 0xfe, 0x3f, 0xff, + 0xf8, + /* U+F54B "" */ 0x0, 0xf, 0xf8, 0x1, 0xdf, 0xff, 0x1, 0xef, 0xff, 0xc0, 0xf7, 0xff, 0xf0, 0x7b, 0xff, 0xf8, @@ -534,7 +568,16 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t gylph_bitmap[] = { 0x0, 0x0, 0x0, 0x7, 0xf8, 0x0, 0xf, 0xfe, 0x3, 0xbf, 0xff, 0x83, 0xdf, 0xff, 0xc1, 0xef, 0xff, 0xe0, 0xf7, 0xff, 0xe0, 0x3b, 0xff, 0xe0, - 0x0, 0x7f, 0xc0, 0x0 + 0x0, 0x7f, 0xc0, 0x0, + + /* U+F560 "" */ + 0x0, 0x0, 0x0, 0x0, 0x60, 0x0, 0xf, 0x0, + 0x1, 0xf0, 0x8, 0x3e, 0x1, 0xc7, 0xc4, 0x1e, + 0xf8, 0xe1, 0xff, 0x1f, 0xf, 0xe3, 0xf0, 0x7c, + 0x7e, 0x23, 0x8f, 0xc7, 0x11, 0xf8, 0xf8, 0x3f, + 0xf, 0xc7, 0xe0, 0x7e, 0xfc, 0x3, 0xff, 0x80, + 0x1f, 0xf0, 0x0, 0xfe, 0x0, 0x7, 0xc0, 0x0, + 0x38, 0x0, 0x1, 0x0, 0x0 }; @@ -639,20 +682,25 @@ static const lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] = { {.bitmap_index = 1423, .adv_w = 192, .box_w = 3, .box_h = 18, .ofs_x = 5, .ofs_y = -2}, {.bitmap_index = 1430, .adv_w = 192, .box_w = 10, .box_h = 18, .ofs_x = 1, .ofs_y = -2}, {.bitmap_index = 1453, .adv_w = 192, .box_w = 10, .box_h = 4, .ofs_x = 1, .ofs_y = 5}, - {.bitmap_index = 1458, .adv_w = 320, .box_w = 19, .box_h = 20, .ofs_x = 0, .ofs_y = -3}, - {.bitmap_index = 1506, .adv_w = 320, .box_w = 20, .box_h = 17, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 1549, .adv_w = 120, .box_w = 8, .box_h = 19, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 1568, .adv_w = 320, .box_w = 20, .box_h = 20, .ofs_x = 0, .ofs_y = -3}, - {.bitmap_index = 1618, .adv_w = 240, .box_w = 15, .box_h = 19, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 1654, .adv_w = 320, .box_w = 20, .box_h = 17, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 1697, .adv_w = 400, .box_w = 25, .box_h = 12, .ofs_x = 0, .ofs_y = 1}, - {.bitmap_index = 1735, .adv_w = 400, .box_w = 25, .box_h = 12, .ofs_x = 0, .ofs_y = 1}, - {.bitmap_index = 1773, .adv_w = 400, .box_w = 25, .box_h = 12, .ofs_x = 0, .ofs_y = 1}, - {.bitmap_index = 1811, .adv_w = 400, .box_w = 25, .box_h = 12, .ofs_x = 0, .ofs_y = 1}, - {.bitmap_index = 1849, .adv_w = 400, .box_w = 25, .box_h = 12, .ofs_x = 0, .ofs_y = 1}, - {.bitmap_index = 1887, .adv_w = 280, .box_w = 15, .box_h = 20, .ofs_x = 1, .ofs_y = -3}, - {.bitmap_index = 1925, .adv_w = 200, .box_w = 11, .box_h = 21, .ofs_x = 0, .ofs_y = -3}, - {.bitmap_index = 1954, .adv_w = 400, .box_w = 25, .box_h = 19, .ofs_x = 0, .ofs_y = -2} + {.bitmap_index = 1458, .adv_w = 320, .box_w = 20, .box_h = 20, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 1508, .adv_w = 320, .box_w = 19, .box_h = 20, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 1556, .adv_w = 320, .box_w = 20, .box_h = 17, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 1599, .adv_w = 320, .box_w = 19, .box_h = 20, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 1647, .adv_w = 120, .box_w = 8, .box_h = 19, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 1666, .adv_w = 320, .box_w = 20, .box_h = 20, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 1716, .adv_w = 240, .box_w = 15, .box_h = 19, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 1752, .adv_w = 320, .box_w = 20, .box_h = 19, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 1800, .adv_w = 320, .box_w = 20, .box_h = 17, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 1843, .adv_w = 400, .box_w = 25, .box_h = 12, .ofs_x = 0, .ofs_y = 1}, + {.bitmap_index = 1881, .adv_w = 400, .box_w = 25, .box_h = 12, .ofs_x = 0, .ofs_y = 1}, + {.bitmap_index = 1919, .adv_w = 400, .box_w = 25, .box_h = 12, .ofs_x = 0, .ofs_y = 1}, + {.bitmap_index = 1957, .adv_w = 400, .box_w = 25, .box_h = 12, .ofs_x = 0, .ofs_y = 1}, + {.bitmap_index = 1995, .adv_w = 400, .box_w = 25, .box_h = 12, .ofs_x = 0, .ofs_y = 1}, + {.bitmap_index = 2033, .adv_w = 280, .box_w = 15, .box_h = 20, .ofs_x = 1, .ofs_y = -3}, + {.bitmap_index = 2071, .adv_w = 200, .box_w = 11, .box_h = 21, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 2100, .adv_w = 360, .box_w = 23, .box_h = 17, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 2149, .adv_w = 400, .box_w = 25, .box_h = 19, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 2209, .adv_w = 320, .box_w = 20, .box_h = 21, .ofs_x = 0, .ofs_y = -3} }; /*--------------------- @@ -660,8 +708,9 @@ static const lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] = { *--------------------*/ static const uint16_t unicode_list_1[] = { - 0x0, 0x23, 0x112, 0x16e, 0x1cf, 0x207, 0x229, 0x22a, - 0x22b, 0x22c, 0x22d, 0x27c, 0x27d, 0x534 + 0x0, 0x16, 0x39, 0x68, 0x128, 0x184, 0x1e5, 0x1fb, + 0x21d, 0x23f, 0x240, 0x241, 0x242, 0x243, 0x292, 0x293, + 0x3fc, 0x54a, 0x55f }; /*Collect the unicode lists and glyph_id offsets*/ @@ -672,8 +721,8 @@ static const lv_font_fmt_txt_cmap_t cmaps[] = .unicode_list = NULL, .glyph_id_ofs_list = NULL, .list_length = 0, .type = LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY }, { - .range_start = 61463, .range_length = 1333, .glyph_id_start = 96, - .unicode_list = unicode_list_1, .glyph_id_ofs_list = NULL, .list_length = 14, .type = LV_FONT_FMT_TXT_CMAP_SPARSE_TINY + .range_start = 61441, .range_length = 1376, .glyph_id_start = 96, + .unicode_list = unicode_list_1, .glyph_id_ofs_list = NULL, .list_length = 19, .type = LV_FONT_FMT_TXT_CMAP_SPARSE_TINY } }; diff --git a/src/DisplayApp/LittleVgl.h b/src/DisplayApp/LittleVgl.h index 8bd56dd..5c1c443 100644 --- a/src/DisplayApp/LittleVgl.h +++ b/src/DisplayApp/LittleVgl.h @@ -6,10 +6,6 @@ #include <drivers/St7789.h> #include <drivers/Cst816s.h> - -static void disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p); -static bool touchpad_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data); - namespace Pinetime { namespace Components { class LittleVgl { diff --git a/src/DisplayApp/Screens/ApplicationList.cpp b/src/DisplayApp/Screens/ApplicationList.cpp new file mode 100644 index 0000000..eb85be4 --- /dev/null +++ b/src/DisplayApp/Screens/ApplicationList.cpp @@ -0,0 +1,82 @@ +#include <libs/lvgl/lvgl.h> +#include <DisplayApp/DisplayApp.h> +#include <functional> +#include "ApplicationList.h" +#include "Tile.h" +#include "Symbols.h" + +using namespace Pinetime::Applications::Screens; + +ApplicationList::ApplicationList(Pinetime::Applications::DisplayApp *app) : + Screen(app), + screens{app, { + [this]() -> std::unique_ptr<Screen> { return CreateScreen1(); }, + [this]() -> std::unique_ptr<Screen> { return CreateScreen2(); }, + //[this]() -> std::unique_ptr<Screen> { return CreateScreen3(); } + } + } {} + + +ApplicationList::~ApplicationList() { + lv_obj_clean(lv_scr_act()); +} + +bool ApplicationList::Refresh() { + if(running) + running = screens.Refresh(); + return running; +} + +bool ApplicationList::OnButtonPushed() { + running = false; + app->StartApp(Apps::Clock); + return true; +} + +bool ApplicationList::OnTouchEvent(Pinetime::Applications::TouchEvents event) { + return screens.OnTouchEvent(event); +} + +std::unique_ptr<Screen> ApplicationList::CreateScreen1() { + std::array<Screens::Tile::Applications, 6> applications { + {{Symbols::clock, Apps::Clock}, + {Symbols::music, Apps::Music}, + {Symbols::sun, Apps::Brightness}, + {Symbols::list, Apps::SysInfo}, + {Symbols::check, Apps::FirmwareValidation}, + {Symbols::none, Apps::None} + } + + + }; + + return std::unique_ptr<Screen>(new Screens::Tile(app, applications)); +} + +std::unique_ptr<Screen> ApplicationList::CreateScreen2() { + std::array<Screens::Tile::Applications, 6> applications { + {{Symbols::tachometer, Apps::Gauge}, + {Symbols::asterisk, Apps::Meter}, + {Symbols::paintbrush, Apps::Paint}, + {Symbols::none, Apps::None}, + {Symbols::none, Apps::None}, + {Symbols::none, Apps::None} + } + }; + + return std::unique_ptr<Screen>(new Screens::Tile(app, applications)); +} + +std::unique_ptr<Screen> ApplicationList::CreateScreen3() { + std::array<Screens::Tile::Applications, 6> applications { + {{"A", Apps::Meter}, + {"B", Apps::Gauge}, + {"C", Apps::Clock}, + {"D", Apps::Music}, + {"E", Apps::SysInfo}, + {"F", Apps::Brightness} + } + }; + + return std::unique_ptr<Screen>(new Screens::Tile(app, applications)); +} diff --git a/src/DisplayApp/Screens/ApplicationList.h b/src/DisplayApp/Screens/ApplicationList.h new file mode 100644 index 0000000..a1e6811 --- /dev/null +++ b/src/DisplayApp/Screens/ApplicationList.h @@ -0,0 +1,32 @@ +#pragma once + +#include <vector> +#include <Components/Ble/NimbleController.h> +#include "Screen.h" +#include "Label.h" +#include "ScreenList.h" +#include "Gauge.h" +#include "Meter.h" +#include <functional> + +namespace Pinetime { + namespace Applications { + namespace Screens { + class ApplicationList : public Screen { + public: + explicit ApplicationList(DisplayApp* app); + ~ApplicationList() override; + bool Refresh() override; + bool OnButtonPushed() override; + bool OnTouchEvent(TouchEvents event) override; + private: + bool running = true; + + ScreenList<2> screens; + std::unique_ptr<Screen> CreateScreen1(); + std::unique_ptr<Screen> CreateScreen2(); + std::unique_ptr<Screen> CreateScreen3(); + }; + } + } +}
\ No newline at end of file diff --git a/src/DisplayApp/Screens/Clock.cpp b/src/DisplayApp/Screens/Clock.cpp index fc6441e..06fab9a 100644 --- a/src/DisplayApp/Screens/Clock.cpp +++ b/src/DisplayApp/Screens/Clock.cpp @@ -121,13 +121,12 @@ bool Clock::Refresh() { auto hour = time.hours().count(); auto minute = time.minutes().count(); - auto second = time.seconds().count(); char minutesChar[3]; - sprintf(minutesChar, "%02d", minute); + sprintf(minutesChar, "%02d", static_cast<int>(minute)); char hoursChar[3]; - sprintf(hoursChar, "%02d", hour); + sprintf(hoursChar, "%02d", static_cast<int>(hour)); char timeStr[6]; sprintf(timeStr, "%c%c:%c%c", hoursChar[0],hoursChar[1],minutesChar[0], minutesChar[1]); diff --git a/src/DisplayApp/Screens/Clock.h b/src/DisplayApp/Screens/Clock.h index e1e10bd..7363fda 100644 --- a/src/DisplayApp/Screens/Clock.h +++ b/src/DisplayApp/Screens/Clock.h @@ -57,7 +57,7 @@ namespace Pinetime { Pinetime::Controllers::DateTime::Days currentDayOfWeek = Pinetime::Controllers::DateTime::Days::Unknown; uint8_t currentDay = 0; - DirtyValue<uint8_t> batteryPercentRemaining {0}; + DirtyValue<float> batteryPercentRemaining {0}; DirtyValue<bool> bleState {false}; DirtyValue<std::chrono::time_point<std::chrono::system_clock, std::chrono::nanoseconds>> currentDateTime; DirtyValue<uint32_t> stepCount {0}; diff --git a/src/DisplayApp/Screens/DropDownDemo.cpp b/src/DisplayApp/Screens/DropDownDemo.cpp new file mode 100644 index 0000000..735a0cc --- /dev/null +++ b/src/DisplayApp/Screens/DropDownDemo.cpp @@ -0,0 +1,64 @@ +#include <libs/lvgl/lvgl.h> +#include <libraries/log/nrf_log.h> +#include "DropDownDemo.h" +#include "../DisplayApp.h" + +using namespace Pinetime::Applications::Screens; +extern lv_font_t jetbrains_mono_extrabold_compressed; +extern lv_font_t jetbrains_mono_bold_20; + +DropDownDemo::DropDownDemo(Pinetime::Applications::DisplayApp *app) : Screen(app) { + // Create the dropdown object, with many item, and fix its height + ddlist = lv_ddlist_create(lv_scr_act(), NULL); + lv_ddlist_set_options(ddlist, "Apple\n" + "Banana\n" + "Orange\n" + "Melon\n" + "Grape\n" + "Raspberry\n" + "A\n" + "B\n" + "C\n" + "D\n" + "E"); + lv_ddlist_set_fix_width(ddlist, 150); + lv_ddlist_set_draw_arrow(ddlist, true); + lv_ddlist_set_fix_height(ddlist, 150); + lv_obj_align(ddlist, NULL, LV_ALIGN_IN_TOP_MID, 0, 20); +} + +DropDownDemo::~DropDownDemo() { + // Reset the touchmode + app->SetTouchMode(DisplayApp::TouchModes::Gestures); + lv_obj_clean(lv_scr_act()); +} + +bool DropDownDemo::Refresh() { + auto* list = static_cast<lv_ddlist_ext_t *>(ddlist->ext_attr); + + // Switch touchmode to Polling if the dropdown is opened. This will allow to scroll inside the + // dropdown while it is opened. + // Disable the polling mode when the dropdown is closed to be able to handle the gestures. + if(list->opened) + app->SetTouchMode(DisplayApp::TouchModes::Polling); + else + app->SetTouchMode(DisplayApp::TouchModes::Gestures); + return running; +} + +bool DropDownDemo::OnButtonPushed() { + running = false; + return true; +} + +bool DropDownDemo::OnTouchEvent(Pinetime::Applications::TouchEvents event) { + // If the dropdown is opened, notify Display app that it doesn't need to handle the event + // (this will prevent displayApp from going back to the menu or clock scree). + auto* list = static_cast<lv_ddlist_ext_t *>(ddlist->ext_attr); + if(list->opened) { + return true; + } else { + return false; + } +} + diff --git a/src/DisplayApp/Screens/DropDownDemo.h b/src/DisplayApp/Screens/DropDownDemo.h new file mode 100644 index 0000000..7c75efc --- /dev/null +++ b/src/DisplayApp/Screens/DropDownDemo.h @@ -0,0 +1,29 @@ +#pragma once + +#include <cstdint> +#include "Screen.h" +#include <bits/unique_ptr.h> +#include <libs/lvgl/src/lv_core/lv_style.h> +#include <libs/lvgl/src/lv_core/lv_obj.h> + +namespace Pinetime { + namespace Applications { + namespace Screens { + + class DropDownDemo : public Screen{ + public: + DropDownDemo(DisplayApp* app); + ~DropDownDemo() override; + + bool Refresh() override; + bool OnButtonPushed() override; + bool OnTouchEvent(TouchEvents event) override; + + private: + lv_obj_t * ddlist; + bool running = true; + bool isDropDownOpened = false; + }; + } + } +} diff --git a/src/DisplayApp/Screens/FirmwareValidation.cpp b/src/DisplayApp/Screens/FirmwareValidation.cpp new file mode 100644 index 0000000..fb2dd95 --- /dev/null +++ b/src/DisplayApp/Screens/FirmwareValidation.cpp @@ -0,0 +1,91 @@ +#include <libs/lvgl/lvgl.h> +#include "FirmwareValidation.h" +#include "../DisplayApp.h" +#include "../../Version.h" +#include "../../Components/FirmwareValidator/FirmwareValidator.h" + +using namespace Pinetime::Applications::Screens; +extern lv_font_t jetbrains_mono_extrabold_compressed; +extern lv_font_t jetbrains_mono_bold_20; + +namespace { + static void ButtonEventHandler(lv_obj_t * obj, lv_event_t event) + { + FirmwareValidation* screen = static_cast<FirmwareValidation *>(obj->user_data); + screen->OnButtonEvent(obj, event); + } + +} + +FirmwareValidation::FirmwareValidation(Pinetime::Applications::DisplayApp *app, + Pinetime::Controllers::FirmwareValidator &validator) + : Screen{app}, validator{validator} { + labelVersionInfo = lv_label_create(lv_scr_act(), NULL); + lv_obj_align(labelVersionInfo, NULL, LV_ALIGN_IN_TOP_LEFT, 0, 0); + lv_label_set_text(labelVersionInfo, "Version : "); + lv_label_set_align(labelVersionInfo, LV_LABEL_ALIGN_LEFT); + + + labelVersionValue = lv_label_create(lv_scr_act(), NULL); + lv_obj_align(labelVersionValue, labelVersionInfo, LV_ALIGN_OUT_RIGHT_MID, 0, 0); + lv_label_set_recolor(labelVersionValue, true); + sprintf(version, "%ld.%ld.%ld", Version::Major(), Version::Minor(), Version::Patch()); + lv_label_set_text(labelVersionValue, version); + + labelIsValidated = lv_label_create(lv_scr_act(), NULL); + lv_obj_align(labelIsValidated, NULL, LV_ALIGN_IN_TOP_LEFT, 0, 50); + lv_label_set_recolor(labelIsValidated, true); + lv_label_set_long_mode(labelIsValidated, LV_LABEL_LONG_BREAK); + lv_obj_set_width(labelIsValidated, 240); + + if(validator.IsValidated()) + lv_label_set_text(labelIsValidated, "You have already\n#00ff00 validated# this firmware#"); + else { + lv_label_set_text(labelIsValidated, + "Please #00ff00 Validate# this version or\n#ff0000 Reset# to rollback to the previous version."); + + buttonValidate = lv_btn_create(lv_scr_act(), NULL); + lv_obj_align(buttonValidate, NULL, LV_ALIGN_IN_BOTTOM_LEFT, 0, 0); + buttonValidate->user_data = this; + lv_obj_set_event_cb(buttonValidate, ButtonEventHandler); + + labelButtonValidate = lv_label_create(buttonValidate, NULL); + lv_label_set_recolor(labelButtonValidate, true); + lv_label_set_text(labelButtonValidate, "#00ff00 Validate#"); + + buttonReset = lv_btn_create(lv_scr_act(), NULL); + buttonReset->user_data = this; + lv_obj_align(buttonReset, NULL, LV_ALIGN_IN_BOTTOM_RIGHT, 0, 0); + lv_obj_set_event_cb(buttonReset, ButtonEventHandler); + + labelButtonReset = lv_label_create(buttonReset, NULL); + lv_label_set_recolor(labelButtonReset, true); + lv_label_set_text(labelButtonReset, "#ff0000 Reset#"); + } +} + + +FirmwareValidation::~FirmwareValidation() { + lv_obj_clean(lv_scr_act()); +} + +bool FirmwareValidation::Refresh() { + return running; +} + +bool FirmwareValidation::OnButtonPushed() { + running = false; + return true; +} + +void FirmwareValidation::OnButtonEvent(lv_obj_t *object, lv_event_t event) { + if(object == buttonValidate && event == LV_EVENT_PRESSED) { + validator.Validate(); + running = false; + } else if(object == buttonReset && event == LV_EVENT_PRESSED) { + validator.Reset(); + } + +} + + diff --git a/src/DisplayApp/Screens/FirmwareValidation.h b/src/DisplayApp/Screens/FirmwareValidation.h new file mode 100644 index 0000000..947f557 --- /dev/null +++ b/src/DisplayApp/Screens/FirmwareValidation.h @@ -0,0 +1,42 @@ +#pragma once + +#include <cstdint> +#include "Screen.h" +#include <bits/unique_ptr.h> +#include <libs/lvgl/src/lv_core/lv_style.h> +#include <libs/lvgl/src/lv_core/lv_obj.h> + +namespace Pinetime { + namespace Controllers { + class FirmwareValidator; + } + + namespace Applications { + namespace Screens { + + class FirmwareValidation : public Screen{ + public: + FirmwareValidation(DisplayApp* app, Pinetime::Controllers::FirmwareValidator& validator); + ~FirmwareValidation() override; + + bool Refresh() override; + bool OnButtonPushed() override; + + void OnButtonEvent(lv_obj_t *object, lv_event_t event); + + private: + Pinetime::Controllers::FirmwareValidator& validator; + + lv_obj_t* labelVersionInfo; + lv_obj_t* labelVersionValue; + char version[9]; + lv_obj_t* labelIsValidated; + lv_obj_t* buttonValidate; + lv_obj_t* labelButtonValidate; + lv_obj_t* buttonReset; + lv_obj_t* labelButtonReset; + bool running = true; + }; + } + } +} diff --git a/src/DisplayApp/Screens/Gauge.cpp b/src/DisplayApp/Screens/Gauge.cpp index 4c4cccd..fd90523 100644 --- a/src/DisplayApp/Screens/Gauge.cpp +++ b/src/DisplayApp/Screens/Gauge.cpp @@ -19,6 +19,7 @@ Gauge::Gauge(Pinetime::Applications::DisplayApp *app) : Screen(app) { style.text.color = LV_COLOR_WHITE; style.line.color = LV_COLOR_RED; /*Line color after the critical value*/ + /*Describe the color for the needles*/ needle_colors[0] = LV_COLOR_ORANGE; diff --git a/src/DisplayApp/Screens/InfiniPaint.cpp b/src/DisplayApp/Screens/InfiniPaint.cpp new file mode 100644 index 0000000..b340f5d --- /dev/null +++ b/src/DisplayApp/Screens/InfiniPaint.cpp @@ -0,0 +1,44 @@ +#include <libs/lvgl/lvgl.h> +#include <libraries/log/nrf_log.h> +#include "InfiniPaint.h" +#include "../DisplayApp.h" + +using namespace Pinetime::Applications::Screens; +extern lv_font_t jetbrains_mono_extrabold_compressed; +extern lv_font_t jetbrains_mono_bold_20; + +InfiniPaint::InfiniPaint(Pinetime::Applications::DisplayApp *app, Pinetime::Components::LittleVgl& lvgl) : Screen(app), lvgl{lvgl} { + app->SetTouchMode(DisplayApp::TouchModes::Polling); + std::fill(b, b+bufferSize, LV_COLOR_WHITE); +} + +InfiniPaint::~InfiniPaint() { + // Reset the touchmode + app->SetTouchMode(DisplayApp::TouchModes::Gestures); + lv_obj_clean(lv_scr_act()); +} + +bool InfiniPaint::Refresh() { + return running; +} + +bool InfiniPaint::OnButtonPushed() { + running = false; + return true; +} + +bool InfiniPaint::OnTouchEvent(Pinetime::Applications::TouchEvents event) { + return true; +} + +bool InfiniPaint::OnTouchEvent(uint16_t x, uint16_t y) { + lv_area_t area; + area.x1 = x-(width/2); + area.y1 = y-(height/2); + area.x2 = x+(width/2)-1; + area.y2 = y+(height/2)-1; + lvgl.SetFullRefresh(Components::LittleVgl::FullRefreshDirections::None); + lvgl.FlushDisplay(&area, b); + return true; +} + diff --git a/src/DisplayApp/Screens/InfiniPaint.h b/src/DisplayApp/Screens/InfiniPaint.h new file mode 100644 index 0000000..a1592f9 --- /dev/null +++ b/src/DisplayApp/Screens/InfiniPaint.h @@ -0,0 +1,35 @@ +#pragma once + +#include <cstdint> +#include "Screen.h" +#include <bits/unique_ptr.h> +#include <libs/lvgl/src/lv_core/lv_style.h> +#include <libs/lvgl/src/lv_core/lv_obj.h> +#include <drivers/St7789.h> +#include <DisplayApp/LittleVgl.h> + +namespace Pinetime { + namespace Applications { + namespace Screens { + + class InfiniPaint : public Screen{ + public: + InfiniPaint(DisplayApp* app, Pinetime::Components::LittleVgl& lvgl); + ~InfiniPaint() override; + + bool Refresh() override; + bool OnButtonPushed() override; + bool OnTouchEvent(TouchEvents event) override; + bool OnTouchEvent(uint16_t x, uint16_t y) override; + + private: + Pinetime::Components::LittleVgl& lvgl; + static constexpr uint16_t width = 10; + static constexpr uint16_t height = 10; + static constexpr uint16_t bufferSize = width*height; + lv_color_t b[bufferSize]; + bool running = true; + }; + } + } +} diff --git a/src/DisplayApp/Screens/Label.cpp b/src/DisplayApp/Screens/Label.cpp index ba35279..780ee88 100644 --- a/src/DisplayApp/Screens/Label.cpp +++ b/src/DisplayApp/Screens/Label.cpp @@ -3,26 +3,13 @@ using namespace Pinetime::Applications::Screens; - -Label::Label(const char* text) : text{text} { - -} - -Label::~Label() { - -} - -void Label::Refresh() { - -} - -void Label::Show() { +Label::Label(Pinetime::Applications::DisplayApp *app, const char *text) : Screen(app), text{text} { label = lv_label_create(lv_scr_act(), NULL); lv_label_set_align(label, LV_LABEL_ALIGN_LEFT); lv_obj_set_size(label, 240, 240); lv_label_set_text(label, text); } -void Label::Hide() { +Label::~Label() { lv_obj_clean(lv_scr_act()); } diff --git a/src/DisplayApp/Screens/Label.h b/src/DisplayApp/Screens/Label.h index b73540f..3e7b379 100644 --- a/src/DisplayApp/Screens/Label.h +++ b/src/DisplayApp/Screens/Label.h @@ -2,19 +2,18 @@ #include <vector> #include "Screen.h" +#include <lvgl/lvgl.h> namespace Pinetime { namespace Applications { namespace Screens { - class Label { + + class Label : public Screen { public: - Label() = default; - explicit Label(const char* text); - ~Label(); - void Refresh(); + Label(DisplayApp* app, const char* text); + ~Label() override; + bool Refresh() override {return false;} - void Hide(); - void Show(); private: lv_obj_t * label = nullptr; const char* text = nullptr; diff --git a/src/DisplayApp/Screens/Message.cpp b/src/DisplayApp/Screens/Message.cpp deleted file mode 100644 index b83cb75..0000000 --- a/src/DisplayApp/Screens/Message.cpp +++ /dev/null @@ -1,81 +0,0 @@ -#include <cstdio> -#include <libs/date/includes/date/date.h> -#include <Components/DateTime/DateTimeController.h> -#include <Version.h> -#include <libs/lvgl/src/lv_core/lv_obj.h> -#include <libs/lvgl/src/lv_font/lv_font.h> -#include <libs/lvgl/lvgl.h> -#include <libraries/log/nrf_log.h> -#include "Message.h" -#include <DisplayApp/DisplayApp.h> - - -using namespace Pinetime::Applications::Screens; - -extern lv_font_t jetbrains_mono_bold_20; - -static void event_handler(lv_obj_t * obj, lv_event_t event) { - Message* screen = static_cast<Message *>(obj->user_data); - screen->OnObjectEvent(obj, event); -} - -Message::Message(DisplayApp* app) : Screen(app) { - - backgroundLabel = lv_label_create(lv_scr_act(), NULL); - backgroundLabel->user_data = this; - - lv_obj_set_click(backgroundLabel, true); - lv_obj_set_event_cb(backgroundLabel, event_handler); - lv_label_set_long_mode(backgroundLabel, LV_LABEL_LONG_CROP); - lv_obj_set_size(backgroundLabel, 240, 240); - lv_obj_set_pos(backgroundLabel, 0, 0); - lv_label_set_text(backgroundLabel, ""); - - button = lv_btn_create(lv_scr_act(), NULL); - lv_obj_set_event_cb(button, event_handler); - lv_obj_align(button, NULL, LV_ALIGN_CENTER, 0, -40); - button->user_data = this; - - label = lv_label_create(button, NULL); - lv_label_set_text(label, "Hello!"); - - labelClick = lv_label_create(lv_scr_act(), NULL); - lv_obj_align(labelClick, button, LV_ALIGN_OUT_BOTTOM_MID, 0, 30); - lv_label_set_text(labelClick, "0"); -} - -Message::~Message() { - lv_obj_clean(lv_scr_act()); -} - -bool Message::Refresh() { - if(previousClickCount != clickCount) { - lv_label_set_text_fmt(labelClick, "%d", clickCount); - previousClickCount = clickCount; - } - - return running; -} - -void Message::OnObjectEvent(lv_obj_t *obj, lv_event_t event) { - if(obj == backgroundLabel) { - if(event == LV_EVENT_CLICKED) { - app->PushMessage(DisplayApp::Messages::SwitchScreen); - NRF_LOG_INFO("SCREEN"); - } - return ; - } - - if(event == LV_EVENT_CLICKED) { - NRF_LOG_INFO("Clicked"); - clickCount++; - } - else if(event == LV_EVENT_VALUE_CHANGED) { - NRF_LOG_INFO("Toggled"); - } -} - -bool Message::OnButtonPushed() { - running = false; - return true; -} diff --git a/src/DisplayApp/Screens/Message.h b/src/DisplayApp/Screens/Message.h deleted file mode 100644 index 3ace66f..0000000 --- a/src/DisplayApp/Screens/Message.h +++ /dev/null @@ -1,31 +0,0 @@ -#pragma once - -#include <cstdint> -#include "Screen.h" -#include <bits/unique_ptr.h> -#include <lvgl/src/lv_core/lv_style.h> - -namespace Pinetime { - namespace Applications { - namespace Screens { - class Message : public Screen{ - public: - explicit Message(DisplayApp* app); - ~Message() override; - bool Refresh() override; - bool OnButtonPushed(); - void OnObjectEvent(lv_obj_t* obj, lv_event_t event); - - private: - lv_obj_t * label; - lv_obj_t* backgroundLabel; - lv_obj_t * button; - lv_obj_t * labelClick; - - uint32_t clickCount = 0 ; - uint32_t previousClickCount = 0; - bool running = true; - }; - } - } -} diff --git a/src/DisplayApp/Screens/Music.cpp b/src/DisplayApp/Screens/Music.cpp new file mode 100644 index 0000000..9b7d198 --- /dev/null +++ b/src/DisplayApp/Screens/Music.cpp @@ -0,0 +1,125 @@ +#include <libs/lvgl/lvgl.h> +#include "Music.h" + +using namespace Pinetime::Applications::Screens; +extern lv_font_t jetbrains_mono_extrabold_compressed; +extern lv_font_t jetbrains_mono_bold_20; + +static void event_handler(lv_obj_t * obj, lv_event_t event) +{ + Music* screen = static_cast<Music *>(obj->user_data); + screen->OnObjectEvent(obj, event); +} + +Music::Music(Pinetime::Applications::DisplayApp *app, Pinetime::Controllers::MusicService &music) : Screen(app), musicService(music) { + lv_obj_t * label; + + btnVolDown = lv_btn_create(lv_scr_act(), NULL); + btnVolDown->user_data = this; + lv_obj_set_event_cb(btnVolDown, event_handler); + lv_obj_align(btnVolDown, NULL, LV_ALIGN_IN_TOP_LEFT, 10, 10); + label = lv_label_create(btnVolDown, NULL); + lv_label_set_text(label, "v-"); + + btnVolUp = lv_btn_create(lv_scr_act(), NULL); + btnVolUp->user_data = this; + lv_obj_set_event_cb(btnVolUp, event_handler); + lv_obj_align(btnVolUp, NULL, LV_ALIGN_IN_TOP_RIGHT, -10, 10); + label = lv_label_create(btnVolUp, NULL); + lv_label_set_text(label, "v+"); + + btnPrev = lv_btn_create(lv_scr_act(), NULL); + btnPrev->user_data = this; + lv_obj_set_event_cb(btnPrev, event_handler); + lv_obj_set_size(btnPrev, LV_HOR_RES / 4, LV_VER_RES / 4); + lv_obj_align(btnPrev, NULL, LV_ALIGN_IN_BOTTOM_LEFT, 10,-10); + label = lv_label_create(btnPrev, NULL); + lv_label_set_text(label, "<<"); + + btnPlayPause = lv_btn_create(lv_scr_act(), NULL); + btnPlayPause->user_data = this; + lv_obj_set_event_cb(btnPlayPause, event_handler); + lv_obj_set_size(btnPlayPause, LV_HOR_RES / 4, LV_VER_RES / 4); + lv_obj_align(btnPlayPause, NULL, LV_ALIGN_IN_BOTTOM_MID, 0,-10); + txtPlayPause = lv_label_create(btnPlayPause, NULL); + lv_label_set_text(txtPlayPause, ">"); + + btnNext = lv_btn_create(lv_scr_act(), NULL); + btnNext->user_data = this; + lv_obj_set_event_cb(btnNext, event_handler); + lv_obj_set_size(btnNext, LV_HOR_RES / 4, LV_VER_RES / 4); + lv_obj_align(btnNext, NULL, LV_ALIGN_IN_BOTTOM_RIGHT, -10,-10); + label = lv_label_create(btnNext, NULL); + lv_label_set_text(label, ">>"); + + txtArtist = lv_label_create(lv_scr_act(), NULL); + lv_label_set_long_mode(txtArtist, LV_LABEL_LONG_SROLL); + lv_obj_align(txtArtist, NULL, LV_ALIGN_IN_LEFT_MID, 0,-20); + lv_label_set_text(txtArtist, "Artist Name"); + lv_label_set_align(txtArtist, LV_LABEL_ALIGN_CENTER); + lv_obj_set_width(txtArtist, LV_HOR_RES); + + txtTrack = lv_label_create(lv_scr_act(), NULL); + lv_label_set_long_mode(txtTrack, LV_LABEL_LONG_DOT); + lv_obj_align(txtTrack, NULL, LV_ALIGN_IN_LEFT_MID, 0,20); + lv_label_set_text(txtTrack, "This is a very long track name"); + lv_label_set_align(txtTrack, LV_LABEL_ALIGN_CENTER); + lv_obj_set_width(txtTrack, LV_HOR_RES); + + musicService.event(Controllers::MusicService::EVENT_MUSIC_OPEN); +} + +Music::~Music() { + lv_obj_clean(lv_scr_act()); +} + +bool Music::OnButtonPushed() { + running = false; + return true; +} + +bool Music::Refresh() { + + if (m_artist != musicService.artist()) { + m_artist = musicService.artist(); + lv_label_set_text(txtArtist, m_artist.data()); + } + if (m_track != musicService.track()) { + m_track = musicService.track(); + lv_label_set_text(txtTrack, m_track.data()); + } + if (m_album != musicService.album()) { + m_album = musicService.album(); + } + if (m_status != musicService.status()) { + m_status = musicService.status(); + } + if (m_status == Pinetime::Controllers::MusicService::STATUS_MUSIC_PLAYING) { + lv_label_set_text(txtPlayPause, "||"); + } else { + lv_label_set_text(txtPlayPause, ">"); + } + + return running; +} + +void Music::OnObjectEvent(lv_obj_t* obj, lv_event_t event) +{ + if (event == LV_EVENT_CLICKED) { + if (obj == btnVolDown) { + musicService.event(Controllers::MusicService::EVENT_MUSIC_VOLDOWN); + } else if (obj == btnVolUp) { + musicService.event(Controllers::MusicService::EVENT_MUSIC_VOLUP); + } else if (obj == btnPrev) { + musicService.event(Controllers::MusicService::EVENT_MUSIC_PREV); + } else if (obj == btnPlayPause) { + if (m_status == Pinetime::Controllers::MusicService::STATUS_MUSIC_PLAYING) { + musicService.event(Controllers::MusicService::EVENT_MUSIC_PAUSE); + } else { + musicService.event(Controllers::MusicService::EVENT_MUSIC_PLAY); + } + } else if (obj == btnNext) { + musicService.event(Controllers::MusicService::EVENT_MUSIC_NEXT); + } + } +} diff --git a/src/DisplayApp/Screens/Music.h b/src/DisplayApp/Screens/Music.h new file mode 100644 index 0000000..95cac0f --- /dev/null +++ b/src/DisplayApp/Screens/Music.h @@ -0,0 +1,49 @@ +#pragma once + +#include <cstdint> +#include <chrono> +#include <Components/Gfx/Gfx.h> +#include "Screen.h" +#include <bits/unique_ptr.h> +#include <libs/lvgl/src/lv_core/lv_style.h> +#include <libs/lvgl/src/lv_core/lv_obj.h> +#include <Components/Battery/BatteryController.h> +#include <Components/Ble/BleController.h> +#include "../../Version.h" +#include <Components/Ble/MusicService.h> +#include <string> + +namespace Pinetime { + namespace Applications { + namespace Screens { + + class Music : public Screen{ + public: + Music(DisplayApp* app, Pinetime::Controllers::MusicService &music); + ~Music() override; + + bool Refresh() override; + bool OnButtonPushed() override; + + void OnObjectEvent(lv_obj_t* obj, lv_event_t event); + + private: + lv_obj_t * btnPrev; + lv_obj_t * btnPlayPause; + lv_obj_t * btnNext; + lv_obj_t * btnVolDown; + lv_obj_t * btnVolUp; + lv_obj_t * txtArtist; + lv_obj_t * txtTrack; + lv_obj_t * txtPlayPause; + + bool running = true; + Pinetime::Controllers::MusicService &musicService; + std::string m_artist; + std::string m_album; + std::string m_track; + unsigned char m_status; + }; + } + } +} diff --git a/src/DisplayApp/Screens/Screen.h b/src/DisplayApp/Screens/Screen.h index d890231..dbf81a4 100644 --- a/src/DisplayApp/Screens/Screen.h +++ b/src/DisplayApp/Screens/Screen.h @@ -1,4 +1,6 @@ #pragma once + +#include <cstdint> #include "../TouchEvents.h" namespace Pinetime { @@ -18,6 +20,7 @@ namespace Pinetime { // Return false if the event hasn't been handled by the app, true if it has been handled virtual bool OnTouchEvent(TouchEvents event) { return false; } + virtual bool OnTouchEvent(uint16_t x, uint16_t y) { return false; } protected: DisplayApp* app; diff --git a/src/DisplayApp/Screens/ScreenList.h b/src/DisplayApp/Screens/ScreenList.h index b0ee016..d873336 100644 --- a/src/DisplayApp/Screens/ScreenList.h +++ b/src/DisplayApp/Screens/ScreenList.h @@ -2,40 +2,64 @@ #include <vector> #include <Components/Ble/NimbleController.h> +#include <functional> #include "Screen.h" #include "Label.h" namespace Pinetime { namespace Applications { namespace Screens { + template <size_t N> class ScreenList : public Screen { public: - explicit ScreenList(DisplayApp* app, - Pinetime::Controllers::DateTime& dateTimeController, - Pinetime::Controllers::Battery& batteryController, - Pinetime::Controllers::BrightnessController& brightnessController, - Pinetime::Controllers::Ble& bleController, - Pinetime::Drivers::WatchdogView& watchdog); - ~ScreenList() override; - bool Refresh() override; - bool OnButtonPushed() override; - bool OnTouchEvent(TouchEvents event) override; - private: - bool running = true; - uint8_t screenIndex = 0; + ScreenList(DisplayApp* app, std::array<std::function<std::unique_ptr<Screen>()>, N>&& screens) + : Screen(app), screens{std::move(screens)}, current{this->screens[0]()} { + + } + + ~ScreenList() override { - // TODO choose another container without dynamic alloc - std::vector<Screens::Label> screens; - Pinetime::Controllers::DateTime& dateTimeController; - Pinetime::Controllers::Battery& batteryController; - Pinetime::Controllers::BrightnessController& brightnessController; - Pinetime::Controllers::Ble& bleController; - Pinetime::Drivers::WatchdogView& watchdog; + } + bool Refresh() override { + running = current->Refresh(); + return running; + } - char t1[200]; - char t2[200]; - char t3[30]; + bool OnButtonPushed() override { + running = false; + return true; + } + + bool OnTouchEvent(TouchEvents event) override { + switch (event) { + case TouchEvents::SwipeDown: + if (screenIndex > 0) { + current.reset(nullptr); + app->SetFullRefresh(DisplayApp::FullRefreshDirections::Down); + screenIndex--; + current = screens[screenIndex](); + } + return true; + case TouchEvents::SwipeUp: + if (screenIndex < screens.size() - 1) { + current.reset(nullptr); + app->SetFullRefresh(DisplayApp::FullRefreshDirections::Up); + screenIndex++; + current = screens[screenIndex](); + } + return true; + default: + return false; + } + return false; + } + + private: + bool running = true; + uint8_t screenIndex = 0; + std::array<std::function<std::unique_ptr<Screen>()>, N> screens; + std::unique_ptr<Screen> current; }; } } diff --git a/src/DisplayApp/Screens/Symbols.h b/src/DisplayApp/Screens/Symbols.h index 3104db8..aeea324 100644 --- a/src/DisplayApp/Screens/Symbols.h +++ b/src/DisplayApp/Screens/Symbols.h @@ -4,20 +4,26 @@ namespace Pinetime { namespace Applications { namespace Screens { namespace Symbols { - static constexpr char* batteryFull = "\xEF\x89\x80"; - static constexpr char* batteryEmpty = "\xEF\x89\x84"; - static constexpr char* batteryThreeQuarter = "\xEF\x89\x81"; - static constexpr char* batteryHalf = "\xEF\x89\x82"; - static constexpr char* batteryOneQuarter = "\xEF\x89\x83"; - static constexpr char* heartBeat = "\xEF\x88\x9E"; - static constexpr char* bluetoothFull = "\xEF\x8A\x93"; - static constexpr char* bluetooth = "\xEF\x8A\x94"; - static constexpr char* plug = "\xEF\x87\xA6"; - static constexpr char* shoe = "\xEF\x95\x8B"; - static constexpr char* clock = "\xEF\x80\x97"; - static constexpr char* info = "\xEF\x84\xA9"; - static constexpr char* list = "\xEF\x80\xBA"; - static constexpr char* sun = "\xEF\x86\x85"; + static constexpr const char* none = ""; + static constexpr const char* batteryFull = "\xEF\x89\x80"; + static constexpr const char* batteryEmpty = "\xEF\x89\x84"; + static constexpr const char* batteryThreeQuarter = "\xEF\x89\x81"; + static constexpr const char* batteryHalf = "\xEF\x89\x82"; + static constexpr const char* batteryOneQuarter = "\xEF\x89\x83"; + static constexpr const char* heartBeat = "\xEF\x88\x9E"; + static constexpr const char* bluetoothFull = "\xEF\x8A\x93"; + static constexpr const char* bluetooth = "\xEF\x8A\x94"; + static constexpr const char* plug = "\xEF\x87\xA6"; + static constexpr const char* shoe = "\xEF\x95\x8B"; + static constexpr const char* clock = "\xEF\x80\x97"; + static constexpr const char* info = "\xEF\x84\xA9"; + static constexpr const char* list = "\xEF\x80\xBA"; + static constexpr const char* sun = "\xEF\x86\x85"; + static constexpr const char* check = "\xEF\x95\xA0"; + static constexpr const char* music = "\xEF\x80\x81"; + static constexpr const char* tachometer = "\xEF\x8F\xBD"; + static constexpr const char* asterisk = "\xEF\x81\xA9"; + static constexpr const char* paintbrush = "\xEF\x87\xBC"; } } } diff --git a/src/DisplayApp/Screens/ScreenList.cpp b/src/DisplayApp/Screens/SystemInfo.cpp index 754d5f7..fcafcf7 100644 --- a/src/DisplayApp/Screens/ScreenList.cpp +++ b/src/DisplayApp/Screens/SystemInfo.cpp @@ -1,40 +1,61 @@ #include <libs/lvgl/lvgl.h> #include <DisplayApp/DisplayApp.h> -#include "ScreenList.h" +#include <functional> +#include "SystemInfo.h" #include "../../Version.h" +#include "Tile.h" using namespace Pinetime::Applications::Screens; -// TODO this class must be improved to receive the list of "sub screens" via pointer or -// move operation. -// It should accept many type of "sub screen" (it only supports Label for now). -// The number of sub screen it supports must be dynamic. -ScreenList::ScreenList(Pinetime::Applications::DisplayApp *app, - Pinetime::Controllers::DateTime &dateTimeController, - Pinetime::Controllers::Battery& batteryController, - Pinetime::Controllers::BrightnessController& brightnessController, +SystemInfo::SystemInfo(Pinetime::Applications::DisplayApp *app, + Pinetime::Controllers::DateTime &dateTimeController, + Pinetime::Controllers::Battery& batteryController, + Pinetime::Controllers::BrightnessController& brightnessController, Pinetime::Controllers::Ble& bleController, - Pinetime::Drivers::WatchdogView& watchdog) : + Pinetime::Drivers::WatchdogView& watchdog) : Screen(app), dateTimeController{dateTimeController}, batteryController{batteryController}, - brightnessController{brightnessController}, bleController{bleController}, watchdog{watchdog} { - screens.reserve(3); + brightnessController{brightnessController}, bleController{bleController}, watchdog{watchdog}, + screens{app, { + [this]() -> std::unique_ptr<Screen> { return CreateScreen1(); }, + [this]() -> std::unique_ptr<Screen> { return CreateScreen2(); }, + [this]() -> std::unique_ptr<Screen> { return CreateScreen3(); } + } + } {} - // TODO all of this is far too heavy (string processing). This should be improved. - // TODO the info (battery, time,...) should be updated in the Refresh method. +SystemInfo::~SystemInfo() { + lv_obj_clean(lv_scr_act()); +} + +bool SystemInfo::Refresh() { + screens.Refresh(); + return running; +} - auto batteryPercent = static_cast<int16_t>(batteryController.PercentRemaining()); - if(batteryPercent > 100) batteryPercent = 100; - else if(batteryPercent < 0) batteryPercent = 0; +bool SystemInfo::OnButtonPushed() { + running = false; + return true; +} + +bool SystemInfo::OnTouchEvent(Pinetime::Applications::TouchEvents event) { + return screens.OnTouchEvent(event); +} + +std::unique_ptr<Screen> SystemInfo::CreateScreen1() { + auto batteryPercentF = batteryController.PercentRemaining(); + uint16_t batteryPercent = 0; + if(batteryPercentF > 100.0f) batteryPercent = 100; + else if(batteryPercentF < 0.0f) batteryPercent = 0; uint8_t brightness = 0; switch(brightnessController.Level()) { + case Controllers::BrightnessController::Levels::Off: brightness = 0; break; case Controllers::BrightnessController::Levels::Low: brightness = 1; break; case Controllers::BrightnessController::Levels::Medium: brightness = 2; break; case Controllers::BrightnessController::Levels::High: brightness = 3; break; } - auto resetReason = [&watchdog]() { + auto resetReason = [this]() { switch (watchdog.ResetReason()) { case Drivers::Watchdog::ResetReasons::Watchdog: return "wtdg"; case Drivers::Watchdog::ResetReasons::HardReset: return "hardr"; @@ -63,7 +84,7 @@ ScreenList::ScreenList(Pinetime::Applications::DisplayApp *app, // TODO handle more than 100 days of uptime sprintf(t1, "Pinetime\n" - "Version:%d.%d.%d\n" + "Version:%ld.%ld.%ld\n" "Build: %s\n" " %s\n" "Date: %02d/%02d/%04d\n" @@ -72,68 +93,24 @@ ScreenList::ScreenList(Pinetime::Applications::DisplayApp *app, "Battery: %d%%\n" "Backlight: %d/3\n" "Last reset: %s\n", - Version::Major(), Version::Minor(), Version::Patch(), - __DATE__, __TIME__, - dateTimeController.Day(), dateTimeController.Month(), dateTimeController.Year(), - dateTimeController.Hours(), dateTimeController.Minutes(), dateTimeController.Seconds(), - uptimeDays, uptimeHours, uptimeMinutes, uptimeSeconds, - batteryPercent, brightness, resetReason); - - screens.emplace_back(t1); + Version::Major(), Version::Minor(), Version::Patch(), + __DATE__, __TIME__, + dateTimeController.Day(), static_cast<uint8_t>(dateTimeController.Month()), dateTimeController.Year(), + dateTimeController.Hours(), dateTimeController.Minutes(), dateTimeController.Seconds(), + uptimeDays, uptimeHours, uptimeMinutes, uptimeSeconds, + batteryPercent, brightness, resetReason); + + return std::unique_ptr<Screen>(new Screens::Label(app, t1)); +} +std::unique_ptr<Screen> SystemInfo::CreateScreen2() { auto& bleAddr = bleController.Address(); sprintf(t2, "BLE MAC: \n %2x:%2x:%2x:%2x:%2x:%2x", bleAddr[5], bleAddr[4], bleAddr[3], bleAddr[2], bleAddr[1], bleAddr[0]); - screens.emplace_back(t2); - - strncpy(t3, "Hello from\nthe developper!", 27); - - screens.emplace_back(t3); - - auto &screen = screens[screenIndex]; - screen.Show(); -} - -ScreenList::~ScreenList() { - lv_obj_clean(lv_scr_act()); + return std::unique_ptr<Screen>(new Screens::Label(app, t2)); } -bool ScreenList::Refresh() { - auto &screen = screens[screenIndex]; - screen.Refresh(); - - return running; -} - -bool ScreenList::OnButtonPushed() { - running = false; - return true; -} - -bool ScreenList::OnTouchEvent(Pinetime::Applications::TouchEvents event) { - switch (event) { - case TouchEvents::SwipeDown: - if (screenIndex > 0) { - app->SetFullRefresh(DisplayApp::FullRefreshDirections::Down); - auto &oldScreen = screens[screenIndex]; - oldScreen.Hide(); - screenIndex--; - auto &newScreen = screens[screenIndex]; - newScreen.Show(); - } - return true; - case TouchEvents::SwipeUp: - app->SetFullRefresh(DisplayApp::FullRefreshDirections::Up); - if (screenIndex < screens.size() - 1) { - auto &oldScreen = screens[screenIndex]; - oldScreen.Hide(); - screenIndex++; - auto &newScreen = screens[screenIndex]; - newScreen.Show(); - } - return true; - default: - return false; - } - return false; +std::unique_ptr<Screen> SystemInfo::CreateScreen3() { + strncpy(t3, "Hello from\nthe developper!", 27); + return std::unique_ptr<Screen>(new Screens::Label(app, t3)); } diff --git a/src/DisplayApp/Screens/SystemInfo.h b/src/DisplayApp/Screens/SystemInfo.h new file mode 100644 index 0000000..ac8abae --- /dev/null +++ b/src/DisplayApp/Screens/SystemInfo.h @@ -0,0 +1,47 @@ +#pragma once + +#include <vector> +#include <Components/Ble/NimbleController.h> +#include "Screen.h" +#include "Label.h" +#include "ScreenList.h" +#include "Gauge.h" +#include "Meter.h" +#include <functional> + +namespace Pinetime { + namespace Applications { + namespace Screens { + class SystemInfo : public Screen { + public: + explicit SystemInfo(DisplayApp* app, + Pinetime::Controllers::DateTime& dateTimeController, + Pinetime::Controllers::Battery& batteryController, + Pinetime::Controllers::BrightnessController& brightnessController, + Pinetime::Controllers::Ble& bleController, + Pinetime::Drivers::WatchdogView& watchdog); + ~SystemInfo() override; + bool Refresh() override; + bool OnButtonPushed() override; + bool OnTouchEvent(TouchEvents event) override; + private: + bool running = true; + + Pinetime::Controllers::DateTime& dateTimeController; + Pinetime::Controllers::Battery& batteryController; + Pinetime::Controllers::BrightnessController& brightnessController; + Pinetime::Controllers::Ble& bleController; + Pinetime::Drivers::WatchdogView& watchdog; + + char t1[200]; + char t2[200]; + char t3[30]; + + ScreenList<3> screens; + std::unique_ptr<Screen> CreateScreen1(); + std::unique_ptr<Screen> CreateScreen2(); + std::unique_ptr<Screen> CreateScreen3(); + }; + } + } +}
\ No newline at end of file diff --git a/src/DisplayApp/Screens/Tile.cpp b/src/DisplayApp/Screens/Tile.cpp index 61e3c01..1447d78 100644 --- a/src/DisplayApp/Screens/Tile.cpp +++ b/src/DisplayApp/Screens/Tile.cpp @@ -17,9 +17,16 @@ static void event_handler(lv_obj_t * obj, lv_event_t event) { screen->OnObjectEvent(obj, event, eventData); } -static const char * btnm_map1[] = {Symbols::heartBeat, Symbols::shoe, Symbols::clock, "\n", Symbols::info, Symbols::list, Symbols::sun, ""}; - -Tile::Tile(DisplayApp* app) : Screen(app) { +Tile::Tile(DisplayApp* app, std::array<Applications, 6>& applications) : Screen(app) { + for(int i = 0, appIndex = 0; i < 8; i++) { + if(i == 3) btnm_map1[i] = "\n"; + else if(i == 7) btnm_map1[i] = ""; + else { + btnm_map1[i] = applications[appIndex].icon; + apps[appIndex] = applications[appIndex].application; + appIndex++; + } + } modal.reset(new Modal(app)); btnm1 = lv_btnm_create(lv_scr_act(), NULL); @@ -39,63 +46,16 @@ bool Tile::Refresh() { } void Tile::OnObjectEvent(lv_obj_t *obj, lv_event_t event, uint32_t buttonId) { - auto* tile = static_cast<Tile*>(obj->user_data); if(event == LV_EVENT_VALUE_CHANGED) { - switch(buttonId) { - case 0: - tile->StartMeterApp(); - break; - case 1: - tile->StartGaugeApp(); - break; - case 2: - tile->StartClockApp(); - break; - case 3: - char versionStr[20]; - sprintf(versionStr, "VERSION: %d.%d.%d", Version::Major(), Version::Minor(), Version::Patch()); - modal->Show(versionStr); - break; - case 4: - tile->StartSysInfoApp(); - break; - case 5: - tile->StartBrightnessApp(); - - break; - } - clickCount++; + app->StartApp(apps[buttonId]); + running = false; } } bool Tile::OnButtonPushed() { - app->StartApp(DisplayApp::Apps::Clock); + app->StartApp(Apps::Clock); running = false; return true; } -void Tile::StartClockApp() { - app->StartApp(DisplayApp::Apps::Clock); - running = false; -} - -void Tile::StartSysInfoApp() { - app->StartApp(DisplayApp::Apps::SysInfo); - running = false; -} - -void Tile::StartBrightnessApp() { - app->StartApp(DisplayApp::Apps::Brightness); - running = false; -} - -void Tile::StartMeterApp() { - app->StartApp(DisplayApp::Apps::Meter); - running = false; -} - -void Tile::StartGaugeApp() { - app->StartApp(DisplayApp::Apps::Gauge); - running = false; -} diff --git a/src/DisplayApp/Screens/Tile.h b/src/DisplayApp/Screens/Tile.h index a04b58a..3136d89 100644 --- a/src/DisplayApp/Screens/Tile.h +++ b/src/DisplayApp/Screens/Tile.h @@ -5,13 +5,19 @@ #include <bits/unique_ptr.h> #include "Modal.h" #include <lvgl/src/lv_core/lv_style.h> +#include <DisplayApp/Apps.h> namespace Pinetime { namespace Applications { namespace Screens { class Tile : public Screen { public: - explicit Tile(DisplayApp* app); + struct Applications { + const char* icon; + Pinetime::Applications::Apps application; + }; + + explicit Tile(DisplayApp* app, std::array<Applications, 6>& applications); ~Tile() override; bool Refresh() override; @@ -20,40 +26,13 @@ namespace Pinetime { void OnObjectEvent(lv_obj_t* obj, lv_event_t event, uint32_t buttonId); private: - - lv_style_t* labelRelStyle; - lv_style_t* labelPrStyle; - lv_obj_t * label1; - lv_obj_t * label2; - lv_obj_t * label3; - - lv_obj_t* backgroundLabel; - lv_obj_t * button; - lv_obj_t * labelClick; - - lv_obj_t *tileview; - lv_obj_t * tile1; - lv_obj_t * tile2; - lv_obj_t * list; - lv_obj_t * list_btn; - lv_obj_t * tile3; - lv_obj_t * btn1; - lv_obj_t * btn2; - lv_obj_t * btn3; - lv_obj_t * btnm1; - lv_obj_t * btnm2; - - uint32_t clickCount = 0 ; - uint32_t previousClickCount = 0; - void StartClockApp(); - void StartSysInfoApp(); - void StartMeterApp(); - void StartGaugeApp(); bool running = true; std::unique_ptr<Modal> modal; - void StartBrightnessApp(); + + const char* btnm_map1[8]; + Pinetime::Applications::Apps apps[6]; }; } } diff --git a/src/SystemTask/SystemMonitor.h b/src/SystemTask/SystemMonitor.h index 8fcfafb..ec1fd81 100644 --- a/src/SystemTask/SystemMonitor.h +++ b/src/SystemTask/SystemMonitor.h @@ -28,7 +28,7 @@ namespace Pinetime { if(xTaskGetTickCount() - lastTick > 10000) { NRF_LOG_INFO("---------------------------------------\nFree heap : %d", xPortGetFreeHeapSize()); auto nb = uxTaskGetSystemState(tasksStatus, 10, NULL); - for (int i = 0; i < nb; i++) { + for (uint32_t i = 0; i < nb; i++) { NRF_LOG_INFO("Task [%s] - %d", tasksStatus[i].pcTaskName, tasksStatus[i].usStackHighWaterMark); if (tasksStatus[i].usStackHighWaterMark < 20) NRF_LOG_INFO("WARNING!!! Task %s task is nearly full, only %dB available", tasksStatus[i].pcTaskName, diff --git a/src/SystemTask/SystemTask.cpp b/src/SystemTask/SystemTask.cpp index 8f56586..a4e6356 100644 --- a/src/SystemTask/SystemTask.cpp +++ b/src/SystemTask/SystemTask.cpp @@ -12,6 +12,7 @@ #include <host/util/util.h> #include <drivers/InternalFlash.h> #include "../main.h" +#include "Components/Ble/NimbleController.h" using namespace Pinetime::System; @@ -57,14 +58,7 @@ void SystemTask::Work() { spi.Init(); spiNorFlash.Init(); - - // Write the 'image OK' flag if it's not already done - // TODO implement a better verification mecanism for the image (ask for user confirmation via UI/BLE ?) - uint32_t* imageOkPtr = reinterpret_cast<uint32_t *>(0x7BFE8); - uint32_t imageOk = *imageOkPtr; - if(imageOk != 1) - Pinetime::Drivers::InternalFlash::WriteWord(0x7BFE8, 1); - + spiNorFlash.Wakeup(); nimbleController.Init(); nimbleController.StartAdvertising(); lcd.Init(); @@ -112,22 +106,33 @@ void SystemTask::Work() { Messages message = static_cast<Messages >(msg); switch(message) { case Messages::GoToRunning: - isSleeping = false; + spi.Wakeup(); + twiMaster.Wakeup(); + + spiNorFlash.Wakeup(); + lcd.Wakeup(); + touchPanel.Wakeup(); + + displayApp->PushMessage(Applications::DisplayApp::Messages::GoToRunning); + displayApp->PushMessage(Applications::DisplayApp::Messages::UpdateBatteryLevel); + xTimerStart(idleTimer, 0); nimbleController.StartAdvertising(); + isSleeping = false; + isWakingUp = false; break; case Messages::GoToSleep: + isGoingToSleep = true; NRF_LOG_INFO("[SystemTask] Going to sleep"); xTimerStop(idleTimer, 0); displayApp->PushMessage(Pinetime::Applications::DisplayApp::Messages::GoToSleep); - isSleeping = true; break; case Messages::OnNewTime: ReloadIdleTimer(); displayApp->PushMessage(Pinetime::Applications::DisplayApp::Messages::UpdateDateTime); break; case Messages::OnNewNotification: - if(isSleeping) GoToRunning(); + if(isSleeping && !isWakingUp) GoToRunning(); displayApp->PushMessage(Pinetime::Applications::DisplayApp::Messages::NewNotification); break; case Messages::BleConnected: @@ -137,13 +142,12 @@ void SystemTask::Work() { break; case Messages::BleFirmwareUpdateStarted: doNotGoToSleep = true; - if(isSleeping) GoToRunning(); + if(isSleeping && !isWakingUp) GoToRunning(); displayApp->PushMessage(Pinetime::Applications::DisplayApp::Messages::BleFirmwareUpdateStarted); break; case Messages::BleFirmwareUpdateFinished: doNotGoToSleep = false; xTimerStart(idleTimer, 0); - displayApp->PushMessage(Pinetime::Applications::DisplayApp::Messages::BleFirmwareUpdateFinished); if(bleController.State() == Pinetime::Controllers::Ble::FirmwareUpdateStates::Validated) NVIC_SystemReset(); break; @@ -153,6 +157,16 @@ void SystemTask::Work() { case Messages::OnButtonEvent: ReloadIdleTimer(); break; + case Messages::OnDisplayTaskSleeping: + spiNorFlash.Sleep(); + lcd.Sleep(); + touchPanel.Sleep(); + + spi.Sleep(); + twiMaster.Sleep(); + isSleeping = true; + isGoingToSleep = false; + break; default: break; } } @@ -180,24 +194,27 @@ void SystemTask::Work() { } void SystemTask::OnButtonPushed() { + if(isGoingToSleep) return; if(!isSleeping) { NRF_LOG_INFO("[SystemTask] Button pushed"); PushMessage(Messages::OnButtonEvent); displayApp->PushMessage(Pinetime::Applications::DisplayApp::Messages::ButtonPushed); } else { - NRF_LOG_INFO("[SystemTask] Button pushed, waking up"); - GoToRunning(); + if(!isWakingUp) { + NRF_LOG_INFO("[SystemTask] Button pushed, waking up"); + GoToRunning(); + } } } void SystemTask::GoToRunning() { + isWakingUp = true; PushMessage(Messages::GoToRunning); - displayApp->PushMessage(Applications::DisplayApp::Messages::GoToRunning); - displayApp->PushMessage(Applications::DisplayApp::Messages::UpdateBatteryLevel); } void SystemTask::OnTouchEvent() { + if(isGoingToSleep) return ; NRF_LOG_INFO("[SystemTask] Touch event"); if(!isSleeping) { PushMessage(Messages::OnTouchEvent); @@ -206,6 +223,9 @@ void SystemTask::OnTouchEvent() { } void SystemTask::PushMessage(SystemTask::Messages msg) { + if(msg == Messages::GoToSleep) { + isGoingToSleep = true; + } BaseType_t xHigherPriorityTaskWoken; xHigherPriorityTaskWoken = pdFALSE; xQueueSendFromISR(systemTaksMsgQueue, &msg, &xHigherPriorityTaskWoken); @@ -222,6 +242,6 @@ void SystemTask::OnIdle() { } void SystemTask::ReloadIdleTimer() const { - if(isSleeping) return; + if(isSleeping || isGoingToSleep) return; xTimerReset(idleTimer, 0); } diff --git a/src/SystemTask/SystemTask.h b/src/SystemTask/SystemTask.h index 8fa7e7d..40277cf 100644 --- a/src/SystemTask/SystemTask.h +++ b/src/SystemTask/SystemTask.h @@ -8,16 +8,17 @@ #include <Components/Battery/BatteryController.h> #include <DisplayApp/DisplayApp.h> #include <drivers/Watchdog.h> -#include <Components/Ble/NimbleController.h> #include <drivers/SpiNorFlash.h> #include "SystemMonitor.h" +#include "Components/Ble/NimbleController.h" +#include "timers.h" namespace Pinetime { namespace System { class SystemTask { public: enum class Messages {GoToSleep, GoToRunning, OnNewTime, OnNewNotification, BleConnected, - BleFirmwareUpdateStarted, BleFirmwareUpdateFinished, OnTouchEvent, OnButtonEvent + BleFirmwareUpdateStarted, BleFirmwareUpdateFinished, OnTouchEvent, OnButtonEvent, OnDisplayTaskSleeping }; SystemTask(Drivers::SpiMaster &spi, Drivers::St7789 &lcd, @@ -37,6 +38,8 @@ namespace Pinetime { void OnIdle(); + Pinetime::Controllers::NimbleController& nimble() {return nimbleController;}; + private: TaskHandle_t taskHandle; @@ -51,7 +54,9 @@ namespace Pinetime { Pinetime::Controllers::Ble& bleController; Pinetime::Controllers::DateTime& dateTimeController; QueueHandle_t systemTaksMsgQueue; - bool isSleeping = false; + std::atomic<bool> isSleeping{false}; + std::atomic<bool> isGoingToSleep{false}; + std::atomic<bool> isWakingUp{false}; Pinetime::Drivers::Watchdog watchdog; Pinetime::Drivers::WatchdogView watchdogView; Pinetime::Controllers::NotificationManager& notificationManager; @@ -84,4 +89,4 @@ namespace Pinetime { #endif }; } -}
\ No newline at end of file +} diff --git a/src/Version.h.in b/src/Version.h.in index c68a03c..6ff5938 100644 --- a/src/Version.h.in +++ b/src/Version.h.in @@ -5,12 +5,14 @@ namespace Pinetime { class Version { public: - static uint32_t Major() {return major;} - static uint32_t Minor() {return minor;} - static uint32_t Patch() {return patch;} + static constexpr uint32_t Major() {return major;} + static constexpr uint32_t Minor() {return minor;} + static constexpr uint32_t Patch() {return patch;} + static constexpr const char* VersionString() {return versionString;} private: static constexpr uint32_t major = @PROJECT_VERSION_MAJOR@; static constexpr uint32_t minor = @PROJECT_VERSION_MINOR@; static constexpr uint32_t patch = @PROJECT_VERSION_PATCH@; + static constexpr const char* versionString = "@PROJECT_VERSION_MAJOR@.@PROJECT_VERSION_MINOR@.@PROJECT_VERSION_PATCH@"; }; }
\ No newline at end of file diff --git a/src/drivers/Cst816s.cpp b/src/drivers/Cst816s.cpp index 60cd402..f681654 100644 --- a/src/drivers/Cst816s.cpp +++ b/src/drivers/Cst816s.cpp @@ -2,7 +2,6 @@ #include <task.h> #include <nrfx_log.h> #include <legacy/nrf_drv_gpiote.h> - #include "Cst816s.h" using namespace Pinetime::Drivers; @@ -60,9 +59,9 @@ Cst816S::TouchInfos Cst816S::GetTouchInfo() { uint16_t y = (yHigh << 8) | yLow; auto action = touchData[touchEventIndex + (touchStep * i)] >> 6; /* 0 = Down, 1 = Up, 2 = contact*/ - auto finger = touchData[touchIdIndex + (touchStep * i)] >> 4; - auto pressure = touchData[touchXYIndex + (touchStep * i)]; - auto area = touchData[touchMiscIndex + (touchStep * i)] >> 4; + //auto finger = touchData[touchIdIndex + (touchStep * i)] >> 4; + //auto pressure = touchData[touchXYIndex + (touchStep * i)]; + //auto area = touchData[touchMiscIndex + (touchStep * i)] >> 4; info.x = x; info.y = y; @@ -89,7 +88,6 @@ Cst816S::TouchInfos Cst816S::GetTouchInfo() { // case Gestures::LongPress: NRF_LOG_INFO("Gesture : Long press"); break; // default : NRF_LOG_INFO("Unknown"); break; // } - } @@ -97,12 +95,16 @@ Cst816S::TouchInfos Cst816S::GetTouchInfo() { } void Cst816S::Sleep() { - // TODO re enable sleep mode - //twiMaster.Sleep(); - nrf_gpio_cfg_default(6); - nrf_gpio_cfg_default(7); + nrf_gpio_pin_clear(pinReset); + vTaskDelay(5); + nrf_gpio_pin_set(pinReset); + vTaskDelay(50); + static constexpr uint8_t sleepValue = 0x03; + twiMaster.Write(twiAddress, 0xA5, &sleepValue, 1); + NRF_LOG_INFO("[TOUCHPANEL] Sleep"); } void Cst816S::Wakeup() { Init(); + NRF_LOG_INFO("[TOUCHPANEL] Wakeup"); }
\ No newline at end of file diff --git a/src/drivers/Spi.cpp b/src/drivers/Spi.cpp index bf08178..2d8aa3b 100644 --- a/src/drivers/Spi.cpp +++ b/src/drivers/Spi.cpp @@ -1,4 +1,5 @@ #include <hal/nrf_gpio.h> +#include <nrfx_log.h> #include "Spi.h" using namespace Pinetime::Drivers; @@ -18,8 +19,12 @@ bool Spi::Read(uint8_t* cmd, size_t cmdSize, uint8_t *data, size_t dataSize) { } void Spi::Sleep() { - // TODO sleep spi nrf_gpio_cfg_default(pinCsn); + NRF_LOG_INFO("[SPI] Sleep") +} + +bool Spi::WriteCmdAndBuffer(const uint8_t *cmd, size_t cmdSize, const uint8_t *data, size_t dataSize) { + return spiMaster.WriteCmdAndBuffer(pinCsn, cmd, cmdSize, data, dataSize); } bool Spi::Init() { @@ -27,8 +32,10 @@ bool Spi::Init() { return true; } -bool Spi::WriteCmdAndBuffer(const uint8_t *cmd, size_t cmdSize, const uint8_t *data, size_t dataSize) { - return spiMaster.WriteCmdAndBuffer(pinCsn, cmd, cmdSize, data, dataSize); +void Spi::Wakeup() { + nrf_gpio_cfg_output(pinCsn); + nrf_gpio_pin_set(pinCsn); + NRF_LOG_INFO("[SPI] Wakeup") } diff --git a/src/drivers/SpiMaster.cpp b/src/drivers/SpiMaster.cpp index 8087d38..2e5852a 100644 --- a/src/drivers/SpiMaster.cpp +++ b/src/drivers/SpiMaster.cpp @@ -4,6 +4,7 @@ #include "SpiMaster.h" #include <algorithm> #include <task.h> +#include <nrfx_log.h> using namespace Pinetime::Drivers; @@ -117,8 +118,6 @@ void SpiMaster::OnEndEvent() { spiBaseAddress->TASKS_START = 1; } else { - uint8_t* buffer = nullptr; - size_t size = 0; if(taskToNotify != nullptr) { BaseType_t xHigherPriorityTaskWoken = pdFALSE; vTaskNotifyGiveFromISR(taskToNotify, &xHigherPriorityTaskWoken); @@ -233,10 +232,13 @@ void SpiMaster::Sleep() { nrf_gpio_cfg_default(params.pinSCK); nrf_gpio_cfg_default(params.pinMOSI); nrf_gpio_cfg_default(params.pinMISO); + + NRF_LOG_INFO("[SPIMASTER] sleep") } void SpiMaster::Wakeup() { Init(); + NRF_LOG_INFO("[SPIMASTER] Wakeup"); } bool SpiMaster::WriteCmdAndBuffer(uint8_t pinCsn, const uint8_t *cmd, size_t cmdSize, const uint8_t *data, size_t dataSize) { diff --git a/src/drivers/SpiNorFlash.cpp b/src/drivers/SpiNorFlash.cpp index 7e4da1c..351a9df 100644 --- a/src/drivers/SpiNorFlash.cpp +++ b/src/drivers/SpiNorFlash.cpp @@ -11,8 +11,8 @@ SpiNorFlash::SpiNorFlash(Spi& spi) : spi{spi} { } void SpiNorFlash::Init() { - auto id = ReadIdentificaion(); - NRF_LOG_INFO("[SPI FLASH] Manufacturer : %d, Memory type : %d, memory density : %d", id.manufacturer, id.type, id.density); + device_id = ReadIdentificaion(); + NRF_LOG_INFO("[SPI FLASH] Manufacturer : %d, Memory type : %d, memory density : %d", device_id.manufacturer, device_id.type, device_id.density); } void SpiNorFlash::Uninit() { @@ -20,11 +20,25 @@ void SpiNorFlash::Uninit() { } void SpiNorFlash::Sleep() { - + auto cmd = static_cast<uint8_t>(Commands::DeepPowerDown); + spi.Write(&cmd, sizeof(uint8_t)); + NRF_LOG_INFO("[FLASH] Sleep") } void SpiNorFlash::Wakeup() { - + // send Commands::ReleaseFromDeepPowerDown then 3 dummy bytes before reading Device ID + static constexpr uint8_t cmdSize = 4; + uint8_t cmd[cmdSize] = {static_cast<uint8_t>(Commands::ReleaseFromDeepPowerDown), 0x01, 0x02, 0x03}; + uint8_t id = 0; + spi.Read(reinterpret_cast<uint8_t *>(&cmd), cmdSize, &id, 1); + auto devId = device_id = ReadIdentificaion(); + if(devId.type != device_id.type) { + NRF_LOG_INFO("[SpiNorFlash] ID on Wakeup: Failed"); + } + else { + NRF_LOG_INFO("[SpiNorFlash] ID on Wakeup: %d", id); + } + NRF_LOG_INFO("[FLASH] Wakeup") } SpiNorFlash::Identification SpiNorFlash::ReadIdentificaion() { diff --git a/src/drivers/SpiNorFlash.h b/src/drivers/SpiNorFlash.h index 98267c0..10c25a0 100644 --- a/src/drivers/SpiNorFlash.h +++ b/src/drivers/SpiNorFlash.h @@ -48,11 +48,13 @@ namespace Pinetime { SectorErase = 0x20, ReadSecurityRegister = 0x2B, ReadIdentification = 0x9F, + ReleaseFromDeepPowerDown = 0xAB, + DeepPowerDown = 0xB9 }; static constexpr uint16_t pageSize = 256; Spi& spi; - + Identification device_id; }; } } diff --git a/src/drivers/St7789.cpp b/src/drivers/St7789.cpp index 09269af..ed28c82 100644 --- a/src/drivers/St7789.cpp +++ b/src/drivers/St7789.cpp @@ -1,5 +1,6 @@ #include <hal/nrf_gpio.h> #include <libraries/delay/nrf_delay.h> +#include <nrfx_log.h> #include "St7789.h" #include "Spi.h" @@ -174,12 +175,10 @@ void St7789::HardwareReset() { void St7789::Sleep() { SleepIn(); nrf_gpio_cfg_default(pinDataCommand); -// spi.Sleep(); // TODO sleep SPI + NRF_LOG_INFO("[LCD] Sleep"); } void St7789::Wakeup() { -// spi.Wakeup(); // TODO wake up SPI - nrf_gpio_cfg_output(pinDataCommand); // TODO why do we need to reset the controller? HardwareReset(); @@ -193,4 +192,5 @@ void St7789::Wakeup() { NormalModeOn(); VerticalScrollStartAddress(verticalScrollingStartAddress); DisplayOn(); + NRF_LOG_INFO("[LCD] Wakeup") } diff --git a/src/drivers/TwiMaster.cpp b/src/drivers/TwiMaster.cpp index 5d8fcf6..a9eb5d0 100644 --- a/src/drivers/TwiMaster.cpp +++ b/src/drivers/TwiMaster.cpp @@ -1,5 +1,5 @@ -#include <sdk/integration/nrfx/nrfx_log.h> -#include <sdk/modules/nrfx/hal/nrf_gpio.h> +#include <nrfx_log.h> +#include <hal/nrf_gpio.h> #include <cstring> #include "TwiMaster.h" @@ -137,4 +137,18 @@ void TwiMaster::Write(uint8_t deviceAddress, const uint8_t *data, size_t size, b uint32_t error = twiBaseAddress->ERRORSRC; twiBaseAddress->ERRORSRC = error; } -}
\ No newline at end of file +} + +void TwiMaster::Sleep() { + while(twiBaseAddress->ENABLE != 0) { + twiBaseAddress->ENABLE = (TWIM_ENABLE_ENABLE_Disabled << TWIM_ENABLE_ENABLE_Pos); + } + nrf_gpio_cfg_default(6); + nrf_gpio_cfg_default(7); + NRF_LOG_INFO("[TWIMASTER] Sleep"); +} + +void TwiMaster::Wakeup() { + Init(); + NRF_LOG_INFO("[TWIMASTER] Wakeup"); +} diff --git a/src/drivers/TwiMaster.h b/src/drivers/TwiMaster.h index 3b7555f..9b6b507 100644 --- a/src/drivers/TwiMaster.h +++ b/src/drivers/TwiMaster.h @@ -22,6 +22,9 @@ namespace Pinetime { void Read(uint8_t deviceAddress, uint8_t registerAddress, uint8_t* buffer, size_t size); void Write(uint8_t deviceAddress, uint8_t registerAddress, const uint8_t* data, size_t size); + void Sleep(); + void Wakeup(); + private: void Read(uint8_t deviceAddress, uint8_t* buffer, size_t size, bool stop); void Write(uint8_t deviceAddress, const uint8_t* data, size_t size, bool stop); diff --git a/src/graphics.cpp b/src/graphics.cpp index 3b53703..9373a9b 100644 --- a/src/graphics.cpp +++ b/src/graphics.cpp @@ -79,6 +79,7 @@ void Process(void* instance) { NRF_LOG_INFO("Init..."); spi.Init(); spiNorFlash.Init(); + spiNorFlash.Wakeup(); brightnessController.Init(); lcd.Init(); gfx.Init(); @@ -103,10 +104,10 @@ void Process(void* instance) { static constexpr uint32_t screenWidth = 240; static constexpr uint32_t screenWidthInBytes = screenWidth*2; // LCD display 16bits color (1 pixel = 2 bytes) uint16_t displayLineBuffer[screenWidth]; - for(int line = 0; line < screenWidth; line++) { + for(uint32_t line = 0; line < screenWidth; line++) { spiNorFlash.Read(line*screenWidthInBytes, reinterpret_cast<uint8_t *>(displayLineBuffer), screenWidth); spiNorFlash.Read((line*screenWidthInBytes)+screenWidth, reinterpret_cast<uint8_t *>(displayLineBuffer) + screenWidth, screenWidth); - for(int col = 0; col < screenWidth; col++) { + for(uint32_t col = 0; col < screenWidth; col++) { gfx.pixel_draw(col, line, displayLineBuffer[col]); } } diff --git a/src/libs/mynewt-nimble/nimble/host/src/ble_gap.c b/src/libs/mynewt-nimble/nimble/host/src/ble_gap.c index be4a1cb..e32482e 100644 --- a/src/libs/mynewt-nimble/nimble/host/src/ble_gap.c +++ b/src/libs/mynewt-nimble/nimble/host/src/ble_gap.c @@ -310,12 +310,14 @@ ble_gap_log_conn(uint8_t own_addr_type, const ble_addr_t *peer_addr, BLE_HS_LOG_ADDR(INFO, peer_addr->val); } + /* // NRF LOG support max 6 params in log BLE_HS_LOG(INFO, " scan_itvl=%d scan_window=%d itvl_min=%d itvl_max=%d " "latency=%d supervision_timeout=%d min_ce_len=%d " "max_ce_len=%d own_addr_type=%d", params->scan_itvl, params->scan_window, params->itvl_min, params->itvl_max, params->latency, params->supervision_timeout, params->min_ce_len, params->max_ce_len, own_addr_type); + */ } #endif |
