Compare commits

...

5 Commits

Author SHA1 Message Date
David Fischer
8086d85573
Merge a3dca29b43 into 78d6e5931c 2026-02-03 21:40:17 +00:00
Jake Kenneally
78d6e5931c
fix: Correct debugging_monitor.py script instructions (#676)
Some checks are pending
CI / build (push) Waiting to run
## Summary

**What is the goal of this PR?**
- Minor correction to the `debugging_monitor.py` script instructions

**What changes are included?**
- `pyserial` should be installed, NOT `serial`, which is a [different
lib](https://pypi.org/project/serial/)
- Added macOS serial port

## Additional Context

- Just a minor docs update. I can confirm the debugging script is
working great on macOS

---

### AI Usage

While CrossPoint doesn't have restrictions on AI tools in contributing,
please be transparent about their usage as it
helps set the right context for reviewers.

Did you use AI tools to help write this code? _**< NO >**_
2026-02-04 00:33:20 +03:00
Luke Stein
dac11c3fdd
fix: Correct instruction text to match actual button text (#672)
## Summary

* Instruction text says "Press OK to scan again" but button label is
actually "Connect" (not OK)
* Corrects instruction text

---

### AI Usage

Did you use AI tools to help write this code? **No**
2026-02-04 00:32:52 +03:00
Dave ID
a3dca29b43 fix potential prev_val == 0 init issue 2026-02-03 16:05:30 +01:00
Dave ID
ee806390f3 add ringbuffer for battery percentage smoothing 2026-02-03 15:48:49 +01:00
6 changed files with 112 additions and 7 deletions

View File

@ -102,13 +102,18 @@ After flashing the new features, its recommended to capture detailed logs fro
First, make sure all required Python packages are installed:
```python
python3 -m pip install serial colorama matplotlib
python3 -m pip install pyserial colorama matplotlib
```
after that run the script:
```sh
# For Linux
# This was tested on Debian and should work on most Linux systems.
python3 scripts/debugging_monitor.py
# For macOS
python3 scripts/debugging_monitor.py /dev/cu.usbmodem2101
```
This was tested on Debian and should work on most Linux systems. Minor adjustments may be required for Windows or macOS.
Minor adjustments may be required for Windows.
## Internals

40
src/Battery.cpp Normal file
View File

@ -0,0 +1,40 @@
#include "Battery.h"
void BatteryPercentageRingBuffer::init(uint16_t v) {
for (size_t i = 0; i < MAX_SAMPLES; i++) {
buf[i] = v;
}
sum = v * MAX_SAMPLES;
prev_val = v;
head = 0;
}
void BatteryPercentageRingBuffer::update(uint16_t v) {
// Previous percentage is set > 100 only if buffer was constructed but not initialized yet
if (prev_val > 100) {
init(v);
}
// Recalculate rolling sum
sum -= buf[head];
buf[head] = v;
sum += v;
// Shift head
head++;
if (head >= MAX_SAMPLES) head = 0;
}
uint16_t BatteryPercentageRingBuffer::evaluate() {
// We 'round' (only works for pos numbers but oh well good enough for battery percentages) to an int
float avg = (sum / MAX_SAMPLES) + 0.5;
uint16_t new_val = (int)avg;
// Battery percentage should not increase when not charging so we just cap it to be lower than the last value
if (new_val < prev_val) {
prev_val = new_val;
return new_val;
} else {
return prev_val;
}
}

View File

@ -1,6 +1,21 @@
#pragma once
#include <BatteryMonitor.h>
#include <cstddef>
#define BAT_GPIO0 0 // Battery voltage
static BatteryMonitor battery(BAT_GPIO0);
struct BatteryPercentageRingBuffer {
static constexpr uint16_t MAX_SAMPLES = 10;
uint16_t buf[MAX_SAMPLES];
uint16_t head = 0;
uint16_t sum = 0;
uint16_t prev_val = 161;
void init(uint16_t value);
void update(uint16_t value);
uint16_t evaluate();
};

View File

@ -1,5 +1,6 @@
#include "ScreenComponents.h"
#include <Arduino.h>
#include <GfxRenderer.h>
#include <cstdint>
@ -8,10 +9,24 @@
#include "Battery.h"
#include "fontIds.h"
BatteryPercentageRingBuffer ScreenComponents::batteryBuffer;
void ScreenComponents::drawBattery(const GfxRenderer& renderer, const int left, const int top,
const bool showPercentage) {
const bool charging = (digitalRead(20) == HIGH);
// Left aligned battery icon and percentage
const uint16_t percentage = battery.readPercentage();
uint16_t percentage = battery.readPercentage();
if (charging) {
// If charging reinitialize buffer with current percentage and display this value
batteryBuffer.init(percentage);
} else {
// Else update buffer with new percentage and return smoothed validated percentage to display
batteryBuffer.update(percentage);
percentage = batteryBuffer.evaluate();
}
const auto percentageText = showPercentage ? std::to_string(percentage) + "%" : "";
renderer.drawText(SMALL_FONT_ID, left + 20, top, percentageText.c_str());
@ -34,12 +49,38 @@ void ScreenComponents::drawBattery(const GfxRenderer& renderer, const int left,
renderer.drawLine(x + batteryWidth - 0, y + 4, x + batteryWidth - 0, y + batteryHeight - 5);
// The +1 is to round up, so that we always fill at least one pixel
int filledWidth = percentage * (batteryWidth - 5) / 100 + 1;
if (filledWidth > batteryWidth - 5) {
filledWidth = batteryWidth - 5; // Ensure we don't overflow
constexpr int maxFillWidth = batteryWidth - 5;
int filledWidth = percentage * maxFillWidth / 100 + 1;
if (filledWidth > maxFillWidth) {
filledWidth = maxFillWidth;
}
// When charging, ensure minimum fill so lightning bolt is fully visible
constexpr int minFillForBolt = 8; // Bolt extends 6px wide, needs padding
if (charging && filledWidth < minFillForBolt) {
filledWidth = minFillForBolt;
}
renderer.fillRect(x + 2, y + 2, filledWidth, batteryHeight - 4);
// Draw lightning bolt when charging (white/inverted on black fill for visibility)
if (charging) {
// Lightning bolt: 6px wide, 8px tall, centered in battery
const int boltX = x + 4;
const int boltY = y + 2;
// Draw bolt in white (state=false) for visibility on black fill
// Upper diagonal pointing right
renderer.drawLine(boltX + 4, boltY + 0, boltX + 5, boltY + 0, false);
renderer.drawLine(boltX + 3, boltY + 1, boltX + 4, boltY + 1, false);
renderer.drawLine(boltX + 2, boltY + 2, boltX + 5, boltY + 2, false); // Wide middle
renderer.drawLine(boltX + 3, boltY + 3, boltX + 4, boltY + 3, false);
// Lower diagonal pointing left
renderer.drawLine(boltX + 2, boltY + 4, boltX + 3, boltY + 4, false);
renderer.drawLine(boltX + 1, boltY + 5, boltX + 4, boltY + 5, false); // Wide middle
renderer.drawLine(boltX + 2, boltY + 6, boltX + 3, boltY + 6, false);
renderer.drawLine(boltX + 1, boltY + 7, boltX + 2, boltY + 7, false);
}
}
ScreenComponents::PopupLayout ScreenComponents::drawPopup(const GfxRenderer& renderer, const char* message) {

View File

@ -4,6 +4,8 @@
#include <cstdint>
#include <vector>
#include "Battery.h"
class GfxRenderer;
struct TabInfo {
@ -15,6 +17,8 @@ class ScreenComponents {
public:
static const int BOOK_PROGRESS_BAR_HEIGHT = 4;
static BatteryPercentageRingBuffer batteryBuffer;
struct PopupLayout {
int x;
int y;

View File

@ -520,7 +520,7 @@ void WifiSelectionActivity::renderNetworkList() const {
const auto height = renderer.getLineHeight(UI_10_FONT_ID);
const auto top = (pageHeight - height) / 2;
renderer.drawCenteredText(UI_10_FONT_ID, top, "No networks found");
renderer.drawCenteredText(SMALL_FONT_ID, top + height + 10, "Press OK to scan again");
renderer.drawCenteredText(SMALL_FONT_ID, top + height + 10, "Press Connect to scan again");
} else {
// Calculate how many networks we can display
constexpr int startY = 60;