From bc88fed0a0ce133875cce46aed1abab9756804cf Mon Sep 17 00:00:00 2001 From: Koen <75178793+koenraijer@users.noreply.github.com> Date: Sat, 15 Feb 2025 11:09:01 +0100 Subject: [PATCH 01/13] Create build.yml --- .github/workflows/build.yml | 171 ++++++++++++++++++++++++++++++++++++ 1 file changed, 171 insertions(+) create mode 100644 .github/workflows/build.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000000..df7a4bab7e --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,171 @@ +# GitHub Actions Workflow to build FreeRTOS Firmware for PineTime Smart Watch +# See https://lupyuen.github.io/pinetime-rust-mynewt/articles/cloud +# Based on https://github.com/JF002/Pinetime/blob/master/doc/buildAndProgram.md +# and https://github.com/JF002/Pinetime/blob/master/bootloader/README.md + +# Name of this Workflow +name: Build PineTime Firmware + +# When to run this Workflow... +on: + + # Run this Workflow when files are updated (Pushed) in the "master" Branch + push: + branches: [ master ] + + # Also run this Workflow when a Pull Request is created or updated in the "master" Branch + pull_request: + branches: [ master ] + +# Steps to run for the Workflow +jobs: + build: + + # Run these steps on Ubuntu + runs-on: ubuntu-latest + + steps: + + ######################################################################################### + # Download and Cache Dependencies + + - name: Install cmake + uses: lukka/get-cmake@v3.18.0 + + - name: Check cache for Embedded Arm Toolchain arm-none-eabi-gcc + id: cache-toolchain + uses: actions/cache@v2 + env: + cache-name: cache-toolchain-9-2020-q2 + with: + path: ${{ runner.temp }}/arm-none-eabi + key: ${{ runner.os }}-build-${{ env.cache-name }} + restore-keys: ${{ runner.os }}-build-${{ env.cache-name }} + + - name: Install Embedded Arm Toolchain arm-none-eabi-gcc + if: steps.cache-toolchain.outputs.cache-hit != 'true' # Install toolchain if not found in cache + uses: fiam/arm-none-eabi-gcc@v1.0.2 + with: + # GNU Embedded Toolchain for Arm release name, in the V-YYYY-qZ format (e.g. "9-2019-q4") + release: 9-2020-q2 + # Directory to unpack GCC to. Defaults to a temporary directory. + directory: ${{ runner.temp }}/arm-none-eabi + + - name: Check cache for nRF5 SDK + id: cache-nrf5sdk + uses: actions/cache@v2 + env: + cache-name: cache-nrf5sdk + with: + path: ${{ runner.temp }}/nrf5_sdk + key: ${{ runner.os }}-build-${{ env.cache-name }} + restore-keys: ${{ runner.os }}-build-${{ env.cache-name }} + + - name: Install nRF5 SDK + if: steps.cache-nrf5sdk.outputs.cache-hit != 'true' # Install SDK if not found in cache + run: | + cd ${{ runner.temp }} + curl https://developer.nordicsemi.com/nRF5_SDK/nRF5_SDK_v15.x.x/nRF5_SDK_15.3.0_59ac345.zip -o nrf5_sdk.zip + unzip nrf5_sdk.zip + mv nRF5_SDK_15.3.0_59ac345 nrf5_sdk + + - name: Check cache for MCUBoot + id: cache-mcuboot + uses: actions/cache@v2 + env: + cache-name: cache-mcuboot + with: + path: ${{ runner.temp }}/mcuboot + key: ${{ runner.os }}-build-${{ env.cache-name }} + restore-keys: ${{ runner.os }}-build-${{ env.cache-name }} + + - name: Install MCUBoot + if: steps.cache-mcuboot.outputs.cache-hit != 'true' # Install MCUBoot if not found in cache + run: | + cd ${{ runner.temp }} + git clone --branch v1.5.0 https://github.com/JuulLabs-OSS/mcuboot + + - name: Install imgtool dependencies + run: pip3 install --user -r ${{ runner.temp }}/mcuboot/scripts/requirements.txt + + - name: Install adafruit-nrfutil + run: | + pip3 install --user wheel + pip3 install --user setuptools + pip3 install --user adafruit-nrfutil + + ######################################################################################### + # Checkout + + - name: Checkout source files + uses: actions/checkout@v2 + + - name: Show files + run: set ; pwd ; ls -l + + ######################################################################################### + # CMake + + - name: CMake + run: | + mkdir -p build + cd build + cmake -DARM_NONE_EABI_TOOLCHAIN_PATH=${{ runner.temp }}/arm-none-eabi -DNRF5_SDK_PATH=${{ runner.temp }}/nrf5_sdk -DUSE_OPENOCD=1 ../ + + ######################################################################################### + # Make and Upload DFU Package + # pinetime-mcuboot-app.img must be flashed at address 0x8000 in the internal flash memory with OpenOCD: + # program image.bin 0x8000 + + # For Debugging Builds: Remove "make" option "-j" for clearer output. Add "--trace" to see details. + # For Faster Builds: Add "make" option "-j" + + - name: Make pinetime-mcuboot-app + run: | + cd build + make pinetime-mcuboot-app + + - name: Create firmware image + run: | + # The generated firmware binary looks like "pinetime-mcuboot-app-0.8.2.bin" + ls -l build/src/pinetime-mcuboot-app*.bin + ${{ runner.temp }}/mcuboot/scripts/imgtool.py create --align 4 --version 1.0.0 --header-size 32 --slot-size 475136 --pad-header build/src/pinetime-mcuboot-app*.bin build/src/pinetime-mcuboot-app-img.bin + ${{ runner.temp }}/mcuboot/scripts/imgtool.py verify build/src/pinetime-mcuboot-app-img.bin + + - name: Create DFU package + run: | + ~/.local/bin/adafruit-nrfutil dfu genpkg --dev-type 0x0052 --application build/src/pinetime-mcuboot-app-img.bin build/src/pinetime-mcuboot-app-dfu.zip + unzip -v build/src/pinetime-mcuboot-app-dfu.zip + # Unzip the package because Upload Artifact will zip up the files + unzip build/src/pinetime-mcuboot-app-dfu.zip -d build/src/pinetime-mcuboot-app-dfu + + - name: Upload DFU package + uses: actions/upload-artifact@v2 + with: + name: pinetime-mcuboot-app-dfu.zip + path: build/src/pinetime-mcuboot-app-dfu/* + + ######################################################################################### + # Make and Upload Standalone Firmware + + - name: Make pinetime-app + run: | + cd build + make pinetime-app + + - name: Upload standalone firmware + uses: actions/upload-artifact@v2 + with: + name: pinetime-app.out + path: build/src/pinetime-app*.out + + ######################################################################################### + # Finish + + - name: Find output + run: | + find . -name "pinetime-app.*" -ls + find . -name "pinetime-mcuboot-app.*" -ls + +# Embedded Arm Toolchain and nRF5 SDK will only be cached if the build succeeds. +# So make sure that the first build always succeeds, e.g. comment out the "Make" step. From f32fb1ddfec0ca984eef56df94d87860b6a09a14 Mon Sep 17 00:00:00 2001 From: Koen <75178793+koenraijer@users.noreply.github.com> Date: Sun, 16 Feb 2025 09:04:59 +0100 Subject: [PATCH 02/13] Update StopWatch.cpp 1. The lap time displays the duration of the lap instead of the time at which the lap button was pressed. 2. The current lap's time that has elapsed should already be displayed for "running laps" that haven't been stopped yet. --- src/displayapp/screens/StopWatch.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/displayapp/screens/StopWatch.cpp b/src/displayapp/screens/StopWatch.cpp index ff852beb69..cfa311ba62 100644 --- a/src/displayapp/screens/StopWatch.cpp +++ b/src/displayapp/screens/StopWatch.cpp @@ -191,12 +191,15 @@ void StopWatch::stopLapBtnEventHandler() { if (currentState == States::Running) { lv_label_set_text(lapText, ""); lapsDone = std::min(lapsDone + 1, maxLapCount); + TickType_t lastLapTime = 0; for (int i = lapsDone - displayedLaps; i < lapsDone; i++) { if (i < 0) { lv_label_ins_text(lapText, LV_LABEL_POS_LAST, "\n"); continue; } - TimeSeparated_t times = convertTicksToTimeSegments(laps[i]); + TickType_t lapDuration = laps[i] - lastLapTime; + lastLapTime = laps[i]; + TimeSeparated_t times = convertTicksToTimeSegments(lapDuration); char buffer[17]; if (times.hours == 0) { snprintf(buffer, sizeof(buffer), "#%2d %2d:%02d.%02d\n", i + 1, times.mins, times.secs, times.hundredths); From 2c3ea1e6848f3a5afafce9f9c79ae21c6a3a7dd0 Mon Sep 17 00:00:00 2001 From: Koen Raijer Date: Sun, 16 Feb 2025 13:34:34 +0100 Subject: [PATCH 03/13] updated StopWatch --- src/displayapp/screens/StopWatch.cpp | 85 +++++++++++++++++++++------- src/displayapp/screens/StopWatch.h | 1 + 2 files changed, 67 insertions(+), 19 deletions(-) diff --git a/src/displayapp/screens/StopWatch.cpp b/src/displayapp/screens/StopWatch.cpp index cfa311ba62..fb2319b62e 100644 --- a/src/displayapp/screens/StopWatch.cpp +++ b/src/displayapp/screens/StopWatch.cpp @@ -135,6 +135,65 @@ void StopWatch::Start() { startTime = xTaskGetTickCount(); currentState = States::Running; wakeLock.Lock(); + + // Add first lap automatically when starting + if (lapsDone == 0) { + lapsDone = 1; + laps[0] = 0; // Current lap starts at 0 + updateLapDisplay(); + } +} + +// Add new method to update lap display: +void StopWatch::updateLapDisplay() { + // Pre-allocate string buffer with estimated capacity + std::string displayText; + // Reserve space for maximum possible size: 2 laps × ~20 chars per lap + displayText.reserve(displayedLaps * 20); + + // Use std::array for safe buffer handling + std::array buffer{}; + + for (int i = lapsDone - displayedLaps; i < lapsDone; i++) { + if (i < 0) { + displayText += '\n'; + continue; + } + + TimeSeparated_t times; + if (i == lapsDone - 1 && currentState == States::Running) { + // For current lap, calculate time since last lap + TickType_t currentLapTime = xTaskGetTickCount() - startTime; + if (i > 0) { + currentLapTime += oldTimeElapsed - laps[i-1]; + } + times = convertTicksToTimeSegments(currentLapTime); + } else { + // For completed laps, show the lap duration + TickType_t lapDuration = (i == 0) ? laps[i] : laps[i] - laps[i-1]; + times = convertTicksToTimeSegments(lapDuration); + } + + // Use snprintf with proper bounds checking + int written; + if (times.hours == 0) { + written = snprintf(buffer.data(), buffer.size(), + "#%2d %2d:%02d.%02d\n", + i + 1, times.mins, times.secs, times.hundredths); + } else { + written = snprintf(buffer.data(), buffer.size(), + "#%2d %2d:%02d:%02d.%02d\n", + i + 1, times.hours, times.mins, times.secs, times.hundredths); + } + + // Only append if snprintf was successful + if (written > 0 && written < static_cast(buffer.size())) { + displayText += buffer.data(); + } + } + + // Update display in one operation + lv_label_set_text(lapText, displayText.c_str()); } void StopWatch::Pause() { @@ -163,6 +222,9 @@ void StopWatch::Refresh() { } } lv_label_set_text_fmt(msecTime, "%02d", currentTimeSeparated.hundredths); + + // Update the lap display + updateLapDisplay(); } else if (currentState == States::Halted) { const TickType_t currentTime = xTaskGetTickCount(); if (currentTime > blinkTime) { @@ -189,25 +251,10 @@ void StopWatch::playPauseBtnEventHandler() { void StopWatch::stopLapBtnEventHandler() { // If running, then this button is used to save laps if (currentState == States::Running) { - lv_label_set_text(lapText, ""); + // Store the current lap time + laps[lapsDone-1] = oldTimeElapsed + xTaskGetTickCount() - startTime; lapsDone = std::min(lapsDone + 1, maxLapCount); - TickType_t lastLapTime = 0; - for (int i = lapsDone - displayedLaps; i < lapsDone; i++) { - if (i < 0) { - lv_label_ins_text(lapText, LV_LABEL_POS_LAST, "\n"); - continue; - } - TickType_t lapDuration = laps[i] - lastLapTime; - lastLapTime = laps[i]; - TimeSeparated_t times = convertTicksToTimeSegments(lapDuration); - char buffer[17]; - if (times.hours == 0) { - snprintf(buffer, sizeof(buffer), "#%2d %2d:%02d.%02d\n", i + 1, times.mins, times.secs, times.hundredths); - } else { - snprintf(buffer, sizeof(buffer), "#%2d %2d:%02d:%02d.%02d\n", i + 1, times.hours, times.mins, times.secs, times.hundredths); - } - lv_label_ins_text(lapText, LV_LABEL_POS_LAST, buffer); - } + updateLapDisplay(); } else if (currentState == States::Halted) { Reset(); } @@ -219,4 +266,4 @@ bool StopWatch::OnButtonPushed() { return true; } return false; -} +} \ No newline at end of file diff --git a/src/displayapp/screens/StopWatch.h b/src/displayapp/screens/StopWatch.h index 55a178dcbe..fce4268a88 100644 --- a/src/displayapp/screens/StopWatch.h +++ b/src/displayapp/screens/StopWatch.h @@ -36,6 +36,7 @@ namespace Pinetime { bool OnButtonPushed() override; private: + void updateLapDisplay(); void SetInterfacePaused(); void SetInterfaceRunning(); void SetInterfaceStopped(); From 980aedfde8948e07c646f6beef4b945df8fff240 Mon Sep 17 00:00:00 2001 From: Koen Raijer Date: Sun, 16 Feb 2025 13:57:15 +0100 Subject: [PATCH 04/13] reposition msec display, reverse lap time order, change lap formatting --- src/displayapp/screens/StopWatch.cpp | 50 +++++++++++++--------------- src/displayapp/screens/StopWatch.h | 2 +- 2 files changed, 24 insertions(+), 28 deletions(-) diff --git a/src/displayapp/screens/StopWatch.cpp b/src/displayapp/screens/StopWatch.cpp index fb2319b62e..f7a7003e92 100644 --- a/src/displayapp/screens/StopWatch.cpp +++ b/src/displayapp/screens/StopWatch.cpp @@ -64,7 +64,8 @@ StopWatch::StopWatch(System::SystemTask& systemTask) : wakeLock(systemTask) { msecTime = lv_label_create(lv_scr_act(), nullptr); lv_label_set_text_static(msecTime, "00"); lv_obj_set_style_local_text_color(msecTime, LV_LABEL_PART_MAIN, LV_STATE_DISABLED, Colors::lightGray); - lv_obj_align(msecTime, lapText, LV_ALIGN_OUT_TOP_MID, 0, 0); + // Position msecTime above the colon + lv_obj_align(msecTime, time, LV_ALIGN_CENTER, 0, -38); // Adjust -38 based on actual font size time = lv_label_create(lv_scr_act(), nullptr); lv_obj_set_style_local_text_font(time, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_76); @@ -144,55 +145,50 @@ void StopWatch::Start() { } } -// Add new method to update lap display: void StopWatch::updateLapDisplay() { - // Pre-allocate string buffer with estimated capacity std::string displayText; - // Reserve space for maximum possible size: 2 laps × ~20 chars per lap - displayText.reserve(displayedLaps * 20); + displayText.reserve(maxLapCount * charactersPerLapEntry); - // Use std::array for safe buffer handling std::array buffer{}; - for (int i = lapsDone - displayedLaps; i < lapsDone; i++) { - if (i < 0) { - displayText += '\n'; - continue; - } - + // Reverse loop to show newest laps first + for (int i = lapsDone - 1; i >= std::max(0, lapsDone - displayedLaps); i--) { TimeSeparated_t times; if (i == lapsDone - 1 && currentState == States::Running) { // For current lap, calculate time since last lap TickType_t currentLapTime = xTaskGetTickCount() - startTime; if (i > 0) { - currentLapTime += oldTimeElapsed - laps[i-1]; + currentLapTime += oldTimeElapsed - laps[i - 1]; } times = convertTicksToTimeSegments(currentLapTime); } else { // For completed laps, show the lap duration - TickType_t lapDuration = (i == 0) ? laps[i] : laps[i] - laps[i-1]; + TickType_t lapDuration = (i == 0) ? laps[i] : laps[i] - laps[i - 1]; times = convertTicksToTimeSegments(lapDuration); } - // Use snprintf with proper bounds checking - int written; - if (times.hours == 0) { - written = snprintf(buffer.data(), buffer.size(), - "#%2d %2d:%02d.%02d\n", - i + 1, times.mins, times.secs, times.hundredths); - } else { - written = snprintf(buffer.data(), buffer.size(), - "#%2d %2d:%02d:%02d.%02d\n", - i + 1, times.hours, times.mins, times.secs, times.hundredths); - } + int written = (times.hours == 0) + ? snprintf(buffer.data(), + buffer.size(), + "Lap %d %2d:%02d.%02d\n", + i + 1, + times.mins, + times.secs, + times.hundredths) + : snprintf(buffer.data(), + buffer.size(), + "Lap %d %2d:%02d:%02d.%02d\n", + i + 1, + times.hours, + times.mins, + times.secs, + times.hundredths); - // Only append if snprintf was successful if (written > 0 && written < static_cast(buffer.size())) { displayText += buffer.data(); } } - // Update display in one operation lv_label_set_text(lapText, displayText.c_str()); } diff --git a/src/displayapp/screens/StopWatch.h b/src/displayapp/screens/StopWatch.h index fce4268a88..20478c878b 100644 --- a/src/displayapp/screens/StopWatch.h +++ b/src/displayapp/screens/StopWatch.h @@ -52,7 +52,7 @@ namespace Pinetime { TickType_t blinkTime = 0; static constexpr int maxLapCount = 20; TickType_t laps[maxLapCount + 1]; - static constexpr int displayedLaps = 2; + static constexpr int displayedLaps = 3; int lapsDone = 0; lv_obj_t *time, *msecTime, *btnPlayPause, *btnStopLap, *txtPlayPause, *txtStopLap; lv_obj_t* lapText; From 00e9547aa86f302a1e2834d5ddc7f64508040e6f Mon Sep 17 00:00:00 2001 From: Koen Raijer Date: Sun, 16 Feb 2025 14:02:05 +0100 Subject: [PATCH 05/13] fix undeclared variable --- src/displayapp/screens/StopWatch.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/displayapp/screens/StopWatch.cpp b/src/displayapp/screens/StopWatch.cpp index f7a7003e92..45e87e46b0 100644 --- a/src/displayapp/screens/StopWatch.cpp +++ b/src/displayapp/screens/StopWatch.cpp @@ -147,7 +147,7 @@ void StopWatch::Start() { void StopWatch::updateLapDisplay() { std::string displayText; - displayText.reserve(maxLapCount * charactersPerLapEntry); + displayText.reserve(maxLapCount * 20); std::array buffer{}; From f223fcaa5892682b6cf97476306a32da8de455b5 Mon Sep 17 00:00:00 2001 From: Koen Raijer Date: Sun, 16 Feb 2025 14:27:05 +0100 Subject: [PATCH 06/13] fix stopwatch msec positioning --- src/displayapp/screens/StopWatch.cpp | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/displayapp/screens/StopWatch.cpp b/src/displayapp/screens/StopWatch.cpp index 45e87e46b0..f555f95e1f 100644 --- a/src/displayapp/screens/StopWatch.cpp +++ b/src/displayapp/screens/StopWatch.cpp @@ -61,17 +61,23 @@ StopWatch::StopWatch(System::SystemTask& systemTask) : wakeLock(systemTask) { lv_obj_set_width(lapText, LV_HOR_RES_MAX); lv_obj_align(lapText, lv_scr_act(), LV_ALIGN_IN_BOTTOM_MID, 0, -btnHeight); - msecTime = lv_label_create(lv_scr_act(), nullptr); - lv_label_set_text_static(msecTime, "00"); - lv_obj_set_style_local_text_color(msecTime, LV_LABEL_PART_MAIN, LV_STATE_DISABLED, Colors::lightGray); - // Position msecTime above the colon - lv_obj_align(msecTime, time, LV_ALIGN_CENTER, 0, -38); // Adjust -38 based on actual font size - time = lv_label_create(lv_scr_act(), nullptr); lv_obj_set_style_local_text_font(time, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_76); lv_label_set_text_static(time, "00:00"); lv_obj_set_style_local_text_color(time, LV_LABEL_PART_MAIN, LV_STATE_DISABLED, Colors::lightGray); - lv_obj_align(time, msecTime, LV_ALIGN_OUT_TOP_MID, 0, 0); + lv_obj_align(time, nullptr, LV_ALIGN_CENTER, 0, -20); + + // Calculate position for msecTime + lv_coord_t fontHeight = lv_font_get_line_height(&jetbrains_mono_76); + // Position above the colon (which is after 2 digits) + int16_t horizontalOffset = lv_obj_get_width(time) / 4; // Approximate position of colon + int16_t verticalOffset = -fontHeight; // Position fully above the time + + msecTime = lv_label_create(lv_scr_act(), nullptr); + lv_label_set_text_static(msecTime, "00"); + lv_obj_set_style_local_text_color(msecTime, LV_LABEL_PART_MAIN, LV_STATE_DISABLED, Colors::lightGray); + // Align relative to time, but offset to colon position + lv_obj_align(msecTime, time, LV_ALIGN_CENTER, horizontalOffset, verticalOffset); SetInterfaceStopped(); From 1824307dde29fce1606d32f07a2514ed12a96aa8 Mon Sep 17 00:00:00 2001 From: Koen Raijer Date: Sun, 16 Feb 2025 14:45:13 +0100 Subject: [PATCH 07/13] re-aligned time/msectime --- src/displayapp/screens/StopWatch.cpp | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/src/displayapp/screens/StopWatch.cpp b/src/displayapp/screens/StopWatch.cpp index f555f95e1f..1b3d30cd70 100644 --- a/src/displayapp/screens/StopWatch.cpp +++ b/src/displayapp/screens/StopWatch.cpp @@ -65,19 +65,12 @@ StopWatch::StopWatch(System::SystemTask& systemTask) : wakeLock(systemTask) { lv_obj_set_style_local_text_font(time, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_76); lv_label_set_text_static(time, "00:00"); lv_obj_set_style_local_text_color(time, LV_LABEL_PART_MAIN, LV_STATE_DISABLED, Colors::lightGray); - lv_obj_align(time, nullptr, LV_ALIGN_CENTER, 0, -20); - - // Calculate position for msecTime - lv_coord_t fontHeight = lv_font_get_line_height(&jetbrains_mono_76); - // Position above the colon (which is after 2 digits) - int16_t horizontalOffset = lv_obj_get_width(time) / 4; // Approximate position of colon - int16_t verticalOffset = -fontHeight; // Position fully above the time + lv_obj_align(time, lapText, LV_ALIGN_OUT_TOP_MID, 0, 0); msecTime = lv_label_create(lv_scr_act(), nullptr); lv_label_set_text_static(msecTime, "00"); lv_obj_set_style_local_text_color(msecTime, LV_LABEL_PART_MAIN, LV_STATE_DISABLED, Colors::lightGray); - // Align relative to time, but offset to colon position - lv_obj_align(msecTime, time, LV_ALIGN_CENTER, horizontalOffset, verticalOffset); + lv_obj_align(msecTime, time, LV_ALIGN_TOP_MID, 0, 0); SetInterfaceStopped(); From c4443d1df0e3e94906a62ded7eb3cd955c941e3b Mon Sep 17 00:00:00 2001 From: Koen Raijer Date: Sun, 16 Feb 2025 14:49:52 +0100 Subject: [PATCH 08/13] renamed alignment --- src/displayapp/screens/StopWatch.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/displayapp/screens/StopWatch.cpp b/src/displayapp/screens/StopWatch.cpp index 1b3d30cd70..f310fe5c1f 100644 --- a/src/displayapp/screens/StopWatch.cpp +++ b/src/displayapp/screens/StopWatch.cpp @@ -70,7 +70,7 @@ StopWatch::StopWatch(System::SystemTask& systemTask) : wakeLock(systemTask) { msecTime = lv_label_create(lv_scr_act(), nullptr); lv_label_set_text_static(msecTime, "00"); lv_obj_set_style_local_text_color(msecTime, LV_LABEL_PART_MAIN, LV_STATE_DISABLED, Colors::lightGray); - lv_obj_align(msecTime, time, LV_ALIGN_TOP_MID, 0, 0); + lv_obj_align(msecTime, time, LV_ALIGN_IN_TOP_MID, 0, 0); SetInterfaceStopped(); From 22571812f82c0204b779f58f79e676c7b432a5cf Mon Sep 17 00:00:00 2001 From: Koen Raijer Date: Sun, 16 Feb 2025 15:05:50 +0100 Subject: [PATCH 09/13] lap and time positioning improvement --- src/displayapp/screens/StopWatch.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/displayapp/screens/StopWatch.cpp b/src/displayapp/screens/StopWatch.cpp index f310fe5c1f..ada65ba4f6 100644 --- a/src/displayapp/screens/StopWatch.cpp +++ b/src/displayapp/screens/StopWatch.cpp @@ -37,6 +37,7 @@ namespace { StopWatch::StopWatch(System::SystemTask& systemTask) : wakeLock(systemTask) { static constexpr uint8_t btnWidth = 115; static constexpr uint8_t btnHeight = 80; + static constexpr uint8_t lapLineHeight = 25; btnPlayPause = lv_btn_create(lv_scr_act(), nullptr); btnPlayPause->user_data = this; lv_obj_set_event_cb(btnPlayPause, play_pause_event_handler); @@ -59,18 +60,18 @@ StopWatch::StopWatch(System::SystemTask& systemTask) : wakeLock(systemTask) { lv_label_set_long_mode(lapText, LV_LABEL_LONG_BREAK); lv_label_set_align(lapText, LV_LABEL_ALIGN_CENTER); lv_obj_set_width(lapText, LV_HOR_RES_MAX); - lv_obj_align(lapText, lv_scr_act(), LV_ALIGN_IN_BOTTOM_MID, 0, -btnHeight); + lv_obj_align(lapText, lv_scr_act(), LV_ALIGN_IN_BOTTOM_MID, 0, -(btnHeight + lapLineHeight)); time = lv_label_create(lv_scr_act(), nullptr); lv_obj_set_style_local_text_font(time, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_76); lv_label_set_text_static(time, "00:00"); lv_obj_set_style_local_text_color(time, LV_LABEL_PART_MAIN, LV_STATE_DISABLED, Colors::lightGray); - lv_obj_align(time, lapText, LV_ALIGN_OUT_TOP_MID, 0, 0); + lv_obj_align(time, lv_scr_act(), LV_ALIGN_IN_TOP_MID, 0, 0); msecTime = lv_label_create(lv_scr_act(), nullptr); lv_label_set_text_static(msecTime, "00"); lv_obj_set_style_local_text_color(msecTime, LV_LABEL_PART_MAIN, LV_STATE_DISABLED, Colors::lightGray); - lv_obj_align(msecTime, time, LV_ALIGN_IN_TOP_MID, 0, 0); + lv_obj_align(msecTime, time, LV_ALIGN_IN_TOP_MID, 0, -1); SetInterfaceStopped(); From 4b37131ca62cbf4f2607848e2824c743d1a6a5c3 Mon Sep 17 00:00:00 2001 From: Koen Raijer Date: Sun, 16 Feb 2025 15:18:52 +0100 Subject: [PATCH 10/13] tiny alignment --- src/displayapp/screens/StopWatch.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/displayapp/screens/StopWatch.cpp b/src/displayapp/screens/StopWatch.cpp index ada65ba4f6..ef1ddf5c42 100644 --- a/src/displayapp/screens/StopWatch.cpp +++ b/src/displayapp/screens/StopWatch.cpp @@ -37,7 +37,7 @@ namespace { StopWatch::StopWatch(System::SystemTask& systemTask) : wakeLock(systemTask) { static constexpr uint8_t btnWidth = 115; static constexpr uint8_t btnHeight = 80; - static constexpr uint8_t lapLineHeight = 25; + static constexpr uint8_t lapLineHeight = 27; btnPlayPause = lv_btn_create(lv_scr_act(), nullptr); btnPlayPause->user_data = this; lv_obj_set_event_cb(btnPlayPause, play_pause_event_handler); @@ -66,7 +66,7 @@ StopWatch::StopWatch(System::SystemTask& systemTask) : wakeLock(systemTask) { lv_obj_set_style_local_text_font(time, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_76); lv_label_set_text_static(time, "00:00"); lv_obj_set_style_local_text_color(time, LV_LABEL_PART_MAIN, LV_STATE_DISABLED, Colors::lightGray); - lv_obj_align(time, lv_scr_act(), LV_ALIGN_IN_TOP_MID, 0, 0); + lv_obj_align(time, lv_scr_act(), LV_ALIGN_IN_TOP_MID, 0, 2); msecTime = lv_label_create(lv_scr_act(), nullptr); lv_label_set_text_static(msecTime, "00"); From 0e5b76d1801a781be91cdaf2281daa957fafe25f Mon Sep 17 00:00:00 2001 From: Koen Raijer Date: Sun, 16 Feb 2025 15:19:39 +0100 Subject: [PATCH 11/13] alignment --- src/displayapp/screens/StopWatch.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/displayapp/screens/StopWatch.cpp b/src/displayapp/screens/StopWatch.cpp index ef1ddf5c42..6ed71b67d1 100644 --- a/src/displayapp/screens/StopWatch.cpp +++ b/src/displayapp/screens/StopWatch.cpp @@ -37,7 +37,7 @@ namespace { StopWatch::StopWatch(System::SystemTask& systemTask) : wakeLock(systemTask) { static constexpr uint8_t btnWidth = 115; static constexpr uint8_t btnHeight = 80; - static constexpr uint8_t lapLineHeight = 27; + static constexpr uint8_t lapLineHeight = 30; btnPlayPause = lv_btn_create(lv_scr_act(), nullptr); btnPlayPause->user_data = this; lv_obj_set_event_cb(btnPlayPause, play_pause_event_handler); @@ -66,12 +66,12 @@ StopWatch::StopWatch(System::SystemTask& systemTask) : wakeLock(systemTask) { lv_obj_set_style_local_text_font(time, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_76); lv_label_set_text_static(time, "00:00"); lv_obj_set_style_local_text_color(time, LV_LABEL_PART_MAIN, LV_STATE_DISABLED, Colors::lightGray); - lv_obj_align(time, lv_scr_act(), LV_ALIGN_IN_TOP_MID, 0, 2); + lv_obj_align(time, lv_scr_act(), LV_ALIGN_IN_TOP_MID, 0, 5); msecTime = lv_label_create(lv_scr_act(), nullptr); lv_label_set_text_static(msecTime, "00"); lv_obj_set_style_local_text_color(msecTime, LV_LABEL_PART_MAIN, LV_STATE_DISABLED, Colors::lightGray); - lv_obj_align(msecTime, time, LV_ALIGN_IN_TOP_MID, 0, -1); + lv_obj_align(msecTime, time, LV_ALIGN_IN_TOP_MID, 0, -3); SetInterfaceStopped(); From e0b17a8ac37841bcfd3289632148b6cdd7700484 Mon Sep 17 00:00:00 2001 From: Koen Raijer Date: Sun, 16 Feb 2025 15:33:52 +0100 Subject: [PATCH 12/13] small repositioning --- src/displayapp/screens/StopWatch.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/displayapp/screens/StopWatch.cpp b/src/displayapp/screens/StopWatch.cpp index 6ed71b67d1..1bced0c140 100644 --- a/src/displayapp/screens/StopWatch.cpp +++ b/src/displayapp/screens/StopWatch.cpp @@ -66,7 +66,7 @@ StopWatch::StopWatch(System::SystemTask& systemTask) : wakeLock(systemTask) { lv_obj_set_style_local_text_font(time, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_76); lv_label_set_text_static(time, "00:00"); lv_obj_set_style_local_text_color(time, LV_LABEL_PART_MAIN, LV_STATE_DISABLED, Colors::lightGray); - lv_obj_align(time, lv_scr_act(), LV_ALIGN_IN_TOP_MID, 0, 5); + lv_obj_align(time, lv_scr_act(), LV_ALIGN_IN_TOP_MID, 0, 10); msecTime = lv_label_create(lv_scr_act(), nullptr); lv_label_set_text_static(msecTime, "00"); From 172ab5187529a582f8cde57dbbbe0b3285c876b5 Mon Sep 17 00:00:00 2001 From: Koen <75178793+koenraijer@users.noreply.github.com> Date: Sun, 16 Feb 2025 15:53:36 +0100 Subject: [PATCH 13/13] Delete .github/workflows/build.yml --- .github/workflows/build.yml | 171 ------------------------------------ 1 file changed, 171 deletions(-) delete mode 100644 .github/workflows/build.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml deleted file mode 100644 index df7a4bab7e..0000000000 --- a/.github/workflows/build.yml +++ /dev/null @@ -1,171 +0,0 @@ -# GitHub Actions Workflow to build FreeRTOS Firmware for PineTime Smart Watch -# See https://lupyuen.github.io/pinetime-rust-mynewt/articles/cloud -# Based on https://github.com/JF002/Pinetime/blob/master/doc/buildAndProgram.md -# and https://github.com/JF002/Pinetime/blob/master/bootloader/README.md - -# Name of this Workflow -name: Build PineTime Firmware - -# When to run this Workflow... -on: - - # Run this Workflow when files are updated (Pushed) in the "master" Branch - push: - branches: [ master ] - - # Also run this Workflow when a Pull Request is created or updated in the "master" Branch - pull_request: - branches: [ master ] - -# Steps to run for the Workflow -jobs: - build: - - # Run these steps on Ubuntu - runs-on: ubuntu-latest - - steps: - - ######################################################################################### - # Download and Cache Dependencies - - - name: Install cmake - uses: lukka/get-cmake@v3.18.0 - - - name: Check cache for Embedded Arm Toolchain arm-none-eabi-gcc - id: cache-toolchain - uses: actions/cache@v2 - env: - cache-name: cache-toolchain-9-2020-q2 - with: - path: ${{ runner.temp }}/arm-none-eabi - key: ${{ runner.os }}-build-${{ env.cache-name }} - restore-keys: ${{ runner.os }}-build-${{ env.cache-name }} - - - name: Install Embedded Arm Toolchain arm-none-eabi-gcc - if: steps.cache-toolchain.outputs.cache-hit != 'true' # Install toolchain if not found in cache - uses: fiam/arm-none-eabi-gcc@v1.0.2 - with: - # GNU Embedded Toolchain for Arm release name, in the V-YYYY-qZ format (e.g. "9-2019-q4") - release: 9-2020-q2 - # Directory to unpack GCC to. Defaults to a temporary directory. - directory: ${{ runner.temp }}/arm-none-eabi - - - name: Check cache for nRF5 SDK - id: cache-nrf5sdk - uses: actions/cache@v2 - env: - cache-name: cache-nrf5sdk - with: - path: ${{ runner.temp }}/nrf5_sdk - key: ${{ runner.os }}-build-${{ env.cache-name }} - restore-keys: ${{ runner.os }}-build-${{ env.cache-name }} - - - name: Install nRF5 SDK - if: steps.cache-nrf5sdk.outputs.cache-hit != 'true' # Install SDK if not found in cache - run: | - cd ${{ runner.temp }} - curl https://developer.nordicsemi.com/nRF5_SDK/nRF5_SDK_v15.x.x/nRF5_SDK_15.3.0_59ac345.zip -o nrf5_sdk.zip - unzip nrf5_sdk.zip - mv nRF5_SDK_15.3.0_59ac345 nrf5_sdk - - - name: Check cache for MCUBoot - id: cache-mcuboot - uses: actions/cache@v2 - env: - cache-name: cache-mcuboot - with: - path: ${{ runner.temp }}/mcuboot - key: ${{ runner.os }}-build-${{ env.cache-name }} - restore-keys: ${{ runner.os }}-build-${{ env.cache-name }} - - - name: Install MCUBoot - if: steps.cache-mcuboot.outputs.cache-hit != 'true' # Install MCUBoot if not found in cache - run: | - cd ${{ runner.temp }} - git clone --branch v1.5.0 https://github.com/JuulLabs-OSS/mcuboot - - - name: Install imgtool dependencies - run: pip3 install --user -r ${{ runner.temp }}/mcuboot/scripts/requirements.txt - - - name: Install adafruit-nrfutil - run: | - pip3 install --user wheel - pip3 install --user setuptools - pip3 install --user adafruit-nrfutil - - ######################################################################################### - # Checkout - - - name: Checkout source files - uses: actions/checkout@v2 - - - name: Show files - run: set ; pwd ; ls -l - - ######################################################################################### - # CMake - - - name: CMake - run: | - mkdir -p build - cd build - cmake -DARM_NONE_EABI_TOOLCHAIN_PATH=${{ runner.temp }}/arm-none-eabi -DNRF5_SDK_PATH=${{ runner.temp }}/nrf5_sdk -DUSE_OPENOCD=1 ../ - - ######################################################################################### - # Make and Upload DFU Package - # pinetime-mcuboot-app.img must be flashed at address 0x8000 in the internal flash memory with OpenOCD: - # program image.bin 0x8000 - - # For Debugging Builds: Remove "make" option "-j" for clearer output. Add "--trace" to see details. - # For Faster Builds: Add "make" option "-j" - - - name: Make pinetime-mcuboot-app - run: | - cd build - make pinetime-mcuboot-app - - - name: Create firmware image - run: | - # The generated firmware binary looks like "pinetime-mcuboot-app-0.8.2.bin" - ls -l build/src/pinetime-mcuboot-app*.bin - ${{ runner.temp }}/mcuboot/scripts/imgtool.py create --align 4 --version 1.0.0 --header-size 32 --slot-size 475136 --pad-header build/src/pinetime-mcuboot-app*.bin build/src/pinetime-mcuboot-app-img.bin - ${{ runner.temp }}/mcuboot/scripts/imgtool.py verify build/src/pinetime-mcuboot-app-img.bin - - - name: Create DFU package - run: | - ~/.local/bin/adafruit-nrfutil dfu genpkg --dev-type 0x0052 --application build/src/pinetime-mcuboot-app-img.bin build/src/pinetime-mcuboot-app-dfu.zip - unzip -v build/src/pinetime-mcuboot-app-dfu.zip - # Unzip the package because Upload Artifact will zip up the files - unzip build/src/pinetime-mcuboot-app-dfu.zip -d build/src/pinetime-mcuboot-app-dfu - - - name: Upload DFU package - uses: actions/upload-artifact@v2 - with: - name: pinetime-mcuboot-app-dfu.zip - path: build/src/pinetime-mcuboot-app-dfu/* - - ######################################################################################### - # Make and Upload Standalone Firmware - - - name: Make pinetime-app - run: | - cd build - make pinetime-app - - - name: Upload standalone firmware - uses: actions/upload-artifact@v2 - with: - name: pinetime-app.out - path: build/src/pinetime-app*.out - - ######################################################################################### - # Finish - - - name: Find output - run: | - find . -name "pinetime-app.*" -ls - find . -name "pinetime-mcuboot-app.*" -ls - -# Embedded Arm Toolchain and nRF5 SDK will only be cached if the build succeeds. -# So make sure that the first build always succeeds, e.g. comment out the "Make" step.