Compare commits

...

9 Commits

Author SHA1 Message Date
Jonathan Bennett
e0a720d667 Merge branch 'develop' into kill-led-builtin 2025-12-21 23:23:45 -06:00
Jorropo
5a3855b208 in shame.py do not complain about missing targets (#9032)
PR CI only runs a small subset of all tests.

It is very likely a file we didn't found in the PR is just not tested in PR.
2025-12-21 08:11:18 -05:00
WillyJL
8fdba1f1e2 RTC: PCF85063 support, port to SensorLib 0.3.1 (#8061)
* RTC: PCF85063 support, port to SensorLib 0.3.1

* Tidy up defines

* Remove RTC/PCF8563 mentions from unrelated variants

* Bump SensorLib 0.3.2

* Use SensorRtcHelper

* Consistent warning message

* Fix oversight

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Manuel <71137295+mverch67@users.noreply.github.com>
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-12-20 19:10:21 -06:00
Jorropo
db64a5b51e implement basic github action comment reporting target diffs (#9022)
This is missing logic:
- report average
- don't bother reporting if the results are negligeable
- praise the user if it's improving the situation
- shame the user if it's not improving the situation
2025-12-20 19:29:01 -05:00
zeropt
3371d3372c Adding support for InkHUD joystick navigation for the Seeed Wio Tracker L1 E-ink (#8678)
* TwoButtonExtened mirrors TwoButton but added joystick functionality

* basic ui navigation with a joystick

settings->joystick.enabled setting added and SETTINGS_VERSION
incremented by one in InkHUD/Persistence.h

in seeed_wio_tracker_L1_eink/nicheGraphics.h enable joystick and
disable "Next Tile" menu item in

implement prevTile and prevApplet functions in
InkHUD/WindowManager.h,cpp and InkHUD/InkHUD.h,cpp

onStickCenterShort, onStickCenterLong, onStickUp, onStickDown,
onStickLeft, and onStickRight functions added to:
- InkHUD/InkHUD.h,cpp
- InkHUD/Events.h,cpp
- InkHUD/Applet.h

change navigation actions in InkHUD/Events.cpp events based on
whether the joystick is enabled or not

in seeed_wio_tracker_L1_eink/nicheGraphics.h connect joystick events to
the new joystick handler functions

* handle joystick input in NotificationApplet and TipsApplet

Both the joystick center short press and the user button short press can
be used to advance through the Tips applet.

dismiss notifications with any joystick input

* MenuApplet controls
allows menu navigation including a back button

* add AlignStickApplet for aligning the joystick with the screen

add joystick.aligned and joystick.alignment to InkHUD/Persistence.h for
storing alignment status and relative angle

create AlignStick applet that prompts the user for a joystick input and
rotates the controls to align with the screen

AlignStick applet is run after the tips applet if the joystick is
enabled and not aligned

add menu item for opening the AlignStick applet

* update tips applet with joystick controls

* format InkHUD additions

* fix stroke consistency when resizing joystick graphic

* tweak button tips for order consistency

* increase joystick debounce

* fix comments

* remove unnecessary '+'

* remap joystick controls to match standard inkHUD behavior

Input with a joystick now behaves as follows

User Button (joystick center):
- short press in applet -> opens menu
- long press in applet -> opens menu
- short press in menu -> selects
- long press in menu -> selects

Exit Button:
- short press in applet -> switches tile
- long press in applet -> nothing for now
- short press in menu -> closes menu
- long press in menu -> nothing for now

---------

Co-authored-by: scobert <scobert57@gmail.com>
Co-authored-by: HarukiToreda <116696711+HarukiToreda@users.noreply.github.com>
2025-12-20 15:15:42 -05:00
Jonathan Bennett
a14505cafa Merge branch 'develop' into kill-led-builtin 2025-12-09 23:20:19 -06:00
Jonathan Bennett
2ae409ff8b Merge branch 'develop' into kill-led-builtin 2025-12-08 17:16:10 -06:00
Jonathan Bennett
e500ae6415 LUD_BUILTIN workarounds 2025-12-08 17:14:43 -06:00
Jonathan Bennett
8fb0365833 Just set LED_BUILTIN universally to -1, as we don't use it. 2025-12-08 17:14:43 -06:00
130 changed files with 1737 additions and 305 deletions

View File

@@ -21,7 +21,7 @@ jobs:
# Use 'arctastic' self-hosted runner pool when building in the main repo # Use 'arctastic' self-hosted runner pool when building in the main repo
runs-on: ${{ github.repository_owner == 'meshtastic' && 'arctastic' || 'ubuntu-latest' }} runs-on: ${{ github.repository_owner == 'meshtastic' && 'arctastic' || 'ubuntu-latest' }}
outputs: outputs:
artifact-id: ${{ steps.upload.outputs.artifact-id }} artifact-id: ${{ steps.upload-firmware.outputs.artifact-id }}
steps: steps:
- uses: actions/checkout@v6 - uses: actions/checkout@v6
with: with:
@@ -71,7 +71,7 @@ jobs:
- name: Store binaries as an artifact - name: Store binaries as an artifact
uses: actions/upload-artifact@v6 uses: actions/upload-artifact@v6
id: upload id: upload-firmware
with: with:
name: firmware-${{ inputs.platform }}-${{ inputs.pio_env }}-${{ inputs.version }} name: firmware-${{ inputs.platform }}-${{ inputs.pio_env }}-${{ inputs.version }}
overwrite: true overwrite: true
@@ -84,3 +84,12 @@ jobs:
release/*.zip release/*.zip
release/device-*.sh release/device-*.sh
release/device-*.bat release/device-*.bat
- name: Store manifests as an artifact
uses: actions/upload-artifact@v6
id: upload-manifest
with:
name: manifest-${{ inputs.platform }}-${{ inputs.pio_env }}-${{ inputs.version }}
overwrite: true
path: |
release/*.mt.json

View File

@@ -233,6 +233,40 @@ jobs:
description: "Download firmware-${{matrix.arch}}-${{ needs.version.outputs.long }}.zip. This artifact will be available for 90 days from creation" description: "Download firmware-${{matrix.arch}}-${{ needs.version.outputs.long }}.zip. This artifact will be available for 90 days from creation"
github-token: ${{ secrets.GITHUB_TOKEN }} github-token: ${{ secrets.GITHUB_TOKEN }}
shame:
if: github.repository == 'meshtastic/firmware'
continue-on-error: true
runs-on: ubuntu-latest
needs: [build]
steps:
- uses: actions/checkout@v6
with:
filter: blob:none # means we download all the git history but none of the commit (except ones with checkout like the head)
fetch-depth: 0
- name: Download the current manifests
uses: actions/download-artifact@v7
with:
path: ./manifests-new/
pattern: manifest-*
merge-multiple: true
- name: Upload combined manifests for later commit and global stats crunching.
uses: actions/upload-artifact@v6
id: upload-manifest
with:
name: manifests-all
overwrite: true
path: |
manifests-new/*.mt.json
- name: Find the merge base
run: echo "MERGE_BASE=$(git merge-base "origin/$base" "$head")" >> $GITHUB_ENV
env:
base: ${{ github.base_ref }}
head: ${{ github.head_ref }}
- name: Download the old manifests
run: gh run download -R ${{ github.repository }} --commit ${{ env.MERGE_BASE }} --name manifests-all --dir manifest-old/
- name: Do scan and post comment
run: python3 bin/shame.py ${{ github.event.pull_request.number }} manifests-old/ manifests-new/
release-artifacts: release-artifacts:
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: ${{ github.event_name == 'workflow_dispatch' && github.repository == 'meshtastic/firmware' }} if: ${{ github.event_name == 'workflow_dispatch' && github.repository == 'meshtastic/firmware' }}

95
bin/shame.py Normal file
View File

@@ -0,0 +1,95 @@
import sys
import os
import json
from github import Github
def parseFile(path):
with open(path, "r") as f:
data = json.loads(f)
for file in data["files"]:
if file["name"].endswith(".bin"):
return file["name"], file["bytes"]
if len(sys.argv) != 4:
print(f"expected usage: {sys.argv[0]} <PR number> <path to old-manifests> <path to new-manifests>")
sys.exit(1)
pr_number = int(sys.argv[1])
token = os.getenv("GITHUB_TOKEN")
if not token:
raise EnvironmentError("GITHUB_TOKEN not found in environment.")
repo_name = os.getenv("GITHUB_REPOSITORY") # "owner/repo"
if not repo_name:
raise EnvironmentError("GITHUB_REPOSITORY not found in environment.")
oldFiles = sys.argv[2]
old = set(os.path.join(oldFiles, f) for f in os.listdir(oldFiles) if os.path.isfile(f))
newFiles = sys.argv[3]
new = set(os.path.join(newFiles, f) for f in os.listdir(newFiles) if os.path.isfile(f))
startMarkdown = "# Target Size Changes\n\n"
markdown = ""
newlyIntroduced = new - old
if len(newlyIntroduced) > 0:
markdown += "## Newly Introduced Targets\n\n"
# create a table
markdown += "| File | Size |\n"
markdown += "| ---- | ---- |\n"
for f in newlyIntroduced:
name, size = parseFile(f)
markdown += f"| `{name}` | {size}b |\n"
# do not log removed targets
# PRs only run a small subset of builds, so removed targets are not meaningful
# since they are very likely to just be not ran in PR CI
both = old & new
degradations = []
improvements = []
for f in both:
oldName, oldSize = parseFile(f)
_, newSize = parseFile(f)
if oldSize != newSize:
if newSize < oldSize:
improvements.append((oldName, oldSize, newSize))
else:
degradations.append((oldName, oldSize, newSize))
if len(degradations) > 0:
markdown += "\n## Degradation\n\n"
# create a table
markdown += "| File | Difference | Old Size | New Size |\n"
markdown += "| ---- | ---------- | -------- | -------- |\n"
for oldName, oldSize, newSize in degradations:
markdown += f"| `{oldName}` | **{oldSize - newSize}b** | {oldSize}b | {newSize}b |\n"
if len(improvements) > 0:
markdown += "\n## Improvement\n\n"
# create a table
markdown += "| File | Difference | Old Size | New Size |\n"
markdown += "| ---- | ---------- | -------- | -------- |\n"
for oldName, oldSize, newSize in improvements:
markdown += f"| `{oldName}` | **{oldSize - newSize}b** | {oldSize}b | {newSize}b |\n"
if len(markdown) == 0:
markdown = "No changes in target sizes detected."
g = Github(token)
repo = g.get_repo(repo_name)
pr = repo.get_pull(pr_number)
existing_comment = None
for comment in pr.get_issue_comments():
if comment.body.startswith(startMarkdown):
existing_comment = comment
break
final_markdown = startMarkdown + markdown
if existing_comment:
existing_comment.edit(body=final_markdown)
else:
pr.create_issue_comment(body=final_markdown)

View File

@@ -55,6 +55,7 @@ build_flags = -Wno-missing-field-initializers
-DMESHTASTIC_EXCLUDE_POWERSTRESS=1 ; exclude power stress test module from main firmware -DMESHTASTIC_EXCLUDE_POWERSTRESS=1 ; exclude power stress test module from main firmware
-DMESHTASTIC_EXCLUDE_GENERIC_THREAD_MODULE=1 -DMESHTASTIC_EXCLUDE_GENERIC_THREAD_MODULE=1
-D MAX_THREADS=40 ; As we've split modules, we have more threads to manage -D MAX_THREADS=40 ; As we've split modules, we have more threads to manage
-DLED_BUILTIN=-1
#-DBUILD_EPOCH=$UNIX_TIME ; set in platformio-custom.py now #-DBUILD_EPOCH=$UNIX_TIME ; set in platformio-custom.py now
#-D OLED_PL=1 #-D OLED_PL=1
#-D DEBUG_HEAP=1 ; uncomment to add free heap space / memory leak debugging logs #-D DEBUG_HEAP=1 ; uncomment to add free heap space / memory leak debugging logs

View File

@@ -29,8 +29,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#if __has_include("Melopero_RV3028.h") #if __has_include("Melopero_RV3028.h")
#include "Melopero_RV3028.h" #include "Melopero_RV3028.h"
#endif #endif
#if __has_include("pcf8563.h") #if __has_include("SensorRtcHelper.hpp")
#include "pcf8563.h" #include "SensorRtcHelper.hpp"
#endif #endif
/* Offer chance for variant-specific defines */ /* Offer chance for variant-specific defines */

View File

@@ -25,8 +25,8 @@ ScanI2C::FoundDevice ScanI2C::firstScreen() const
ScanI2C::FoundDevice ScanI2C::firstRTC() const ScanI2C::FoundDevice ScanI2C::firstRTC() const
{ {
ScanI2C::DeviceType types[] = {RTC_RV3028, RTC_PCF8563, RTC_RX8130CE}; ScanI2C::DeviceType types[] = {RTC_RV3028, RTC_PCF8563, RTC_PCF85063, RTC_RX8130CE};
return firstOfOrNONE(3, types); return firstOfOrNONE(4, types);
} }
ScanI2C::FoundDevice ScanI2C::firstKeyboard() const ScanI2C::FoundDevice ScanI2C::firstKeyboard() const

View File

@@ -14,6 +14,7 @@ class ScanI2C
SCREEN_ST7567, SCREEN_ST7567,
RTC_RV3028, RTC_RV3028,
RTC_PCF8563, RTC_PCF8563,
RTC_PCF85063,
RTC_RX8130CE, RTC_RX8130CE,
CARDKB, CARDKB,
TDECKKB, TDECKKB,

View File

@@ -202,6 +202,10 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
SCAN_SIMPLE_CASE(RX8130CE_RTC, RTC_RX8130CE, "RX8130CE", (uint8_t)addr.address) SCAN_SIMPLE_CASE(RX8130CE_RTC, RTC_RX8130CE, "RX8130CE", (uint8_t)addr.address)
#endif #endif
#ifdef PCF85063_RTC
SCAN_SIMPLE_CASE(PCF85063_RTC, RTC_PCF85063, "PCF85063", (uint8_t)addr.address)
#endif
case CARDKB_ADDR: case CARDKB_ADDR:
// Do we have the RAK14006 instead? // Do we have the RAK14006 instead?
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x04), 1); registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x04), 1);

View File

@@ -66,26 +66,26 @@ RTCSetResult readFromRTC()
currentQuality = RTCQualityDevice; currentQuality = RTCQualityDevice;
} }
return RTCSetResultSuccess; return RTCSetResultSuccess;
} else {
LOG_WARN("RTC not found (found address 0x%02X)", rtc_found.address);
} }
#elif defined(PCF8563_RTC) #elif defined(PCF8563_RTC) || defined(PCF85063_RTC)
#if defined(PCF8563_RTC)
if (rtc_found.address == PCF8563_RTC) { if (rtc_found.address == PCF8563_RTC) {
#elif defined(PCF85063_RTC)
if (rtc_found.address == PCF85063_RTC) {
#endif
uint32_t now = millis(); uint32_t now = millis();
PCF8563_Class rtc; SensorRtcHelper rtc;
#if WIRE_INTERFACES_COUNT == 2 #if WIRE_INTERFACES_COUNT == 2
rtc.begin(rtc_found.port == ScanI2C::I2CPort::WIRE1 ? Wire1 : Wire); rtc.begin(rtc_found.port == ScanI2C::I2CPort::WIRE1 ? Wire1 : Wire);
#else #else
rtc.begin(); rtc.begin(Wire);
#endif #endif
auto tc = rtc.getDateTime(); RTC_DateTime datetime = rtc.getDateTime();
tm t; tm t = datetime.toUnixTime();
t.tm_year = tc.year - 1900;
t.tm_mon = tc.month - 1;
t.tm_mday = tc.day;
t.tm_hour = tc.hour;
t.tm_min = tc.minute;
t.tm_sec = tc.second;
tv.tv_sec = gm_mktime(&t); tv.tv_sec = gm_mktime(&t);
tv.tv_usec = 0; tv.tv_usec = 0;
uint32_t printableEpoch = tv.tv_sec; // Print lib only supports 32 bit but time_t can be 64 bit on some platforms uint32_t printableEpoch = tv.tv_sec; // Print lib only supports 32 bit but time_t can be 64 bit on some platforms
@@ -100,14 +100,16 @@ RTCSetResult readFromRTC()
} }
#endif #endif
LOG_DEBUG("Read RTC time from PCF8563 getDateTime as %02d-%02d-%02d %02d:%02d:%02d (%ld)", t.tm_year + 1900, t.tm_mon + 1, LOG_DEBUG("Read RTC time from %s getDateTime as %02d-%02d-%02d %02d:%02d:%02d (%ld)", rtc.getChipName(), t.tm_year + 1900,
t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec, printableEpoch); t.tm_mon + 1, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec, printableEpoch);
if (currentQuality == RTCQualityNone) { if (currentQuality == RTCQualityNone) {
timeStartMsec = now; timeStartMsec = now;
zeroOffsetSecs = tv.tv_sec; zeroOffsetSecs = tv.tv_sec;
currentQuality = RTCQualityDevice; currentQuality = RTCQualityDevice;
} }
return RTCSetResultSuccess; return RTCSetResultSuccess;
} else {
LOG_WARN("RTC not found (found address 0x%02X)", rtc_found.address);
} }
#elif defined(RX8130CE_RTC) #elif defined(RX8130CE_RTC)
if (rtc_found.address == RX8130CE_RTC) { if (rtc_found.address == RX8130CE_RTC) {
@@ -232,20 +234,28 @@ RTCSetResult perhapsSetRTC(RTCQuality q, const struct timeval *tv, bool forceUpd
rtc.setTime(t->tm_year + 1900, t->tm_mon + 1, t->tm_wday, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec); rtc.setTime(t->tm_year + 1900, t->tm_mon + 1, t->tm_wday, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);
LOG_DEBUG("RV3028_RTC setTime %02d-%02d-%02d %02d:%02d:%02d (%ld)", t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, LOG_DEBUG("RV3028_RTC setTime %02d-%02d-%02d %02d:%02d:%02d (%ld)", t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
t->tm_hour, t->tm_min, t->tm_sec, printableEpoch); t->tm_hour, t->tm_min, t->tm_sec, printableEpoch);
} else {
LOG_WARN("RTC not found (found address 0x%02X)", rtc_found.address);
} }
#elif defined(PCF8563_RTC) #elif defined(PCF8563_RTC) || defined(PCF85063_RTC)
#if defined(PCF8563_RTC)
if (rtc_found.address == PCF8563_RTC) { if (rtc_found.address == PCF8563_RTC) {
PCF8563_Class rtc; #elif defined(PCF85063_RTC)
if (rtc_found.address == PCF85063_RTC) {
#endif
SensorRtcHelper rtc;
#if WIRE_INTERFACES_COUNT == 2 #if WIRE_INTERFACES_COUNT == 2
rtc.begin(rtc_found.port == ScanI2C::I2CPort::WIRE1 ? Wire1 : Wire); rtc.begin(rtc_found.port == ScanI2C::I2CPort::WIRE1 ? Wire1 : Wire);
#else #else
rtc.begin(); rtc.begin(Wire);
#endif #endif
tm *t = gmtime(&tv->tv_sec); tm *t = gmtime(&tv->tv_sec);
rtc.setDateTime(t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec); rtc.setDateTime(*t);
LOG_DEBUG("PCF8563_RTC setDateTime %02d-%02d-%02d %02d:%02d:%02d (%ld)", t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, LOG_DEBUG("%s setDateTime %02d-%02d-%02d %02d:%02d:%02d (%ld)", rtc.getChipName(), t->tm_year + 1900, t->tm_mon + 1,
t->tm_hour, t->tm_min, t->tm_sec, printableEpoch); t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec, printableEpoch);
} else {
LOG_WARN("RTC not found (found address 0x%02X)", rtc_found.address);
} }
#elif defined(RX8130CE_RTC) #elif defined(RX8130CE_RTC)
if (rtc_found.address == RX8130CE_RTC) { if (rtc_found.address == RX8130CE_RTC) {

View File

@@ -88,8 +88,14 @@ class Applet : public GFX
virtual void onForeground() {} virtual void onForeground() {}
virtual void onBackground() {} virtual void onBackground() {}
virtual void onShutdown() {} virtual void onShutdown() {}
virtual void onButtonShortPress() {} // (System Applets only) virtual void onButtonShortPress() {}
virtual void onButtonLongPress() {} // (System Applets only) virtual void onButtonLongPress() {}
virtual void onExitShort() {}
virtual void onExitLong() {}
virtual void onNavUp() {}
virtual void onNavDown() {}
virtual void onNavLeft() {}
virtual void onNavRight() {}
virtual bool approveNotification(Notification &n); // Allow an applet to veto a notification virtual bool approveNotification(Notification &n); // Allow an applet to veto a notification

View File

@@ -0,0 +1,205 @@
#ifdef MESHTASTIC_INCLUDE_INKHUD
#include "./AlignStickApplet.h"
using namespace NicheGraphics;
InkHUD::AlignStickApplet::AlignStickApplet()
{
if (!settings->joystick.aligned)
bringToForeground();
}
void InkHUD::AlignStickApplet::onRender()
{
setFont(fontMedium);
printAt(0, 0, "Align Joystick:");
setFont(fontSmall);
std::string instructions = "Move joystick in the direction indicated";
printWrapped(0, fontMedium.lineHeight() * 1.5, width(), instructions);
// Size of the region in which the joystick graphic should fit
uint16_t joyXLimit = X(0.8);
uint16_t contentH = fontMedium.lineHeight() * 1.5 + fontSmall.lineHeight() * 1;
if (getTextWidth(instructions) > width())
contentH += fontSmall.lineHeight();
uint16_t freeY = height() - contentH - fontSmall.lineHeight() * 1.2;
uint16_t joyYLimit = freeY * 0.8;
// Use the shorter of the two
uint16_t joyWidth = joyXLimit < joyYLimit ? joyXLimit : joyYLimit;
// Center the joystick graphic
uint16_t centerX = X(0.5);
uint16_t centerY = contentH + freeY * 0.5;
// Draw joystick graphic
drawStick(centerX, centerY, joyWidth);
setFont(fontSmall);
printAt(X(0.5), Y(1.0) - fontSmall.lineHeight() * 0.2, "Long press to skip", CENTER, BOTTOM);
}
// Draw a scalable joystick graphic
void InkHUD::AlignStickApplet::drawStick(uint16_t centerX, uint16_t centerY, uint16_t width)
{
if (width < 9) // too small to draw
return;
else if (width < 40) { // only draw up arrow
uint16_t chamfer = width < 20 ? 1 : 2;
// Draw filled up arrow
drawDirection(centerX, centerY - width / 4, Direction::UP, width, chamfer, BLACK);
} else { // large enough to draw the full thing
uint16_t chamfer = width < 80 ? 1 : 2;
uint16_t stroke = 3; // pixels
uint16_t arrowW = width * 0.22;
uint16_t hollowW = arrowW - stroke * 2;
// Draw center circle
fillCircle((int16_t)centerX, (int16_t)centerY, (int16_t)(width * 0.2), BLACK);
fillCircle((int16_t)centerX, (int16_t)centerY, (int16_t)(width * 0.2) - stroke, WHITE);
// Draw filled up arrow
drawDirection(centerX, centerY - width / 2, Direction::UP, arrowW, chamfer, BLACK);
// Draw down arrow
drawDirection(centerX, centerY + width / 2, Direction::DOWN, arrowW, chamfer, BLACK);
drawDirection(centerX, centerY + width / 2 - stroke, Direction::DOWN, hollowW, 0, WHITE);
// Draw left arrow
drawDirection(centerX - width / 2, centerY, Direction::LEFT, arrowW, chamfer, BLACK);
drawDirection(centerX - width / 2 + stroke, centerY, Direction::LEFT, hollowW, 0, WHITE);
// Draw right arrow
drawDirection(centerX + width / 2, centerY, Direction::RIGHT, arrowW, chamfer, BLACK);
drawDirection(centerX + width / 2 - stroke, centerY, Direction::RIGHT, hollowW, 0, WHITE);
}
}
// Draw a scalable joystick direction arrow
// a right-triangle with blunted tips
/*
_ <--point
^ / \
| / \
size / \
| / \
v |_________|
*/
void InkHUD::AlignStickApplet::drawDirection(uint16_t pointX, uint16_t pointY, Direction direction, uint16_t size,
uint16_t chamfer, Color color)
{
uint16_t chamferW = chamfer * 2 + 1;
uint16_t triangleW = size - chamferW;
// Draw arrow
switch (direction) {
case Direction::UP:
fillRect(pointX - chamfer, pointY, chamferW, triangleW, color);
fillRect(pointX - chamfer - triangleW, pointY + triangleW, chamferW + triangleW * 2, chamferW, color);
fillTriangle(pointX - chamfer, pointY, pointX - chamfer - triangleW, pointY + triangleW, pointX - chamfer,
pointY + triangleW, color);
fillTriangle(pointX + chamfer, pointY, pointX + chamfer + triangleW, pointY + triangleW, pointX + chamfer,
pointY + triangleW, color);
break;
case Direction::DOWN:
fillRect(pointX - chamfer, pointY - triangleW + 1, chamferW, triangleW, color);
fillRect(pointX - chamfer - triangleW, pointY - size + 1, chamferW + triangleW * 2, chamferW, color);
fillTriangle(pointX - chamfer, pointY, pointX - chamfer - triangleW, pointY - triangleW, pointX - chamfer,
pointY - triangleW, color);
fillTriangle(pointX + chamfer, pointY, pointX + chamfer + triangleW, pointY - triangleW, pointX + chamfer,
pointY - triangleW, color);
break;
case Direction::LEFT:
fillRect(pointX, pointY - chamfer, triangleW, chamferW, color);
fillRect(pointX + triangleW, pointY - chamfer - triangleW, chamferW, chamferW + triangleW * 2, color);
fillTriangle(pointX, pointY - chamfer, pointX + triangleW, pointY - chamfer - triangleW, pointX + triangleW,
pointY - chamfer, color);
fillTriangle(pointX, pointY + chamfer, pointX + triangleW, pointY + chamfer + triangleW, pointX + triangleW,
pointY + chamfer, color);
break;
case Direction::RIGHT:
fillRect(pointX - triangleW + 1, pointY - chamfer, triangleW, chamferW, color);
fillRect(pointX - size + 1, pointY - chamfer - triangleW, chamferW, chamferW + triangleW * 2, color);
fillTriangle(pointX, pointY - chamfer, pointX - triangleW, pointY - chamfer - triangleW, pointX - triangleW,
pointY - chamfer, color);
fillTriangle(pointX, pointY + chamfer, pointX - triangleW, pointY + chamfer + triangleW, pointX - triangleW,
pointY + chamfer, color);
break;
}
}
void InkHUD::AlignStickApplet::onForeground()
{
// Prevent most other applets from requesting update, and skip their rendering entirely
// Another system applet with a higher precedence can potentially ignore this
SystemApplet::lockRendering = true;
SystemApplet::lockRequests = true;
handleInput = true; // Intercept the button input for our applet
}
void InkHUD::AlignStickApplet::onBackground()
{
// Allow normal update behavior to resume
SystemApplet::lockRendering = false;
SystemApplet::lockRequests = false;
SystemApplet::handleInput = false;
// Need to force an update, as a polite request wouldn't be honored, seeing how we are now in the background
// Usually, onBackground is followed by another applet's onForeground (which requests update), but not in this case
inkhud->forceUpdate(EInk::UpdateTypes::FULL);
}
void InkHUD::AlignStickApplet::onButtonLongPress()
{
sendToBackground();
inkhud->forceUpdate(EInk::UpdateTypes::FULL);
}
void InkHUD::AlignStickApplet::onExitLong()
{
sendToBackground();
inkhud->forceUpdate(EInk::UpdateTypes::FULL);
}
void InkHUD::AlignStickApplet::onNavUp()
{
settings->joystick.aligned = true;
sendToBackground();
inkhud->forceUpdate(EInk::UpdateTypes::FULL);
}
void InkHUD::AlignStickApplet::onNavDown()
{
inkhud->rotateJoystick(2); // 180 deg
settings->joystick.aligned = true;
sendToBackground();
inkhud->forceUpdate(EInk::UpdateTypes::FULL);
}
void InkHUD::AlignStickApplet::onNavLeft()
{
inkhud->rotateJoystick(3); // 270 deg
settings->joystick.aligned = true;
sendToBackground();
inkhud->forceUpdate(EInk::UpdateTypes::FULL);
}
void InkHUD::AlignStickApplet::onNavRight()
{
inkhud->rotateJoystick(1); // 90 deg
settings->joystick.aligned = true;
sendToBackground();
inkhud->forceUpdate(EInk::UpdateTypes::FULL);
}
#endif

View File

@@ -0,0 +1,50 @@
#ifdef MESHTASTIC_INCLUDE_INKHUD
/*
System Applet for manually aligning the joystick with the screen
should be run at startup if the joystick is enabled
and not aligned to the screen
*/
#pragma once
#include "configuration.h"
#include "graphics/niche/InkHUD/SystemApplet.h"
namespace NicheGraphics::InkHUD
{
class AlignStickApplet : public SystemApplet
{
public:
AlignStickApplet();
void onRender() override;
void onForeground() override;
void onBackground() override;
void onButtonLongPress() override;
void onExitLong() override;
void onNavUp() override;
void onNavDown() override;
void onNavLeft() override;
void onNavRight() override;
protected:
enum Direction {
UP,
DOWN,
LEFT,
RIGHT,
};
void drawStick(uint16_t centerX, uint16_t centerY, uint16_t width);
void drawDirection(uint16_t pointX, uint16_t pointY, Direction direction, uint16_t size, uint16_t chamfer, Color color);
};
} // namespace NicheGraphics::InkHUD
#endif

View File

@@ -30,6 +30,7 @@ enum MenuAction {
TOGGLE_AUTOSHOW_APPLET, TOGGLE_AUTOSHOW_APPLET,
SET_RECENTS, SET_RECENTS,
ROTATE, ROTATE,
ALIGN_JOYSTICK,
LAYOUT, LAYOUT,
TOGGLE_BATTERY_ICON, TOGGLE_BATTERY_ICON,
TOGGLE_NOTIFICATIONS, TOGGLE_NOTIFICATIONS,

View File

@@ -178,6 +178,10 @@ void InkHUD::MenuApplet::execute(MenuItem item)
inkhud->rotate(); inkhud->rotate();
break; break;
case ALIGN_JOYSTICK:
inkhud->openAlignStick();
break;
case LAYOUT: case LAYOUT:
// Todo: smarter incrementing of tile count // Todo: smarter incrementing of tile count
settings->userTiles.count++; settings->userTiles.count++;
@@ -287,14 +291,17 @@ void InkHUD::MenuApplet::showPage(MenuPage page)
// items.push_back(MenuItem("Display Off", MenuPage::EXIT)); // TODO // items.push_back(MenuItem("Display Off", MenuPage::EXIT)); // TODO
items.push_back(MenuItem("Save & Shut Down", MenuAction::SHUTDOWN)); items.push_back(MenuItem("Save & Shut Down", MenuAction::SHUTDOWN));
items.push_back(MenuItem("Exit", MenuPage::EXIT)); items.push_back(MenuItem("Exit", MenuPage::EXIT));
previousPage = MenuPage::EXIT;
break; break;
case SEND: case SEND:
populateSendPage(); populateSendPage();
previousPage = MenuPage::ROOT;
break; break;
case CANNEDMESSAGE_RECIPIENT: case CANNEDMESSAGE_RECIPIENT:
populateRecipientPage(); populateRecipientPage();
previousPage = MenuPage::OPTIONS;
break; break;
case OPTIONS: case OPTIONS:
@@ -321,6 +328,8 @@ void InkHUD::MenuApplet::showPage(MenuPage page)
if (settings->userTiles.maxCount > 1) if (settings->userTiles.maxCount > 1)
items.push_back(MenuItem("Layout", MenuAction::LAYOUT, MenuPage::OPTIONS)); items.push_back(MenuItem("Layout", MenuAction::LAYOUT, MenuPage::OPTIONS));
items.push_back(MenuItem("Rotate", MenuAction::ROTATE, MenuPage::OPTIONS)); items.push_back(MenuItem("Rotate", MenuAction::ROTATE, MenuPage::OPTIONS));
if (settings->joystick.enabled)
items.push_back(MenuItem("Align Joystick", MenuAction::ALIGN_JOYSTICK, MenuPage::EXIT));
items.push_back(MenuItem("Notifications", MenuAction::TOGGLE_NOTIFICATIONS, MenuPage::OPTIONS, items.push_back(MenuItem("Notifications", MenuAction::TOGGLE_NOTIFICATIONS, MenuPage::OPTIONS,
&settings->optionalFeatures.notifications)); &settings->optionalFeatures.notifications));
items.push_back(MenuItem("Battery Icon", MenuAction::TOGGLE_BATTERY_ICON, MenuPage::OPTIONS, items.push_back(MenuItem("Battery Icon", MenuAction::TOGGLE_BATTERY_ICON, MenuPage::OPTIONS,
@@ -332,20 +341,24 @@ void InkHUD::MenuApplet::showPage(MenuPage page)
items.push_back( items.push_back(
MenuItem("12-Hour Clock", MenuAction::TOGGLE_12H_CLOCK, MenuPage::OPTIONS, &config.display.use_12h_clock)); MenuItem("12-Hour Clock", MenuAction::TOGGLE_12H_CLOCK, MenuPage::OPTIONS, &config.display.use_12h_clock));
items.push_back(MenuItem("Exit", MenuPage::EXIT)); items.push_back(MenuItem("Exit", MenuPage::EXIT));
previousPage = MenuPage::ROOT;
break; break;
case APPLETS: case APPLETS:
populateAppletPage(); populateAppletPage();
items.push_back(MenuItem("Exit", MenuPage::EXIT)); items.push_back(MenuItem("Exit", MenuPage::EXIT));
previousPage = MenuPage::OPTIONS;
break; break;
case AUTOSHOW: case AUTOSHOW:
populateAutoshowPage(); populateAutoshowPage();
items.push_back(MenuItem("Exit", MenuPage::EXIT)); items.push_back(MenuItem("Exit", MenuPage::EXIT));
previousPage = MenuPage::OPTIONS;
break; break;
case RECENTS: case RECENTS:
populateRecentsPage(); populateRecentsPage();
previousPage = MenuPage::OPTIONS;
break; break;
case EXIT: case EXIT:
@@ -479,12 +492,21 @@ void InkHUD::MenuApplet::onButtonShortPress()
// Push the auto-close timer back // Push the auto-close timer back
OSThread::setIntervalFromNow(MENU_TIMEOUT_SEC * 1000UL); OSThread::setIntervalFromNow(MENU_TIMEOUT_SEC * 1000UL);
// Move menu cursor to next entry, then update if (!settings->joystick.enabled) {
if (cursorShown) // Move menu cursor to next entry, then update
cursor = (cursor + 1) % items.size(); if (cursorShown)
else cursor = (cursor + 1) % items.size();
cursorShown = true; else
requestUpdate(Drivers::EInk::UpdateTypes::FAST); cursorShown = true;
requestUpdate(Drivers::EInk::UpdateTypes::FAST);
} else {
if (cursorShown)
execute(items.at(cursor));
else
showPage(MenuPage::EXIT);
if (!wantsToRender())
requestUpdate(Drivers::EInk::UpdateTypes::FAST);
}
} }
void InkHUD::MenuApplet::onButtonLongPress() void InkHUD::MenuApplet::onButtonLongPress()
@@ -504,6 +526,62 @@ void InkHUD::MenuApplet::onButtonLongPress()
requestUpdate(Drivers::EInk::UpdateTypes::FAST); requestUpdate(Drivers::EInk::UpdateTypes::FAST);
} }
void InkHUD::MenuApplet::onExitShort()
{
// Exit the menu
showPage(MenuPage::EXIT);
requestUpdate(Drivers::EInk::UpdateTypes::FAST);
}
void InkHUD::MenuApplet::onNavUp()
{
OSThread::setIntervalFromNow(MENU_TIMEOUT_SEC * 1000UL);
// Move menu cursor to previous entry, then update
if (cursor == 0)
cursor = items.size() - 1;
else
cursor--;
if (!cursorShown)
cursorShown = true;
requestUpdate(Drivers::EInk::UpdateTypes::FAST);
}
void InkHUD::MenuApplet::onNavDown()
{
OSThread::setIntervalFromNow(MENU_TIMEOUT_SEC * 1000UL);
// Move menu cursor to next entry, then update
if (cursorShown)
cursor = (cursor + 1) % items.size();
else
cursorShown = true;
requestUpdate(Drivers::EInk::UpdateTypes::FAST);
}
void InkHUD::MenuApplet::onNavLeft()
{
OSThread::setIntervalFromNow(MENU_TIMEOUT_SEC * 1000UL);
// Go to the previous menu page
showPage(previousPage);
requestUpdate(Drivers::EInk::UpdateTypes::FAST);
}
void InkHUD::MenuApplet::onNavRight()
{
OSThread::setIntervalFromNow(MENU_TIMEOUT_SEC * 1000UL);
if (cursorShown)
execute(items.at(cursor));
if (!wantsToRender())
requestUpdate(Drivers::EInk::UpdateTypes::FAST);
}
// Dynamically create MenuItem entries for activating / deactivating Applets, for the "Applet Selection" submenu // Dynamically create MenuItem entries for activating / deactivating Applets, for the "Applet Selection" submenu
void InkHUD::MenuApplet::populateAppletPage() void InkHUD::MenuApplet::populateAppletPage()
{ {
@@ -796,4 +874,4 @@ void InkHUD::MenuApplet::freeCannedMessageResources()
cm.recipientItems.clear(); cm.recipientItems.clear();
} }
#endif #endif

View File

@@ -27,6 +27,11 @@ class MenuApplet : public SystemApplet, public concurrency::OSThread
void onBackground() override; void onBackground() override;
void onButtonShortPress() override; void onButtonShortPress() override;
void onButtonLongPress() override; void onButtonLongPress() override;
void onExitShort() override;
void onNavUp() override;
void onNavDown() override;
void onNavLeft() override;
void onNavRight() override;
void onRender() override; void onRender() override;
void show(Tile *t); // Open the menu, onto a user tile void show(Tile *t); // Open the menu, onto a user tile
@@ -52,6 +57,7 @@ class MenuApplet : public SystemApplet, public concurrency::OSThread
void freeCannedMessageResources(); // Clear MenuApplet's canned message processing data void freeCannedMessageResources(); // Clear MenuApplet's canned message processing data
MenuPage currentPage = MenuPage::ROOT; MenuPage currentPage = MenuPage::ROOT;
MenuPage previousPage = MenuPage::EXIT;
uint8_t cursor = 0; // Which menu item is currently highlighted uint8_t cursor = 0; // Which menu item is currently highlighted
bool cursorShown = false; // Is *any* item highlighted? (Root menu: no initial selection) bool cursorShown = false; // Is *any* item highlighted? (Root menu: no initial selection)
@@ -97,4 +103,4 @@ class MenuApplet : public SystemApplet, public concurrency::OSThread
} // namespace NicheGraphics::InkHUD } // namespace NicheGraphics::InkHUD
#endif #endif

View File

@@ -153,6 +153,42 @@ void InkHUD::NotificationApplet::onButtonLongPress()
inkhud->forceUpdate(EInk::UpdateTypes::FULL); inkhud->forceUpdate(EInk::UpdateTypes::FULL);
} }
void InkHUD::NotificationApplet::onExitShort()
{
dismiss();
inkhud->forceUpdate(EInk::UpdateTypes::FULL);
}
void InkHUD::NotificationApplet::onExitLong()
{
dismiss();
inkhud->forceUpdate(EInk::UpdateTypes::FULL);
}
void InkHUD::NotificationApplet::onNavUp()
{
dismiss();
inkhud->forceUpdate(EInk::UpdateTypes::FULL);
}
void InkHUD::NotificationApplet::onNavDown()
{
dismiss();
inkhud->forceUpdate(EInk::UpdateTypes::FULL);
}
void InkHUD::NotificationApplet::onNavLeft()
{
dismiss();
inkhud->forceUpdate(EInk::UpdateTypes::FULL);
}
void InkHUD::NotificationApplet::onNavRight()
{
dismiss();
inkhud->forceUpdate(EInk::UpdateTypes::FULL);
}
// Ask the WindowManager to check whether any displayed applets are already displaying the info from this notification // Ask the WindowManager to check whether any displayed applets are already displaying the info from this notification
// Called internally when we first get a "notifiable event", and then again before render, // Called internally when we first get a "notifiable event", and then again before render,
// in case autoshow swapped which applet was displayed // in case autoshow swapped which applet was displayed

View File

@@ -31,6 +31,12 @@ class NotificationApplet : public SystemApplet
void onBackground() override; void onBackground() override;
void onButtonShortPress() override; void onButtonShortPress() override;
void onButtonLongPress() override; void onButtonLongPress() override;
void onExitShort() override;
void onExitLong() override;
void onNavUp() override;
void onNavDown() override;
void onNavLeft() override;
void onNavRight() override;
int onReceiveTextMessage(const meshtastic_MeshPacket *p); int onReceiveTextMessage(const meshtastic_MeshPacket *p);

View File

@@ -112,12 +112,21 @@ void InkHUD::TipsApplet::onRender()
setFont(fontSmall); setFont(fontSmall);
int16_t cursorY = fontMedium.lineHeight() * 1.5; int16_t cursorY = fontMedium.lineHeight() * 1.5;
printAt(0, cursorY, "User Button"); if (!settings->joystick.enabled) {
cursorY += fontSmall.lineHeight() * 1.2; printAt(0, cursorY, "User Button");
printAt(0, cursorY, "- short press: next"); cursorY += fontSmall.lineHeight() * 1.2;
cursorY += fontSmall.lineHeight() * 1.2; printAt(0, cursorY, "- short press: next");
printAt(0, cursorY, "- long press: select / open menu"); cursorY += fontSmall.lineHeight() * 1.2;
cursorY += fontSmall.lineHeight() * 1.5; printAt(0, cursorY, "- long press: select / open menu");
} else {
printAt(0, cursorY, "Joystick");
cursorY += fontSmall.lineHeight() * 1.2;
printAt(0, cursorY, "- open menu / select");
cursorY += fontSmall.lineHeight() * 1.5;
printAt(0, cursorY, "Exit Button");
cursorY += fontSmall.lineHeight() * 1.2;
printAt(0, cursorY, "- switch tile / close menu");
}
printAt(0, Y(1.0), "Press button to continue", LEFT, BOTTOM); printAt(0, Y(1.0), "Press button to continue", LEFT, BOTTOM);
} break; } break;
@@ -127,8 +136,13 @@ void InkHUD::TipsApplet::onRender()
printAt(0, 0, "Tip: Rotation"); printAt(0, 0, "Tip: Rotation");
setFont(fontSmall); setFont(fontSmall);
printWrapped(0, fontMedium.lineHeight() * 1.5, width(), if (!settings->joystick.enabled) {
"To rotate the display, use the InkHUD menu. Long-press the user button > Options > Rotate."); printWrapped(0, fontMedium.lineHeight() * 1.5, width(),
"To rotate the display, use the InkHUD menu. Long-press the user button > Options > Rotate.");
} else {
printWrapped(0, fontMedium.lineHeight() * 1.5, width(),
"To rotate the display, use the InkHUD menu. Press the user button > Options > Rotate.");
}
printAt(0, Y(1.0), "Press button to continue", LEFT, BOTTOM); printAt(0, Y(1.0), "Press button to continue", LEFT, BOTTOM);
@@ -232,4 +246,10 @@ void InkHUD::TipsApplet::onButtonShortPress()
requestUpdate(); requestUpdate();
} }
// Functions the same as the user button in this instance
void InkHUD::TipsApplet::onExitShort()
{
onButtonShortPress();
}
#endif #endif

View File

@@ -36,6 +36,7 @@ class TipsApplet : public SystemApplet
void onForeground() override; void onForeground() override;
void onBackground() override; void onBackground() override;
void onButtonShortPress() override; void onButtonShortPress() override;
void onExitShort() override;
protected: protected:
void renderWelcome(); // Very first screen of tutorial void renderWelcome(); // Very first screen of tutorial

View File

@@ -55,10 +55,15 @@ void InkHUD::Events::onButtonShort()
} }
// If no system applet is handling input, default behavior instead is to cycle applets // If no system applet is handling input, default behavior instead is to cycle applets
if (consumer) // or open menu if joystick is enabled
if (consumer) {
consumer->onButtonShortPress(); consumer->onButtonShortPress();
else if (!dismissedExt) // Don't change applet if this button press silenced the external notification module } else if (!dismissedExt) { // Don't change applet if this button press silenced the external notification module
inkhud->nextApplet(); if (!settings->joystick.enabled)
inkhud->nextApplet();
else
inkhud->openMenu();
}
} }
void InkHUD::Events::onButtonLong() void InkHUD::Events::onButtonLong()
@@ -83,6 +88,156 @@ void InkHUD::Events::onButtonLong()
inkhud->openMenu(); inkhud->openMenu();
} }
void InkHUD::Events::onExitShort()
{
if (settings->joystick.enabled) {
// Audio feedback (via buzzer)
// Short tone
playChirp();
// Cancel any beeping, buzzing, blinking
// Some button handling suppressed if we are dismissing an external notification (see below)
bool dismissedExt = dismissExternalNotification();
// Check which system applet wants to handle the button press (if any)
SystemApplet *consumer = nullptr;
for (SystemApplet *sa : inkhud->systemApplets) {
if (sa->handleInput) {
consumer = sa;
break;
}
}
// If no system applet is handling input, default behavior instead is change tiles
if (consumer)
consumer->onExitShort();
else if (!dismissedExt) // Don't change tile if this button press silenced the external notification module
inkhud->nextTile();
}
}
void InkHUD::Events::onExitLong()
{
if (settings->joystick.enabled) {
// Audio feedback (via buzzer)
// Slightly longer than playChirp
playBoop();
// Check which system applet wants to handle the button press (if any)
SystemApplet *consumer = nullptr;
for (SystemApplet *sa : inkhud->systemApplets) {
if (sa->handleInput) {
consumer = sa;
break;
}
}
if (consumer)
consumer->onExitLong();
}
}
void InkHUD::Events::onNavUp()
{
if (settings->joystick.enabled) {
// Audio feedback (via buzzer)
// Short tone
playChirp();
// Cancel any beeping, buzzing, blinking
// Some button handling suppressed if we are dismissing an external notification (see below)
bool dismissedExt = dismissExternalNotification();
// Check which system applet wants to handle the button press (if any)
SystemApplet *consumer = nullptr;
for (SystemApplet *sa : inkhud->systemApplets) {
if (sa->handleInput) {
consumer = sa;
break;
}
}
if (consumer)
consumer->onNavUp();
}
}
void InkHUD::Events::onNavDown()
{
if (settings->joystick.enabled) {
// Audio feedback (via buzzer)
// Short tone
playChirp();
// Cancel any beeping, buzzing, blinking
// Some button handling suppressed if we are dismissing an external notification (see below)
bool dismissedExt = dismissExternalNotification();
// Check which system applet wants to handle the button press (if any)
SystemApplet *consumer = nullptr;
for (SystemApplet *sa : inkhud->systemApplets) {
if (sa->handleInput) {
consumer = sa;
break;
}
}
if (consumer)
consumer->onNavDown();
}
}
void InkHUD::Events::onNavLeft()
{
if (settings->joystick.enabled) {
// Audio feedback (via buzzer)
// Short tone
playChirp();
// Cancel any beeping, buzzing, blinking
// Some button handling suppressed if we are dismissing an external notification (see below)
bool dismissedExt = dismissExternalNotification();
// Check which system applet wants to handle the button press (if any)
SystemApplet *consumer = nullptr;
for (SystemApplet *sa : inkhud->systemApplets) {
if (sa->handleInput) {
consumer = sa;
break;
}
}
// If no system applet is handling input, default behavior instead is to cycle applets
if (consumer)
consumer->onNavLeft();
else if (!dismissedExt) // Don't change applet if this button press silenced the external notification module
inkhud->prevApplet();
}
}
void InkHUD::Events::onNavRight()
{
if (settings->joystick.enabled) {
// Audio feedback (via buzzer)
// Short tone
playChirp();
// Cancel any beeping, buzzing, blinking
// Some button handling suppressed if we are dismissing an external notification (see below)
bool dismissedExt = dismissExternalNotification();
// Check which system applet wants to handle the button press (if any)
SystemApplet *consumer = nullptr;
for (SystemApplet *sa : inkhud->systemApplets) {
if (sa->handleInput) {
consumer = sa;
break;
}
}
// If no system applet is handling input, default behavior instead is to cycle applets
if (consumer)
consumer->onNavRight();
else if (!dismissedExt) // Don't change applet if this button press silenced the external notification module
inkhud->nextApplet();
}
}
// Callback for deepSleepObserver // Callback for deepSleepObserver
// Returns 0 to signal that we agree to sleep now // Returns 0 to signal that we agree to sleep now
int InkHUD::Events::beforeDeepSleep(void *unused) int InkHUD::Events::beforeDeepSleep(void *unused)

View File

@@ -29,6 +29,12 @@ class Events
void onButtonShort(); // User button: short press void onButtonShort(); // User button: short press
void onButtonLong(); // User button: long press void onButtonLong(); // User button: long press
void onExitShort(); // Exit button: short press
void onExitLong(); // Exit button: long press
void onNavUp(); // Navigate up
void onNavDown(); // Navigate down
void onNavLeft(); // Navigate left
void onNavRight(); // Navigate right
int beforeDeepSleep(void *unused); // Prepare for shutdown int beforeDeepSleep(void *unused); // Prepare for shutdown
int beforeReboot(void *unused); // Prepare for reboot int beforeReboot(void *unused); // Prepare for reboot

View File

@@ -80,6 +80,94 @@ void InkHUD::InkHUD::longpress()
events->onButtonLong(); events->onButtonLong();
} }
// Call this when your exit button gets a short press
void InkHUD::InkHUD::exitShort()
{
events->onExitShort();
}
// Call this when your exit button gets a long press
void InkHUD::InkHUD::exitLong()
{
events->onExitLong();
}
// Call this when your joystick gets an up input
void InkHUD::InkHUD::navUp()
{
switch ((persistence->settings.rotation + persistence->settings.joystick.alignment) % 4) {
case 1: // 90 deg
events->onNavLeft();
break;
case 2: // 180 deg
events->onNavDown();
break;
case 3: // 270 deg
events->onNavRight();
break;
default: // 0 deg
events->onNavUp();
break;
}
}
// Call this when your joystick gets a down input
void InkHUD::InkHUD::navDown()
{
switch ((persistence->settings.rotation + persistence->settings.joystick.alignment) % 4) {
case 1: // 90 deg
events->onNavRight();
break;
case 2: // 180 deg
events->onNavUp();
break;
case 3: // 270 deg
events->onNavLeft();
break;
default: // 0 deg
events->onNavDown();
break;
}
}
// Call this when your joystick gets a left input
void InkHUD::InkHUD::navLeft()
{
switch ((persistence->settings.rotation + persistence->settings.joystick.alignment) % 4) {
case 1: // 90 deg
events->onNavDown();
break;
case 2: // 180 deg
events->onNavRight();
break;
case 3: // 270 deg
events->onNavUp();
break;
default: // 0 deg
events->onNavLeft();
break;
}
}
// Call this when your joystick gets a right input
void InkHUD::InkHUD::navRight()
{
switch ((persistence->settings.rotation + persistence->settings.joystick.alignment) % 4) {
case 1: // 90 deg
events->onNavUp();
break;
case 2: // 180 deg
events->onNavLeft();
break;
case 3: // 270 deg
events->onNavDown();
break;
default: // 0 deg
events->onNavRight();
break;
}
}
// Cycle the next user applet to the foreground // Cycle the next user applet to the foreground
// Only activated applets are cycled // Only activated applets are cycled
// If user has a multi-applet layout, the applets will cycle on the "focused tile" // If user has a multi-applet layout, the applets will cycle on the "focused tile"
@@ -88,6 +176,14 @@ void InkHUD::InkHUD::nextApplet()
windowManager->nextApplet(); windowManager->nextApplet();
} }
// Cycle the previous user applet to the foreground
// Only activated applets are cycled
// If user has a multi-applet layout, the applets will cycle on the "focused tile"
void InkHUD::InkHUD::prevApplet()
{
windowManager->prevApplet();
}
// Show the menu (on the the focused tile) // Show the menu (on the the focused tile)
// The applet previously displayed there will be restored once the menu closes // The applet previously displayed there will be restored once the menu closes
void InkHUD::InkHUD::openMenu() void InkHUD::InkHUD::openMenu()
@@ -95,6 +191,12 @@ void InkHUD::InkHUD::openMenu()
windowManager->openMenu(); windowManager->openMenu();
} }
// Bring AlignStick applet to the foreground
void InkHUD::InkHUD::openAlignStick()
{
windowManager->openAlignStick();
}
// In layouts where multiple applets are shown at once, change which tile is focused // In layouts where multiple applets are shown at once, change which tile is focused
// The focused tile in the one which cycles applets on button short press, and displays menu on long press // The focused tile in the one which cycles applets on button short press, and displays menu on long press
void InkHUD::InkHUD::nextTile() void InkHUD::InkHUD::nextTile()
@@ -102,12 +204,26 @@ void InkHUD::InkHUD::nextTile()
windowManager->nextTile(); windowManager->nextTile();
} }
// In layouts where multiple applets are shown at once, change which tile is focused
// The focused tile in the one which cycles applets on button short press, and displays menu on long press
void InkHUD::InkHUD::prevTile()
{
windowManager->prevTile();
}
// Rotate the display image by 90 degrees // Rotate the display image by 90 degrees
void InkHUD::InkHUD::rotate() void InkHUD::InkHUD::rotate()
{ {
windowManager->rotate(); windowManager->rotate();
} }
// rotate the joystick in 90 degree increments
void InkHUD::InkHUD::rotateJoystick(uint8_t angle)
{
persistence->settings.joystick.alignment += angle;
persistence->settings.joystick.alignment %= 4;
}
// Show / hide the battery indicator in top-right // Show / hide the battery indicator in top-right
void InkHUD::InkHUD::toggleBatteryIcon() void InkHUD::InkHUD::toggleBatteryIcon()
{ {

View File

@@ -55,15 +55,25 @@ class InkHUD
void shortpress(); void shortpress();
void longpress(); void longpress();
void exitShort();
void exitLong();
void navUp();
void navDown();
void navLeft();
void navRight();
// Trigger UI changes // Trigger UI changes
// - called by various InkHUD components // - called by various InkHUD components
// - suitable(?) for use by aux button, connected in variant nicheGraphics.h // - suitable(?) for use by aux button, connected in variant nicheGraphics.h
void nextApplet(); void nextApplet();
void prevApplet();
void openMenu(); void openMenu();
void openAlignStick();
void nextTile(); void nextTile();
void prevTile();
void rotate(); void rotate();
void rotateJoystick(uint8_t angle = 1); // rotate 90 deg by default
void toggleBatteryIcon(); void toggleBatteryIcon();
// Updating the display // Updating the display

View File

@@ -29,7 +29,7 @@ class Persistence
// Used to invalidate old settings, if needed // Used to invalidate old settings, if needed
// Version 0 is reserved for testing, and will always load defaults // Version 0 is reserved for testing, and will always load defaults
static constexpr uint32_t SETTINGS_VERSION = 2; static constexpr uint32_t SETTINGS_VERSION = 3;
struct Settings { struct Settings {
struct Meta { struct Meta {
@@ -96,6 +96,19 @@ class Persistence
bool safeShutdownSeen = false; bool safeShutdownSeen = false;
} tips; } tips;
// Joystick settings for enabling and aligning to the screen
struct Joystick {
// Modifies the UI for joystick use
bool enabled = false;
// gets set to true when AlignStick applet is completed
bool aligned = false;
// Rotation of the joystick
// Multiples of 90 degrees clockwise
uint8_t alignment = 0;
} joystick;
// Rotation of the display // Rotation of the display
// Multiples of 90 degrees clockwise // Multiples of 90 degrees clockwise
// Most commonly: rotation is 0 when flex connector is oriented below display // Most commonly: rotation is 0 when flex connector is oriented below display

View File

@@ -2,6 +2,7 @@
#include "./WindowManager.h" #include "./WindowManager.h"
#include "./Applets/System/AlignStick/AlignStickApplet.h"
#include "./Applets/System/BatteryIcon/BatteryIconApplet.h" #include "./Applets/System/BatteryIcon/BatteryIconApplet.h"
#include "./Applets/System/Logo/LogoApplet.h" #include "./Applets/System/Logo/LogoApplet.h"
#include "./Applets/System/Menu/MenuApplet.h" #include "./Applets/System/Menu/MenuApplet.h"
@@ -98,6 +99,38 @@ void InkHUD::WindowManager::nextTile()
userTiles.at(settings->userTiles.focused)->requestHighlight(); userTiles.at(settings->userTiles.focused)->requestHighlight();
} }
// Focus on a different tile but decrement index
void InkHUD::WindowManager::prevTile()
{
// Close the menu applet if open
// We don't *really* want to do this, but it simplifies handling *a lot*
MenuApplet *menu = (MenuApplet *)inkhud->getSystemApplet("Menu");
bool menuWasOpen = false;
if (menu->isForeground()) {
menu->sendToBackground();
menuWasOpen = true;
}
// Swap to next tile
if (settings->userTiles.focused == 0)
settings->userTiles.focused = settings->userTiles.count - 1;
else
settings->userTiles.focused--;
// Make sure that we don't get stuck on the placeholder tile
refocusTile();
if (menuWasOpen)
menu->show(userTiles.at(settings->userTiles.focused));
// Ask the tile to draw an indicator showing which tile is now focused
// Requests a render
// We only draw this indicator if the device uses an aux button to switch tiles.
// Assume aux button is used to switch tiles if the "next tile" menu item is hidden
if (!settings->optionalMenuItems.nextTile)
userTiles.at(settings->userTiles.focused)->requestHighlight();
}
// Show the menu (on the the focused tile) // Show the menu (on the the focused tile)
// The applet previously displayed there will be restored once the menu closes // The applet previously displayed there will be restored once the menu closes
void InkHUD::WindowManager::openMenu() void InkHUD::WindowManager::openMenu()
@@ -106,6 +139,15 @@ void InkHUD::WindowManager::openMenu()
menu->show(userTiles.at(settings->userTiles.focused)); menu->show(userTiles.at(settings->userTiles.focused));
} }
// Bring the AlignStick applet to the foreground
void InkHUD::WindowManager::openAlignStick()
{
if (settings->joystick.enabled) {
AlignStickApplet *alignStick = (AlignStickApplet *)inkhud->getSystemApplet("AlignStick");
alignStick->bringToForeground();
}
}
// On the currently focussed tile: cycle to the next available user applet // On the currently focussed tile: cycle to the next available user applet
// Applets available for this must be activated, and not already displayed on another tile // Applets available for this must be activated, and not already displayed on another tile
void InkHUD::WindowManager::nextApplet() void InkHUD::WindowManager::nextApplet()
@@ -155,6 +197,59 @@ void InkHUD::WindowManager::nextApplet()
inkhud->forceUpdate(EInk::UpdateTypes::FAST); // bringToForeground already requested, but we're manually forcing FAST inkhud->forceUpdate(EInk::UpdateTypes::FAST); // bringToForeground already requested, but we're manually forcing FAST
} }
// On the currently focussed tile: cycle to the previous available user applet
// Applets available for this must be activated, and not already displayed on another tile
void InkHUD::WindowManager::prevApplet()
{
Tile *t = userTiles.at(settings->userTiles.focused);
// Abort if zero applets available
// nullptr means WindowManager::refocusTile determined that there were no available applets
if (!t->getAssignedApplet())
return;
// Find the index of the applet currently shown on the tile
uint8_t appletIndex = -1;
for (uint8_t i = 0; i < inkhud->userApplets.size(); i++) {
if (inkhud->userApplets.at(i) == t->getAssignedApplet()) {
appletIndex = i;
break;
}
}
// Confirm that we did find the applet
assert(appletIndex != (uint8_t)-1);
// Iterate forward through the WindowManager::applets, looking for the previous valid applet
Applet *prevValidApplet = nullptr;
for (uint8_t i = 1; i < inkhud->userApplets.size(); i++) {
uint8_t newAppletIndex = 0;
if (i > appletIndex)
newAppletIndex = inkhud->userApplets.size() + appletIndex - i;
else
newAppletIndex = (appletIndex - i);
Applet *a = inkhud->userApplets.at(newAppletIndex);
// Looking for an applet which is active (enabled by user), but currently in background
if (a->isActive() && !a->isForeground()) {
prevValidApplet = a;
settings->userTiles.displayedUserApplet[settings->userTiles.focused] =
newAppletIndex; // Remember this setting between boots!
break;
}
}
// Confirm that we found another applet
if (!prevValidApplet)
return;
// Hide old applet, show new applet
t->getAssignedApplet()->sendToBackground();
t->assignApplet(prevValidApplet);
prevValidApplet->bringToForeground();
inkhud->forceUpdate(EInk::UpdateTypes::FAST); // bringToForeground already requested, but we're manually forcing FAST
}
// Rotate the display image by 90 degrees // Rotate the display image by 90 degrees
void InkHUD::WindowManager::rotate() void InkHUD::WindowManager::rotate()
{ {
@@ -338,6 +433,8 @@ void InkHUD::WindowManager::createSystemApplets()
addSystemApplet("Logo", new LogoApplet, new Tile); addSystemApplet("Logo", new LogoApplet, new Tile);
addSystemApplet("Pairing", new PairingApplet, new Tile); addSystemApplet("Pairing", new PairingApplet, new Tile);
addSystemApplet("Tips", new TipsApplet, new Tile); addSystemApplet("Tips", new TipsApplet, new Tile);
if (settings->joystick.enabled)
addSystemApplet("AlignStick", new AlignStickApplet, new Tile);
addSystemApplet("Menu", new MenuApplet, nullptr); addSystemApplet("Menu", new MenuApplet, nullptr);
@@ -360,6 +457,8 @@ void InkHUD::WindowManager::placeSystemTiles()
inkhud->getSystemApplet("Logo")->getTile()->setRegion(0, 0, inkhud->width(), inkhud->height()); inkhud->getSystemApplet("Logo")->getTile()->setRegion(0, 0, inkhud->width(), inkhud->height());
inkhud->getSystemApplet("Pairing")->getTile()->setRegion(0, 0, inkhud->width(), inkhud->height()); inkhud->getSystemApplet("Pairing")->getTile()->setRegion(0, 0, inkhud->width(), inkhud->height());
inkhud->getSystemApplet("Tips")->getTile()->setRegion(0, 0, inkhud->width(), inkhud->height()); inkhud->getSystemApplet("Tips")->getTile()->setRegion(0, 0, inkhud->width(), inkhud->height());
if (settings->joystick.enabled)
inkhud->getSystemApplet("AlignStick")->getTile()->setRegion(0, 0, inkhud->width(), inkhud->height());
inkhud->getSystemApplet("Notification")->getTile()->setRegion(0, 0, inkhud->width(), 20); inkhud->getSystemApplet("Notification")->getTile()->setRegion(0, 0, inkhud->width(), 20);

View File

@@ -28,8 +28,11 @@ class WindowManager
// - call these to make stuff change // - call these to make stuff change
void nextTile(); void nextTile();
void prevTile();
void openMenu(); void openMenu();
void openAlignStick();
void nextApplet(); void nextApplet();
void prevApplet();
void rotate(); void rotate();
void toggleBatteryIcon(); void toggleBatteryIcon();

View File

@@ -0,0 +1,523 @@
#ifdef MESHTASTIC_INCLUDE_NICHE_GRAPHICS
#include "./TwoButtonExtended.h"
#include "NodeDB.h" // For the helper function TwoButtonExtended::getUserButtonPin
#include "PowerFSM.h"
#include "sleep.h"
using namespace NicheGraphics::Inputs;
TwoButtonExtended::TwoButtonExtended() : concurrency::OSThread("TwoButtonExtended")
{
// Don't start polling buttons for release immediately
// Assume they are in a "released" state at boot
OSThread::disable();
#ifdef ARCH_ESP32
// Register callbacks for before and after lightsleep
lsObserver.observe(&notifyLightSleep);
lsEndObserver.observe(&notifyLightSleepEnd);
#endif
// Explicitly initialize these, just to keep cppcheck quiet..
buttons[0] = Button();
buttons[1] = Button();
joystick[Direction::UP] = SimpleButton();
joystick[Direction::DOWN] = SimpleButton();
joystick[Direction::LEFT] = SimpleButton();
joystick[Direction::RIGHT] = SimpleButton();
}
// Get access to (or create) the singleton instance of this class
// Accessible inside the ISRs, even though we maybe shouldn't
TwoButtonExtended *TwoButtonExtended::getInstance()
{
// Instantiate the class the first time this method is called
static TwoButtonExtended *const singletonInstance = new TwoButtonExtended;
return singletonInstance;
}
// Begin receiving button input
// We probably need to do this after sleep, as well as at boot
void TwoButtonExtended::start()
{
if (buttons[0].pin != 0xFF)
attachInterrupt(buttons[0].pin, TwoButtonExtended::isrPrimary, buttons[0].activeLogic == LOW ? FALLING : RISING);
if (buttons[1].pin != 0xFF)
attachInterrupt(buttons[1].pin, TwoButtonExtended::isrSecondary, buttons[1].activeLogic == LOW ? FALLING : RISING);
if (joystick[Direction::UP].pin != 0xFF)
attachInterrupt(joystick[Direction::UP].pin, TwoButtonExtended::isrJoystickUp,
joystickActiveLogic == LOW ? FALLING : RISING);
if (joystick[Direction::DOWN].pin != 0xFF)
attachInterrupt(joystick[Direction::DOWN].pin, TwoButtonExtended::isrJoystickDown,
joystickActiveLogic == LOW ? FALLING : RISING);
if (joystick[Direction::LEFT].pin != 0xFF)
attachInterrupt(joystick[Direction::LEFT].pin, TwoButtonExtended::isrJoystickLeft,
joystickActiveLogic == LOW ? FALLING : RISING);
if (joystick[Direction::RIGHT].pin != 0xFF)
attachInterrupt(joystick[Direction::RIGHT].pin, TwoButtonExtended::isrJoystickRight,
joystickActiveLogic == LOW ? FALLING : RISING);
}
// Stop receiving button input, and run custom sleep code
// Called before device sleeps. This might be power-off, or just ESP32 light sleep
// Some devices will want to attach interrupts here, for the user button to wake from sleep
void TwoButtonExtended::stop()
{
if (buttons[0].pin != 0xFF)
detachInterrupt(buttons[0].pin);
if (buttons[1].pin != 0xFF)
detachInterrupt(buttons[1].pin);
if (joystick[Direction::UP].pin != 0xFF)
detachInterrupt(joystick[Direction::UP].pin);
if (joystick[Direction::DOWN].pin != 0xFF)
detachInterrupt(joystick[Direction::DOWN].pin);
if (joystick[Direction::LEFT].pin != 0xFF)
detachInterrupt(joystick[Direction::LEFT].pin);
if (joystick[Direction::RIGHT].pin != 0xFF)
detachInterrupt(joystick[Direction::RIGHT].pin);
}
// Attempt to resolve a GPIO pin for the user button, honoring userPrefs.jsonc and device settings
// This helper method isn't used by the TwoButtonExtended class itself, it could be moved elsewhere.
// Intention is to pass this value to TwoButtonExtended::setWiring in the setupNicheGraphics method.
uint8_t TwoButtonExtended::getUserButtonPin()
{
uint8_t pin = 0xFF; // Unset
// Use default pin for variant, if no better source
#ifdef BUTTON_PIN
pin = BUTTON_PIN;
#endif
// From userPrefs.jsonc, if set
#ifdef USERPREFS_BUTTON_PIN
pin = USERPREFS_BUTTON_PIN;
#endif
// From user's override in device settings, if set
if (config.device.button_gpio)
pin = config.device.button_gpio;
return pin;
}
// Configures the wiring and logic of either button
// Called when outlining your NicheGraphics implementation, in variant/nicheGraphics.cpp
void TwoButtonExtended::setWiring(uint8_t whichButton, uint8_t pin, bool internalPullup)
{
// Prevent the same GPIO being assigned to multiple buttons
// Allows an edge case when the user remaps hardware buttons using device settings, due to a broken user button
for (uint8_t i = 0; i < whichButton; i++) {
if (buttons[i].pin == pin) {
LOG_WARN("Attempted reuse of GPIO %d. Ignoring assignment whichButton=%d", pin, whichButton);
return;
}
}
assert(whichButton < 2);
buttons[whichButton].pin = pin;
buttons[whichButton].activeLogic = LOW;
pinMode(buttons[whichButton].pin, internalPullup ? INPUT_PULLUP : INPUT);
}
// Configures the wiring and logic of the joystick buttons
// Called when outlining your NicheGraphics implementation, in variant/nicheGraphics.cpp
void TwoButtonExtended::setJoystickWiring(uint8_t uPin, uint8_t dPin, uint8_t lPin, uint8_t rPin, bool internalPullup)
{
if (joystick[Direction::UP].pin == uPin || joystick[Direction::DOWN].pin == dPin || joystick[Direction::LEFT].pin == lPin ||
joystick[Direction::RIGHT].pin == rPin) {
LOG_WARN("Attempted reuse of Joystick GPIO. Ignoring assignment");
return;
}
joystick[Direction::UP].pin = uPin;
joystick[Direction::DOWN].pin = dPin;
joystick[Direction::LEFT].pin = lPin;
joystick[Direction::RIGHT].pin = rPin;
joystickActiveLogic = LOW;
pinMode(joystick[Direction::UP].pin, internalPullup ? INPUT_PULLUP : INPUT);
pinMode(joystick[Direction::DOWN].pin, internalPullup ? INPUT_PULLUP : INPUT);
pinMode(joystick[Direction::LEFT].pin, internalPullup ? INPUT_PULLUP : INPUT);
pinMode(joystick[Direction::RIGHT].pin, internalPullup ? INPUT_PULLUP : INPUT);
}
void TwoButtonExtended::setTiming(uint8_t whichButton, uint32_t debounceMs, uint32_t longpressMs)
{
assert(whichButton < 2);
buttons[whichButton].debounceLength = debounceMs;
buttons[whichButton].longpressLength = longpressMs;
}
void TwoButtonExtended::setJoystickDebounce(uint32_t debounceMs)
{
joystickDebounceLength = debounceMs;
}
// Set what should happen when a button becomes pressed
// Use this to implement a "while held" behavior
void TwoButtonExtended::setHandlerDown(uint8_t whichButton, Callback onDown)
{
assert(whichButton < 2);
buttons[whichButton].onDown = onDown;
}
// Set what should happen when a button becomes unpressed
// Use this to implement a "While held" behavior
void TwoButtonExtended::setHandlerUp(uint8_t whichButton, Callback onUp)
{
assert(whichButton < 2);
buttons[whichButton].onUp = onUp;
}
// Set what should happen when a "short press" event has occurred
void TwoButtonExtended::setHandlerShortPress(uint8_t whichButton, Callback onPress)
{
assert(whichButton < 2);
buttons[whichButton].onPress = onPress;
}
// Set what should happen when a "long press" event has fired
// Note: this will occur while the button is still held
void TwoButtonExtended::setHandlerLongPress(uint8_t whichButton, Callback onLongPress)
{
assert(whichButton < 2);
buttons[whichButton].onLongPress = onLongPress;
}
// Set what should happen when a joystick button becomes pressed
// Use this to implement a "while held" behavior
void TwoButtonExtended::setJoystickDownHandlers(Callback uDown, Callback dDown, Callback lDown, Callback rDown)
{
joystick[Direction::UP].onDown = uDown;
joystick[Direction::DOWN].onDown = dDown;
joystick[Direction::LEFT].onDown = lDown;
joystick[Direction::RIGHT].onDown = rDown;
}
// Set what should happen when a joystick button becomes unpressed
// Use this to implement a "while held" behavior
void TwoButtonExtended::setJoystickUpHandlers(Callback uUp, Callback dUp, Callback lUp, Callback rUp)
{
joystick[Direction::UP].onUp = uUp;
joystick[Direction::DOWN].onUp = dUp;
joystick[Direction::LEFT].onUp = lUp;
joystick[Direction::RIGHT].onUp = rUp;
}
// Set what should happen when a "press" event has fired
// Note: this will occur while the joystick button is still held
void TwoButtonExtended::setJoystickPressHandlers(Callback uPress, Callback dPress, Callback lPress, Callback rPress)
{
joystick[Direction::UP].onPress = uPress;
joystick[Direction::DOWN].onPress = dPress;
joystick[Direction::LEFT].onPress = lPress;
joystick[Direction::RIGHT].onPress = rPress;
}
// Handle the start of a press to the primary button
// Wakes our button thread
void TwoButtonExtended::isrPrimary()
{
static volatile bool isrRunning = false;
if (!isrRunning) {
isrRunning = true;
TwoButtonExtended *b = TwoButtonExtended::getInstance();
if (b->buttons[0].state == State::REST) {
b->buttons[0].state = State::IRQ;
b->buttons[0].irqAtMillis = millis();
b->startThread();
}
isrRunning = false;
}
}
// Handle the start of a press to the secondary button
// Wakes our button thread
void TwoButtonExtended::isrSecondary()
{
static volatile bool isrRunning = false;
if (!isrRunning) {
isrRunning = true;
TwoButtonExtended *b = TwoButtonExtended::getInstance();
if (b->buttons[1].state == State::REST) {
b->buttons[1].state = State::IRQ;
b->buttons[1].irqAtMillis = millis();
b->startThread();
}
isrRunning = false;
}
}
// Handle the start of a press to the joystick buttons
// Also wakes our button thread
void TwoButtonExtended::isrJoystickUp()
{
static volatile bool isrRunning = false;
if (!isrRunning) {
isrRunning = true;
TwoButtonExtended *b = TwoButtonExtended::getInstance();
if (b->joystick[Direction::UP].state == State::REST) {
b->joystick[Direction::UP].state = State::IRQ;
b->joystick[Direction::UP].irqAtMillis = millis();
b->startThread();
}
isrRunning = false;
}
}
void TwoButtonExtended::isrJoystickDown()
{
static volatile bool isrRunning = false;
if (!isrRunning) {
isrRunning = true;
TwoButtonExtended *b = TwoButtonExtended::getInstance();
if (b->joystick[Direction::DOWN].state == State::REST) {
b->joystick[Direction::DOWN].state = State::IRQ;
b->joystick[Direction::DOWN].irqAtMillis = millis();
b->startThread();
}
isrRunning = false;
}
}
void TwoButtonExtended::isrJoystickLeft()
{
static volatile bool isrRunning = false;
if (!isrRunning) {
isrRunning = true;
TwoButtonExtended *b = TwoButtonExtended::getInstance();
if (b->joystick[Direction::LEFT].state == State::REST) {
b->joystick[Direction::LEFT].state = State::IRQ;
b->joystick[Direction::LEFT].irqAtMillis = millis();
b->startThread();
}
isrRunning = false;
}
}
void TwoButtonExtended::isrJoystickRight()
{
static volatile bool isrRunning = false;
if (!isrRunning) {
isrRunning = true;
TwoButtonExtended *b = TwoButtonExtended::getInstance();
if (b->joystick[Direction::RIGHT].state == State::REST) {
b->joystick[Direction::RIGHT].state = State::IRQ;
b->joystick[Direction::RIGHT].irqAtMillis = millis();
b->startThread();
}
isrRunning = false;
}
}
// Concise method to start our button thread
// Follows an ISR, listening for button release
void TwoButtonExtended::startThread()
{
if (!OSThread::enabled) {
OSThread::setInterval(10);
OSThread::enabled = true;
}
}
// Concise method to stop our button thread
// Called when we no longer need to poll for button release
void TwoButtonExtended::stopThread()
{
if (OSThread::enabled) {
OSThread::disable();
}
// Reset both buttons manually
// Just in case an IRQ fires during the process of resetting the system
// Can occur with super rapid presses?
buttons[0].state = REST;
buttons[1].state = REST;
joystick[Direction::UP].state = REST;
joystick[Direction::DOWN].state = REST;
joystick[Direction::LEFT].state = REST;
joystick[Direction::RIGHT].state = REST;
}
// Our button thread
// Started by an IRQ, on either button
// Polls for button releases
// Stops when both buttons released
int32_t TwoButtonExtended::runOnce()
{
constexpr uint8_t BUTTON_COUNT = sizeof(buttons) / sizeof(Button);
constexpr uint8_t JOYSTICK_COUNT = sizeof(joystick) / sizeof(SimpleButton);
// Allow either button to request that our thread should continue polling
bool awaitingRelease = false;
// Check both primary and secondary buttons
for (uint8_t i = 0; i < BUTTON_COUNT; i++) {
switch (buttons[i].state) {
// No action: button has not been pressed
case REST:
break;
// New press detected by interrupt
case IRQ:
powerFSM.trigger(EVENT_PRESS); // Tell PowerFSM that press occurred (resets sleep timer)
buttons[i].onDown(); // Run callback: press has begun (possible hold behavior)
buttons[i].state = State::POLLING_UNFIRED; // Mark that button-down has been handled
awaitingRelease = true; // Mark that polling-for-release should continue
break;
// An existing press continues
// Not held long enough to register as longpress
case POLLING_UNFIRED: {
uint32_t length = millis() - buttons[i].irqAtMillis;
// If button released since last thread tick,
if (digitalRead(buttons[i].pin) != buttons[i].activeLogic) {
buttons[i].onUp(); // Run callback: press has ended (possible release of a hold)
buttons[i].state = State::REST; // Mark that the button has reset
if (length > buttons[i].debounceLength && length < buttons[i].longpressLength) // If too short for longpress,
buttons[i].onPress(); // Run callback: press
}
// If button not yet released
else {
awaitingRelease = true; // Mark that polling-for-release should continue
if (length >= buttons[i].longpressLength) {
// Run callback: long press (once)
// Then continue waiting for release, to rearm
buttons[i].state = State::POLLING_FIRED;
buttons[i].onLongPress();
}
}
break;
}
// Button still held, but duration long enough that longpress event already fired
// Just waiting for release
case POLLING_FIRED:
// Release detected
if (digitalRead(buttons[i].pin) != buttons[i].activeLogic) {
buttons[i].state = State::REST;
buttons[i].onUp(); // Callback: release of hold (in this case: *after* longpress has fired)
}
// Not yet released, keep polling
else
awaitingRelease = true;
break;
}
}
// Check all the joystick directions
for (uint8_t i = 0; i < JOYSTICK_COUNT; i++) {
switch (joystick[i].state) {
// No action: button has not been pressed
case REST:
break;
// New press detected by interrupt
case IRQ:
powerFSM.trigger(EVENT_PRESS); // Tell PowerFSM that press occurred (resets sleep timer)
joystick[i].onDown(); // Run callback: press has begun (possible hold behavior)
joystick[i].state = State::POLLING_UNFIRED; // Mark that button-down has been handled
awaitingRelease = true; // Mark that polling-for-release should continue
break;
// An existing press continues
// Not held long enough to register as press
case POLLING_UNFIRED: {
uint32_t length = millis() - joystick[i].irqAtMillis;
// If button released since last thread tick,
if (digitalRead(joystick[i].pin) != joystickActiveLogic) {
joystick[i].onUp(); // Run callback: press has ended (possible release of a hold)
joystick[i].state = State::REST; // Mark that the button has reset
}
// If button not yet released
else {
awaitingRelease = true; // Mark that polling-for-release should continue
if (length >= joystickDebounceLength) {
// Run callback: long press (once)
// Then continue waiting for release, to rearm
joystick[i].state = State::POLLING_FIRED;
joystick[i].onPress();
}
}
break;
}
// Button still held after press
// Just waiting for release
case POLLING_FIRED:
// Release detected
if (digitalRead(joystick[i].pin) != joystickActiveLogic) {
joystick[i].state = State::REST;
joystick[i].onUp(); // Callback: release of hold
}
// Not yet released, keep polling
else
awaitingRelease = true;
break;
}
}
// If all buttons are now released
// we don't need to waste cpu resources polling
// IRQ will restart this thread when we next need it
if (!awaitingRelease)
stopThread();
// Run this method again, or don't..
// Use whatever behavior was previously set by stopThread() or startThread()
return OSThread::interval;
}
#ifdef ARCH_ESP32
// Detach our class' interrupts before lightsleep
// Allows sleep.cpp to configure its own interrupts, which wake the device on user-button press
int TwoButtonExtended::beforeLightSleep(void *unused)
{
stop();
return 0; // Indicates success
}
// Reconfigure our interrupts
// Our class' interrupts were disconnected during sleep, to allow the user button to wake the device from sleep
int TwoButtonExtended::afterLightSleep(esp_sleep_wakeup_cause_t cause)
{
start();
// Manually trigger the button-down ISR
// - during light sleep, our ISR is disabled
// - if light sleep ends by button press, pretend our own ISR caught it
// - need to manually confirm by reading pin ourselves, to avoid occasional false positives
// (false positive only when using internal pullup resistors?)
if (cause == ESP_SLEEP_WAKEUP_GPIO && digitalRead(buttons[0].pin) == buttons[0].activeLogic)
isrPrimary();
return 0; // Indicates success
}
#endif
#endif

View File

@@ -0,0 +1,136 @@
#ifdef MESHTASTIC_INCLUDE_NICHE_GRAPHICS
/*
Re-usable NicheGraphics input source
Short and Long press for up to two buttons
Interrupt driven
*/
/*
This expansion adds support for four more buttons
These buttons are single-action only, no long press
Interrupt driven
*/
#pragma once
#include "configuration.h"
#include "assert.h"
#include "functional"
#ifdef ARCH_ESP32
#include "esp_sleep.h" // For light-sleep handling
#endif
#include "Observer.h"
namespace NicheGraphics::Inputs
{
class TwoButtonExtended : protected concurrency::OSThread
{
public:
typedef std::function<void()> Callback;
static uint8_t getUserButtonPin(); // Resolve the GPIO, considering the various possible source of definition
static TwoButtonExtended *getInstance(); // Create or get the singleton instance
void start(); // Start handling button input
void stop(); // Stop handling button input (disconnect ISRs for sleep)
void setWiring(uint8_t whichButton, uint8_t pin, bool internalPullup = false);
void setJoystickWiring(uint8_t uPin, uint8_t dPin, uint8_t lPin, uint8_t rPin, bool internalPullup = false);
void setTiming(uint8_t whichButton, uint32_t debounceMs, uint32_t longpressMs);
void setJoystickDebounce(uint32_t debounceMs);
void setHandlerDown(uint8_t whichButton, Callback onDown);
void setHandlerUp(uint8_t whichButton, Callback onUp);
void setHandlerShortPress(uint8_t whichButton, Callback onShortPress);
void setHandlerLongPress(uint8_t whichButton, Callback onLongPress);
void setJoystickDownHandlers(Callback uDown, Callback dDown, Callback ldown, Callback rDown);
void setJoystickUpHandlers(Callback uUp, Callback dUp, Callback lUp, Callback rUp);
void setJoystickPressHandlers(Callback uPress, Callback dPress, Callback lPress, Callback rPress);
// Disconnect and reconnect interrupts for light sleep
#ifdef ARCH_ESP32
int beforeLightSleep(void *unused);
int afterLightSleep(esp_sleep_wakeup_cause_t cause);
#endif
private:
// Internal state of a specific button
enum State {
REST, // Up, no activity
IRQ, // Down detected, not yet handled
POLLING_UNFIRED, // Down handled, polling for release
POLLING_FIRED, // Longpress fired, button still held
};
// Joystick Directions
enum Direction { UP = 0, DOWN, LEFT, RIGHT };
// Data used for direction (single-action) buttons
class SimpleButton
{
public:
// Per-button config
uint8_t pin = 0xFF; // 0xFF: unset
volatile State state = State::REST; // Internal state
volatile uint32_t irqAtMillis; // millis() when button went down
// Per-button event callbacks
static void noop(){};
std::function<void()> onDown = noop;
std::function<void()> onUp = noop;
std::function<void()> onPress = noop;
};
// Data used for double-action buttons
class Button : public SimpleButton
{
public:
// Per-button extended config
bool activeLogic = LOW; // Active LOW by default.
uint32_t debounceLength = 50; // Minimum length for shortpress in ms
uint32_t longpressLength = 500; // Time until longpress in ms
// Per-button event callbacks
std::function<void()> onLongPress = noop;
};
#ifdef ARCH_ESP32
// Get notified when lightsleep begins and ends
CallbackObserver<TwoButtonExtended, void *> lsObserver =
CallbackObserver<TwoButtonExtended, void *>(this, &TwoButtonExtended::beforeLightSleep);
CallbackObserver<TwoButtonExtended, esp_sleep_wakeup_cause_t> lsEndObserver =
CallbackObserver<TwoButtonExtended, esp_sleep_wakeup_cause_t>(this, &TwoButtonExtended::afterLightSleep);
#endif
int32_t runOnce() override; // Timer method. Polls for button release
void startThread(); // Start polling for release
void stopThread(); // Stop polling for release
static void isrPrimary(); // User Button ISR
static void isrSecondary(); // optional aux button or joystick center
static void isrJoystickUp();
static void isrJoystickDown();
static void isrJoystickLeft();
static void isrJoystickRight();
TwoButtonExtended(); // Constructor made private: force use of Button::instance()
// Info about both buttons
Button buttons[2];
bool joystickActiveLogic = LOW; // Active LOW by default
uint32_t joystickDebounceLength = 50; // time until press in ms
SimpleButton joystick[4];
};
}; // namespace NicheGraphics::Inputs
#endif

View File

@@ -2,16 +2,14 @@
#if !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C && defined(HAS_BMA423) && __has_include(<SensorBMA423.hpp>) #if !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C && defined(HAS_BMA423) && __has_include(<SensorBMA423.hpp>)
using namespace MotionSensorI2C;
BMA423Sensor::BMA423Sensor(ScanI2C::FoundDevice foundDevice) : MotionSensor::MotionSensor(foundDevice) {} BMA423Sensor::BMA423Sensor(ScanI2C::FoundDevice foundDevice) : MotionSensor::MotionSensor(foundDevice) {}
bool BMA423Sensor::init() bool BMA423Sensor::init()
{ {
if (sensor.begin(deviceAddress(), &MotionSensorI2C::readRegister, &MotionSensorI2C::writeRegister)) { if (sensor.begin(Wire, deviceAddress())) {
sensor.configAccelerometer(sensor.RANGE_2G, sensor.ODR_100HZ, sensor.BW_NORMAL_AVG4, sensor.PERF_CONTINUOUS_MODE); sensor.configAccelerometer(sensor.RANGE_2G, sensor.ODR_100HZ, sensor.BW_NORMAL_AVG4, sensor.PERF_CONTINUOUS_MODE);
sensor.enableAccelerometer(); sensor.enableAccelerometer();
sensor.configInterrupt(BMA4_LEVEL_TRIGGER, BMA4_ACTIVE_HIGH, BMA4_PUSH_PULL, BMA4_OUTPUT_ENABLE, BMA4_INPUT_DISABLE); sensor.configInterrupt();
#ifdef BMA423_INT #ifdef BMA423_INT
pinMode(BMA4XX_INT, INPUT); pinMode(BMA4XX_INT, INPUT);
@@ -26,9 +24,9 @@ bool BMA423Sensor::init()
#ifdef T_WATCH_S3 #ifdef T_WATCH_S3
// Need to raise the wrist function, need to set the correct axis // Need to raise the wrist function, need to set the correct axis
sensor.setReampAxes(sensor.REMAP_TOP_LAYER_RIGHT_CORNER); sensor.setRemapAxes(sensor.REMAP_TOP_LAYER_RIGHT_CORNER);
#else #else
sensor.setReampAxes(sensor.REMAP_BOTTOM_LAYER_BOTTOM_LEFT_CORNER); sensor.setRemapAxes(sensor.REMAP_BOTTOM_LAYER_BOTTOM_LEFT_CORNER);
#endif #endif
// sensor.enableFeature(sensor.FEATURE_STEP_CNTR, true); // sensor.enableFeature(sensor.FEATURE_STEP_CNTR, true);
sensor.enableFeature(sensor.FEATURE_TILT, true); sensor.enableFeature(sensor.FEATURE_TILT, true);
@@ -50,7 +48,7 @@ bool BMA423Sensor::init()
int32_t BMA423Sensor::runOnce() int32_t BMA423Sensor::runOnce()
{ {
if (sensor.readIrqStatus() != DEV_WIRE_NONE) { if (sensor.readIrqStatus()) {
if (sensor.isTilt() || sensor.isDoubleTap()) { if (sensor.isTilt() || sensor.isDoubleTap()) {
wakeScreen(); wakeScreen();
return 500; return 500;

View File

@@ -61,32 +61,6 @@ class MotionSensor
uint32_t endCalibrationAt = 0; uint32_t endCalibrationAt = 0;
}; };
namespace MotionSensorI2C
{
static inline int readRegister(uint8_t address, uint8_t reg, uint8_t *data, uint8_t len)
{
Wire.beginTransmission(address);
Wire.write(reg);
Wire.endTransmission();
Wire.requestFrom((uint8_t)address, (uint8_t)len);
uint8_t i = 0;
while (Wire.available()) {
data[i++] = Wire.read();
}
return 0; // Pass
}
static inline int writeRegister(uint8_t address, uint8_t reg, uint8_t *data, uint8_t len)
{
Wire.beginTransmission(address);
Wire.write(reg);
Wire.write(data, len);
return (0 != Wire.endTransmission());
}
} // namespace MotionSensorI2C
#endif #endif
#endif #endif

View File

@@ -20,8 +20,8 @@ lib_deps =
${esp32_base.lib_deps} ${esp32_base.lib_deps}
# renovate: datasource=custom.pio depName=GxEPD2 packageName=zinggjm/library/GxEPD2 # renovate: datasource=custom.pio depName=GxEPD2 packageName=zinggjm/library/GxEPD2
zinggjm/GxEPD2@1.6.5 zinggjm/GxEPD2@1.6.5
# renovate: datasource=custom.pio depName=PCF8563 packageName=lewisxhe/library/PCF8563_Library # renovate: datasource=custom.pio depName=SensorLib packageName=lewisxhe/library/SensorLib
lewisxhe/PCF8563_Library@1.0.1 lewisxhe/SensorLib@0.3.2
lib_ignore = lib_ignore =
m5stack-coreink m5stack-coreink
monitor_filters = esp32_exception_decoder monitor_filters = esp32_exception_decoder

View File

@@ -13,7 +13,6 @@
#define LED_STATE_ON 1 // State when LED is lit #define LED_STATE_ON 1 // State when LED is lit
#define LED_PIN 10 #define LED_PIN 10
#include "pcf8563.h"
// PCF8563 RTC Module // PCF8563 RTC Module
#define PCF8563_RTC 0x51 #define PCF8563_RTC 0x51
#define HAS_RTC 1 #define HAS_RTC 1

View File

@@ -6,8 +6,6 @@
#define LED_GREEN 12 #define LED_GREEN 12
#define LED_BLUE 2 #define LED_BLUE 2
#define LED_BUILTIN LED_GREEN
static const uint8_t TX = 1; static const uint8_t TX = 1;
static const uint8_t RX = 3; static const uint8_t RX = 3;

View File

@@ -6,8 +6,6 @@
#define LED_GREEN 12 #define LED_GREEN 12
#define LED_BLUE 2 #define LED_BLUE 2
#define LED_BUILTIN LED_GREEN
static const uint8_t TX = 1; static const uint8_t TX = 1;
static const uint8_t RX = 3; static const uint8_t RX = 3;

View File

@@ -9,6 +9,7 @@ build_flags = ${esp32_base.build_flags}
-I variants/esp32/tbeam -I variants/esp32/tbeam
-DBOARD_HAS_PSRAM -DBOARD_HAS_PSRAM
-mfix-esp32-psram-cache-issue -mfix-esp32-psram-cache-issue
-ULED_BUILTIN
upload_speed = 921600 upload_speed = 921600
[env:tbeam-displayshield] [env:tbeam-displayshield]

View File

@@ -8,3 +8,4 @@ build_flags =
-I variants/esp32c6/tlora_c6 -I variants/esp32c6/tlora_c6
-DARDUINO_USB_CDC_ON_BOOT=1 -DARDUINO_USB_CDC_ON_BOOT=1
-DARDUINO_USB_MODE=1 -DARDUINO_USB_MODE=1
-ULED_BUILTIN

View File

@@ -56,10 +56,6 @@
#define HAS_SCREEN 1 #define HAS_SCREEN 1
#define USE_SH1106 1 #define USE_SH1106 1
// PCF8563 RTC Module
// #define PCF8563_RTC 0x51
// #define PIN_RTC_INT 48 // Interrupt from the PCF8563 RTC
#define HAS_RTC 0
#define HAS_GPS 0 #define HAS_GPS 0
#define BUTTON_PIN PIN_BUTTON1 #define BUTTON_PIN PIN_BUTTON1

View File

@@ -18,7 +18,5 @@ build_flags =
lib_deps = ${esp32s3_base.lib_deps} lib_deps = ${esp32s3_base.lib_deps}
# renovate: datasource=git-refs depName=meshtastic-GxEPD2 packageName=https://github.com/meshtastic/GxEPD2 gitBranch=master # renovate: datasource=git-refs depName=meshtastic-GxEPD2 packageName=https://github.com/meshtastic/GxEPD2 gitBranch=master
https://github.com/meshtastic/GxEPD2/archive/1655054ba298e0e29fc2044741940f927f9c2a43.zip https://github.com/meshtastic/GxEPD2/archive/1655054ba298e0e29fc2044741940f927f9c2a43.zip
# renovate: datasource=custom.pio depName=PCF8563 packageName=lewisxhe/library/PCF8563_Library
lewisxhe/PCF8563_Library@1.0.1
# renovate: datasource=custom.pio depName=PCA9557-arduino packageName=maxpromer/library/PCA9557-arduino # renovate: datasource=custom.pio depName=PCA9557-arduino packageName=maxpromer/library/PCA9557-arduino
maxpromer/PCA9557-arduino@1.0.0 maxpromer/PCA9557-arduino@1.0.0

View File

@@ -44,9 +44,6 @@
#define PIN_SERIAL1_RX GPS_TX_PIN #define PIN_SERIAL1_RX GPS_TX_PIN
#define PIN_SERIAL1_TX GPS_RX_PIN #define PIN_SERIAL1_TX GPS_RX_PIN
// PCF8563 RTC Module
#define PCF8563_RTC 0x51
#define SX126X_CS 17 #define SX126X_CS 17
#define LORA_SCK 16 #define LORA_SCK 16
#define LORA_MOSI 15 #define LORA_MOSI 15

View File

@@ -8,3 +8,4 @@ build_flags =
${esp32s3_base.build_flags} ${esp32s3_base.build_flags}
-D HELTEC_V3 -D HELTEC_V3
-I variants/esp32s3/heltec_v3 -I variants/esp32s3/heltec_v3
-ULED_BUILTIN

View File

@@ -6,10 +6,6 @@
#define USB_VID 0x303a #define USB_VID 0x303a
#define USB_PID 0x1001 #define USB_PID 0x1001
static const uint8_t LED_BUILTIN = 35;
#define BUILTIN_LED LED_BUILTIN // backward compatibility
#define LED_BUILTIN LED_BUILTIN // allow testing #ifdef LED_BUILTIN
static const uint8_t TX = 43; static const uint8_t TX = 43;
static const uint8_t RX = 44; static const uint8_t RX = 44;

View File

@@ -3,10 +3,6 @@
#include <stdint.h> #include <stdint.h>
static const uint8_t LED_BUILTIN = 45; // LED is not populated on earliest board variant
#define BUILTIN_LED LED_BUILTIN // Backward compatibility
#define LED_BUILTIN LED_BUILTIN
static const uint8_t TX = 43; static const uint8_t TX = 43;
static const uint8_t RX = 44; static const uint8_t RX = 44;

View File

@@ -19,8 +19,6 @@ lib_deps =
${esp32s3_base.lib_deps} ${esp32s3_base.lib_deps}
# renovate: datasource=git-refs depName=meshtastic-GxEPD2 packageName=https://github.com/meshtastic/GxEPD2 gitBranch=master # renovate: datasource=git-refs depName=meshtastic-GxEPD2 packageName=https://github.com/meshtastic/GxEPD2 gitBranch=master
https://github.com/meshtastic/GxEPD2/archive/1655054ba298e0e29fc2044741940f927f9c2a43.zip https://github.com/meshtastic/GxEPD2/archive/1655054ba298e0e29fc2044741940f927f9c2a43.zip
# renovate: datasource=custom.pio depName=PCF8563 packageName=lewisxhe/library/PCF8563_Library
lewisxhe/PCF8563_Library@1.0.1
upload_speed = 115200 upload_speed = 115200
[env:heltec-vision-master-e213-inkhud] [env:heltec-vision-master-e213-inkhud]

View File

@@ -3,10 +3,6 @@
#include <stdint.h> #include <stdint.h>
static const uint8_t LED_BUILTIN = 45; // LED is not populated on earliest board variant
#define BUILTIN_LED LED_BUILTIN // Backward compatibility
#define LED_BUILTIN LED_BUILTIN
static const uint8_t TX = 43; static const uint8_t TX = 43;
static const uint8_t RX = 44; static const uint8_t RX = 44;

View File

@@ -22,8 +22,6 @@ lib_deps =
${esp32s3_base.lib_deps} ${esp32s3_base.lib_deps}
# renovate: datasource=git-refs depName=meshtastic-GxEPD2 packageName=https://github.com/meshtastic/GxEPD2 gitBranch=master # renovate: datasource=git-refs depName=meshtastic-GxEPD2 packageName=https://github.com/meshtastic/GxEPD2 gitBranch=master
https://github.com/meshtastic/GxEPD2/archive/448c8538129fde3d02a7cb5e6fc81971ad92547f.zip https://github.com/meshtastic/GxEPD2/archive/448c8538129fde3d02a7cb5e6fc81971ad92547f.zip
# renovate: datasource=custom.pio depName=PCF8563 packageName=lewisxhe/library/PCF8563_Library
lewisxhe/PCF8563_Library@1.0.1
upload_speed = 115200 upload_speed = 115200
[env:heltec-vision-master-e290-inkhud] [env:heltec-vision-master-e290-inkhud]

View File

@@ -3,10 +3,6 @@
#include <stdint.h> #include <stdint.h>
static const uint8_t LED_BUILTIN = 35;
#define BUILTIN_LED LED_BUILTIN // backward compatibility
#define LED_BUILTIN LED_BUILTIN
static const uint8_t TX = 43; static const uint8_t TX = 43;
static const uint8_t RX = 44; static const uint8_t RX = 44;

View File

@@ -8,8 +8,6 @@ build_flags =
-D HELTEC_VISION_MASTER_T190 -D HELTEC_VISION_MASTER_T190
lib_deps = lib_deps =
${esp32s3_base.lib_deps} ${esp32s3_base.lib_deps}
# renovate: datasource=custom.pio depName=PCF8563 packageName=lewisxhe/library/PCF8563_Library
lewisxhe/PCF8563_Library@1.0.1
# renovate: datasource=git-refs depName=meshtastic-st7789 packageName=https://github.com/meshtastic/st7789 gitBranch=main # renovate: datasource=git-refs depName=meshtastic-st7789 packageName=https://github.com/meshtastic/st7789 gitBranch=main
https://github.com/meshtastic/st7789/archive/bd33ea58ddfe4a5e4a66d53300ccbd38d66ac21f.zip https://github.com/meshtastic/st7789/archive/bd33ea58ddfe4a5e4a66d53300ccbd38d66ac21f.zip
upload_speed = 921600 upload_speed = 921600

View File

@@ -3,10 +3,6 @@
#include <stdint.h> #include <stdint.h>
static const uint8_t LED_BUILTIN = 18;
#define BUILTIN_LED LED_BUILTIN // backward compatibility
#define LED_BUILTIN LED_BUILTIN
static const uint8_t TX = 43; static const uint8_t TX = 43;
static const uint8_t RX = 44; static const uint8_t RX = 44;

View File

@@ -20,8 +20,6 @@ lib_deps =
${esp32s3_base.lib_deps} ${esp32s3_base.lib_deps}
# renovate: datasource=git-refs depName=meshtastic-GxEPD2 packageName=https://github.com/meshtastic/GxEPD2 gitBranch=master # renovate: datasource=git-refs depName=meshtastic-GxEPD2 packageName=https://github.com/meshtastic/GxEPD2 gitBranch=master
https://github.com/meshtastic/GxEPD2/archive/1655054ba298e0e29fc2044741940f927f9c2a43.zip https://github.com/meshtastic/GxEPD2/archive/1655054ba298e0e29fc2044741940f927f9c2a43.zip
# renovate: datasource=custom.pio depName=PCF8563 packageName=lewisxhe/library/PCF8563_Library
lewisxhe/PCF8563_Library@1.0.1
upload_speed = 115200 upload_speed = 115200
[env:heltec-wireless-paper-inkhud] [env:heltec-wireless-paper-inkhud]

View File

@@ -3,10 +3,6 @@
#include <stdint.h> #include <stdint.h>
static const uint8_t LED_BUILTIN = 18;
#define BUILTIN_LED LED_BUILTIN // backward compatibility
#define LED_BUILTIN LED_BUILTIN
static const uint8_t KEY_BUILTIN = 0; static const uint8_t KEY_BUILTIN = 0;
static const uint8_t TX = 43; static const uint8_t TX = 43;

View File

@@ -17,6 +17,4 @@ lib_deps =
${esp32s3_base.lib_deps} ${esp32s3_base.lib_deps}
# renovate: datasource=git-refs depName=meshtastic-GxEPD2 packageName=https://github.com/meshtastic/GxEPD2 gitBranch=master # renovate: datasource=git-refs depName=meshtastic-GxEPD2 packageName=https://github.com/meshtastic/GxEPD2 gitBranch=master
https://github.com/meshtastic/GxEPD2/archive/55f618961db45a23eff0233546430f1e5a80f63a.zip https://github.com/meshtastic/GxEPD2/archive/55f618961db45a23eff0233546430f1e5a80f63a.zip
# renovate: datasource=custom.pio depName=PCF8563 packageName=lewisxhe/library/PCF8563_Library
lewisxhe/PCF8563_Library@1.0.1
upload_speed = 115200 upload_speed = 115200

View File

@@ -11,10 +11,6 @@
#define USB_VID 0x303a #define USB_VID 0x303a
#define USB_PID 0x1001 #define USB_PID 0x1001
static const uint8_t LED_BUILTIN = 18;
#define BUILTIN_LED LED_BUILTIN // backward compatibility
#define LED_BUILTIN LED_BUILTIN
static const uint8_t TX = 43; static const uint8_t TX = 43;
static const uint8_t RX = 44; static const uint8_t RX = 44;

View File

@@ -11,10 +11,6 @@
#define USB_VID 0x303a #define USB_VID 0x303a
#define USB_PID 0x1001 #define USB_PID 0x1001
static const uint8_t LED_BUILTIN = 18;
#define BUILTIN_LED LED_BUILTIN // backward compatibility
#define LED_BUILTIN LED_BUILTIN
static const uint8_t TX = 43; static const uint8_t TX = 43;
static const uint8_t RX = 44; static const uint8_t RX = 44;

View File

@@ -10,10 +10,6 @@
#define USB_VID 0x303a #define USB_VID 0x303a
#define USB_PID 0x1001 #define USB_PID 0x1001
static const uint8_t LED_BUILTIN = 18;
#define BUILTIN_LED LED_BUILTIN // backward compatibility
#define LED_BUILTIN LED_BUILTIN
static const uint8_t TX = 43; static const uint8_t TX = 43;
static const uint8_t RX = 44; static const uint8_t RX = 44;

View File

@@ -10,10 +10,7 @@
// Some boards have too low voltage on this pin (board design bug) // Some boards have too low voltage on this pin (board design bug)
// Use different pin with 3V and connect with 48 // Use different pin with 3V and connect with 48
// and change this setup for the chosen pin (for example 38) // and change this setup for the chosen pin (for example 38)
static const uint8_t LED_BUILTIN = SOC_GPIO_PIN_COUNT + 48; #define RGB_BUILTIN SOC_GPIO_PIN_COUNT + 48
#define BUILTIN_LED LED_BUILTIN // backward compatibility
#define LED_BUILTIN LED_BUILTIN
#define RGB_BUILTIN LED_BUILTIN
#define RGB_BRIGHTNESS 64 #define RGB_BRIGHTNESS 64
static const uint8_t TX = 43; static const uint8_t TX = 43;

View File

@@ -49,10 +49,6 @@ static const uint8_t T14 = 14;
static const uint8_t VBAT_SENSE = 2; static const uint8_t VBAT_SENSE = 2;
static const uint8_t VBUS_SENSE = 34; static const uint8_t VBUS_SENSE = 34;
// User LED
#define LED_BUILTIN 13
#define BUILTIN_LED LED_BUILTIN // backward compatibility
static const uint8_t RGB_DATA = 40; static const uint8_t RGB_DATA = 40;
// RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API neopixelWrite() // RGB_BUILTIN and RGB_BRIGHTNESS can be used in new Arduino API neopixelWrite()
#define RGB_BUILTIN (RGB_DATA + SOC_GPIO_PIN_COUNT) #define RGB_BUILTIN (RGB_DATA + SOC_GPIO_PIN_COUNT)

View File

@@ -22,7 +22,4 @@ static const uint8_t SCK = 13;
#define SPI_MISO (10) #define SPI_MISO (10)
#define SPI_CS (12) #define SPI_CS (12)
// LEDs
#define LED_BUILTIN LED_GREEN
#endif /* Pins_Arduino_h */ #endif /* Pins_Arduino_h */

View File

@@ -22,7 +22,4 @@ static const uint8_t SCK = 13;
#define SPI_MISO (10) #define SPI_MISO (10)
#define SPI_CS (12) #define SPI_CS (12)
// LEDs
#define LED_BUILTIN LED_GREEN
#endif /* Pins_Arduino_h */ #endif /* Pins_Arduino_h */

View File

@@ -3,8 +3,6 @@
#include <stdint.h> #include <stdint.h>
// static const uint8_t LED_BUILTIN = -1;
// static const uint8_t TX = 43; // static const uint8_t TX = 43;
// static const uint8_t RX = 44; // static const uint8_t RX = 44;

View File

@@ -6,8 +6,6 @@
#define USB_VID 0x303a #define USB_VID 0x303a
#define USB_PID 0x1001 #define USB_PID 0x1001
// static const uint8_t LED_BUILTIN = -1;
static const uint8_t TX = 43; static const uint8_t TX = 43;
static const uint8_t RX = 44; static const uint8_t RX = 44;

View File

@@ -3,8 +3,6 @@
#include <stdint.h> #include <stdint.h>
// static const uint8_t LED_BUILTIN = -1;
// static const uint8_t TX = 43; // static const uint8_t TX = 43;
// static const uint8_t RX = 44; // static const uint8_t RX = 44;

View File

@@ -9,14 +9,12 @@ upload_protocol = esptool
build_flags = ${esp32s3_base.build_flags} build_flags = ${esp32s3_base.build_flags}
-DT_WATCH_S3 -DT_WATCH_S3
-Ivariants/esp32s3/t-watch-s3 -Ivariants/esp32s3/t-watch-s3
-DPCF8563_RTC=0x51
-DHAS_BMA423=1
lib_deps = ${esp32s3_base.lib_deps} lib_deps = ${esp32s3_base.lib_deps}
# renovate: datasource=custom.pio depName=LovyanGFX packageName=lovyan03/library/LovyanGFX # renovate: datasource=custom.pio depName=LovyanGFX packageName=lovyan03/library/LovyanGFX
lovyan03/LovyanGFX@1.2.7 lovyan03/LovyanGFX@1.2.7
# renovate: datasource=custom.pio depName=PCF8563 packageName=lewisxhe/library/PCF8563_Library # renovate: datasource=custom.pio depName=SensorLib packageName=lewisxhe/library/SensorLib
lewisxhe/PCF8563_Library@1.0.1 lewisxhe/SensorLib@0.3.2
# renovate: datasource=custom.pio depName=Adafruit DRV2605 packageName=adafruit/library/Adafruit DRV2605 Library # renovate: datasource=custom.pio depName=Adafruit DRV2605 packageName=adafruit/library/Adafruit DRV2605 Library
adafruit/Adafruit DRV2605 Library@1.2.4 adafruit/Adafruit DRV2605 Library@1.2.4
# renovate: datasource=custom.pio depName=ESP8266Audio packageName=earlephilhower/library/ESP8266Audio # renovate: datasource=custom.pio depName=ESP8266Audio packageName=earlephilhower/library/ESP8266Audio

View File

@@ -41,11 +41,14 @@
#define HAS_AXP2101 #define HAS_AXP2101
// PCF8563 RTC Module
#define PCF8563_RTC 0x51
#define HAS_RTC 1 #define HAS_RTC 1
#define I2C_SDA 10 // For QMC6310 sensors and screens #define I2C_SDA 10 // For QMC6310 sensors and screens
#define I2C_SCL 11 // For QMC6310 sensors and screens #define I2C_SCL 11 // For QMC6310 sensors and screens
#define HAS_BMA423 1
#define BMA4XX_INT 14 // Interrupt for BMA_423 axis sensor #define BMA4XX_INT 14 // Interrupt for BMA_423 axis sensor
#define HAS_GPS 0 #define HAS_GPS 0

View File

@@ -7,10 +7,9 @@ board_check = true
lib_deps = lib_deps =
${esp32s3_base.lib_deps} ${esp32s3_base.lib_deps}
# renovate: datasource=custom.pio depName=PCF8563 packageName=lewisxhe/library/PCF8563_Library # renovate: datasource=custom.pio depName=SensorLib packageName=lewisxhe/library/SensorLib
lewisxhe/PCF8563_Library@1.0.1 lewisxhe/SensorLib@0.3.2
build_flags = build_flags =
${esp32s3_base.build_flags} ${esp32s3_base.build_flags}
-I variants/esp32s3/tbeam-s3-core -I variants/esp32s3/tbeam-s3-core
-D PCF8563_RTC=0x51 ;Putting definitions in variant.h does not compile correctly

View File

@@ -53,6 +53,8 @@
// #define PMU_IRQ 40 // #define PMU_IRQ 40
#define HAS_AXP2101 #define HAS_AXP2101
// PCF8563 RTC Module
#define PCF8563_RTC 0x51
#define HAS_RTC 1 #define HAS_RTC 1
// Specify the PMU as Wire1. In the t-beam-s3 core, PCF8563 and PMU share the bus // Specify the PMU as Wire1. In the t-beam-s3 core, PCF8563 and PMU share the bus
@@ -72,9 +74,6 @@
#define HAS_SDCARD // Have SPI interface SD card slot #define HAS_SDCARD // Have SPI interface SD card slot
#define SDCARD_USE_SPI1 #define SDCARD_USE_SPI1
// PCF8563 RTC Module
// #define PCF8563_RTC 0x51 //Putting definitions in variant. h does not compile correctly
// has 32768 Hz crystal // has 32768 Hz crystal
#define HAS_32768HZ 1 #define HAS_32768HZ 1

View File

@@ -27,8 +27,8 @@ lib_deps = ${esp32s3_base.lib_deps}
adafruit/Adafruit DRV2605 Library@1.2.4 adafruit/Adafruit DRV2605 Library@1.2.4
# renovate: datasource=custom.pio depName=PCF8563 packageName=lewisxhe/library/PCF8563_Library # renovate: datasource=custom.pio depName=PCF8563 packageName=lewisxhe/library/PCF8563_Library
lewisxhe/PCF8563_Library@1.0.1 lewisxhe/PCF8563_Library@1.0.1
# renovate: datasource=custom.pio depName=lewisxhe-SensorLib packageName=lewisxhe/library/SensorLib # renovate: datasource=custom.pio depName=SensorLib packageName=lewisxhe/library/SensorLib
lewisxhe/SensorLib@0.3.1 lewisxhe/SensorLib@0.3.2
# renovate: datasource=github-tags depName=pschatzmann_arduino-audio-driver packageName=pschatzmann/arduino-audio-driver # renovate: datasource=github-tags depName=pschatzmann_arduino-audio-driver packageName=pschatzmann/arduino-audio-driver
https://github.com/pschatzmann/arduino-audio-driver/archive/v0.1.3.zip https://github.com/pschatzmann/arduino-audio-driver/archive/v0.1.3.zip
# TODO renovate # TODO renovate

View File

@@ -35,11 +35,8 @@
#define GPS_TX_PIN 12 #define GPS_TX_PIN 12
#define PIN_GPS_PPS 13 #define PIN_GPS_PPS 13
// PCF8563 RTC Module // PCF85063 RTC Module
#if __has_include("pcf8563.h") #define PCF85063_RTC 0x51
#include "pcf8563.h"
#endif
#define PCF8563_RTC 0x51
#define HAS_RTC 1 #define HAS_RTC 1
// Rotary // Rotary

View File

@@ -11,10 +11,6 @@
#define USB_VID 0x303a #define USB_VID 0x303a
#define USB_PID 0x1001 #define USB_PID 0x1001
static const uint8_t LED_BUILTIN = 18;
#define BUILTIN_LED LED_BUILTIN // backward compatibility
#define LED_BUILTIN LED_BUILTIN
static const uint8_t TX = 43; static const uint8_t TX = 43;
static const uint8_t RX = 44; static const uint8_t RX = 44;

View File

@@ -11,10 +11,6 @@
#define USB_VID 0x303a #define USB_VID 0x303a
#define USB_PID 0x1001 #define USB_PID 0x1001
static const uint8_t LED_BUILTIN = 18;
#define BUILTIN_LED LED_BUILTIN // backward compatibility
#define LED_BUILTIN LED_BUILTIN
static const uint8_t TX = 43; static const uint8_t TX = 43;
static const uint8_t RX = 44; static const uint8_t RX = 44;

View File

@@ -11,10 +11,6 @@
#define USB_VID 0x303a #define USB_VID 0x303a
#define USB_PID 0x1001 #define USB_PID 0x1001
static const uint8_t LED_BUILTIN = 18;
#define BUILTIN_LED LED_BUILTIN // backward compatibility
#define LED_BUILTIN LED_BUILTIN
static const uint8_t TX = 43; static const uint8_t TX = 43;
static const uint8_t RX = 44; static const uint8_t RX = 44;

View File

@@ -6,9 +6,6 @@
#define USB_VID 0x16D0 #define USB_VID 0x16D0
#define USB_PID 0x1178 #define USB_PID 0x1178
#define LED_BUILTIN 13
#define BUILTIN_LED LED_BUILTIN // backward compatibility
static const uint8_t TX = 43; static const uint8_t TX = 43;
static const uint8_t RX = 44; static const uint8_t RX = 44;

View File

@@ -50,7 +50,6 @@ extern "C" {
#define RGBLED_BLUE (0 + 12) // Blue of RGB P0.12 #define RGBLED_BLUE (0 + 12) // Blue of RGB P0.12
#define RGBLED_CA // comment out this line if you have a common cathode type, as defined use common anode logic #define RGBLED_CA // comment out this line if you have a common cathode type, as defined use common anode logic
#define LED_BUILTIN PIN_LED1
#define LED_CONN PIN_LED2 #define LED_CONN PIN_LED2
#define LED_GREEN PIN_LED1 #define LED_GREEN PIN_LED1

View File

@@ -25,8 +25,6 @@ lib_deps =
${nrf52840_base.lib_deps} ${nrf52840_base.lib_deps}
# renovate: datasource=git-refs depName=meshtastic-GxEPD2 packageName=https://github.com/meshtastic/GxEPD2 gitBranch=master # renovate: datasource=git-refs depName=meshtastic-GxEPD2 packageName=https://github.com/meshtastic/GxEPD2 gitBranch=master
https://github.com/meshtastic/GxEPD2/archive/33db3fa8ee6fc47d160bdb44f8f127c9a9203a10.zip https://github.com/meshtastic/GxEPD2/archive/33db3fa8ee6fc47d160bdb44f8f127c9a9203a10.zip
# renovate: datasource=custom.pio depName=PCF8563 packageName=lewisxhe/library/PCF8563_Library
lewisxhe/PCF8563_Library@1.0.1
# renovate: datasource=custom.pio depName=nRF52_PWM packageName=khoih-prog/library/nRF52_PWM # renovate: datasource=custom.pio depName=nRF52_PWM packageName=khoih-prog/library/nRF52_PWM
khoih-prog/nRF52_PWM@1.0.1 khoih-prog/nRF52_PWM@1.0.1
;upload_protocol = fs ;upload_protocol = fs
@@ -48,5 +46,3 @@ build_src_filter =
lib_deps = lib_deps =
${inkhud.lib_deps} ; InkHUD libs first, so we get GFXRoot instead of AdafruitGFX ${inkhud.lib_deps} ; InkHUD libs first, so we get GFXRoot instead of AdafruitGFX
${nrf52840_base.lib_deps} ${nrf52840_base.lib_deps}
# renovate: datasource=custom.pio depName=PCF8563 packageName=lewisxhe/library/PCF8563_Library
lewisxhe/PCF8563_Library@1.0.1

View File

@@ -55,7 +55,6 @@ extern "C" {
#define LED_RED PIN_LED3 #define LED_RED PIN_LED3
#define LED_BLUE PIN_LED1 #define LED_BLUE PIN_LED1
#define LED_GREEN PIN_LED2 #define LED_GREEN PIN_LED2
#define LED_BUILTIN LED_BLUE
#define LED_CONN PIN_GREEN #define LED_CONN PIN_GREEN
#define LED_STATE_ON 0 // State when LED is lit // LED灯亮时的状态 #define LED_STATE_ON 0 // State when LED is lit // LED灯亮时的状态
#define PIN_BUZZER (0 + 6) #define PIN_BUZZER (0 + 6)
@@ -93,8 +92,6 @@ static const uint8_t A0 = PIN_A0;
#define TP_SER_IO (0 + 11) #define TP_SER_IO (0 + 11)
#define PIN_RTC_INT (0 + 16) // Interrupt from the PCF8563 RTC
/* /*
External serial flash WP25R1635FZUIL0 External serial flash WP25R1635FZUIL0
*/ */
@@ -161,9 +158,6 @@ External serial flash WP25R1635FZUIL0
#define PIN_SERIAL1_TX GPS_TX_PIN #define PIN_SERIAL1_TX GPS_TX_PIN
#define PIN_SERIAL1_RX GPS_RX_PIN #define PIN_SERIAL1_RX GPS_RX_PIN
// PCF8563 RTC Module
#define PCF8563_RTC 0x51
/* /*
* SPI Interfaces * SPI Interfaces
*/ */
@@ -190,7 +184,6 @@ External serial flash WP25R1635FZUIL0
#define VBAT_AR_INTERNAL AR_INTERNAL_3_0 #define VBAT_AR_INTERNAL AR_INTERNAL_3_0
#define ADC_MULTIPLIER (2.02F) #define ADC_MULTIPLIER (2.02F)
// #define HAS_RTC 0
// #define HAS_SCREEN 0 // #define HAS_SCREEN 0
#ifdef __cplusplus #ifdef __cplusplus

View File

@@ -58,7 +58,6 @@ extern "C" {
#define LED_BLUE 37 #define LED_BLUE 37
#define LED_PAIRING LED_BLUE // Signals the Status LED Module to handle this LED #define LED_PAIRING LED_BLUE // Signals the Status LED Module to handle this LED
#define LED_BUILTIN -1
#define LED_STATE_ON LOW #define LED_STATE_ON LOW
#define LED_STATE_OFF HIGH #define LED_STATE_OFF HIGH

View File

@@ -40,7 +40,6 @@ extern "C" {
#define NUM_ANALOG_OUTPUTS (0) #define NUM_ANALOG_OUTPUTS (0)
// LEDs // LEDs
#define LED_BUILTIN -1
#define LED_BLUE -1 #define LED_BLUE -1
#define LED_CHARGE (12) #define LED_CHARGE (12)
#define LED_PAIRING (7) #define LED_PAIRING (7)

View File

@@ -51,7 +51,6 @@ extern "C" {
#define PIN_LED1 (32 + 7) // P1.07 Blue D2 #define PIN_LED1 (32 + 7) // P1.07 Blue D2
#define LED_PIN PIN_LED1 #define LED_PIN PIN_LED1
#define LED_BUILTIN -1
#define LED_BLUE -1 #define LED_BLUE -1
#define LED_STATE_ON 1 // State when LED is lit #define LED_STATE_ON 1 // State when LED is lit

View File

@@ -51,7 +51,6 @@ extern "C" {
#define PIN_LED1 (32 + 7) // P1.07 Blue D2 #define PIN_LED1 (32 + 7) // P1.07 Blue D2
#define LED_PIN PIN_LED1 #define LED_PIN PIN_LED1
#define LED_BUILTIN -1
#define LED_BLUE -1 #define LED_BLUE -1
#define LED_STATE_ON 1 // State when LED is lit #define LED_STATE_ON 1 // State when LED is lit

View File

@@ -51,7 +51,6 @@ extern "C" {
#define PIN_LED1 (-1) #define PIN_LED1 (-1)
#define LED_PIN PIN_LED1 #define LED_PIN PIN_LED1
#define LED_BUILTIN -1
#define LED_BLUE -1 #define LED_BLUE -1
#define LED_STATE_ON 1 // State when LED is lit #define LED_STATE_ON 1 // State when LED is lit

View File

@@ -29,7 +29,6 @@ extern "C" {
#define PIN_LED1 (32 + 10) // LED P1.15 #define PIN_LED1 (32 + 10) // LED P1.15
#define PIN_LED2 (-1) // #define PIN_LED2 (-1) //
#define LED_BUILTIN PIN_LED1
#define LED_CONN PIN_LED2 #define LED_CONN PIN_LED2
#define LED_GREEN PIN_LED1 #define LED_GREEN PIN_LED1

View File

@@ -29,7 +29,6 @@ extern "C" {
#define PIN_LED1 (32 + 10) // LED P1.15 #define PIN_LED1 (32 + 10) // LED P1.15
#define PIN_LED2 (-1) // #define PIN_LED2 (-1) //
#define LED_BUILTIN PIN_LED1
#define LED_CONN PIN_LED2 #define LED_CONN PIN_LED2
#define LED_GREEN PIN_LED1 #define LED_GREEN PIN_LED1

View File

@@ -34,7 +34,6 @@ extern "C" {
// #define PIN_LED1 (32 + 9) Green // #define PIN_LED1 (32 + 9) Green
// #define PIN_LED1 (0 + 12) Blue // #define PIN_LED1 (0 + 12) Blue
#define LED_BUILTIN PIN_LED1
#define LED_CONN PIN_LED2 #define LED_CONN PIN_LED2
#define LED_GREEN PIN_LED1 #define LED_GREEN PIN_LED1

View File

@@ -11,6 +11,4 @@ build_flags =
build_src_filter = ${nrf52_base.build_src_filter} +<../variants/nrf52840/canaryone> build_src_filter = ${nrf52_base.build_src_filter} +<../variants/nrf52840/canaryone>
lib_deps = lib_deps =
${nrf52840_base.lib_deps} ${nrf52840_base.lib_deps}
# renovate: datasource=custom.pio depName=PCF8563 packageName=lewisxhe/library/PCF8563_Library
lewisxhe/PCF8563_Library@1.0.1
;upload_protocol = fs ;upload_protocol = fs

View File

@@ -52,7 +52,6 @@ extern "C" {
#define LED_BLUE PIN_LED1 #define LED_BLUE PIN_LED1
#define LED_BUILTIN PIN_LED1
#define LED_CONN PIN_LED3 #define LED_CONN PIN_LED3
#define LED_STATE_ON 0 // State when LED is lit #define LED_STATE_ON 0 // State when LED is lit

View File

@@ -81,7 +81,6 @@ NRF52 PRO MICRO PIN ASSIGNMENT
// LED // LED
#define PIN_LED1 (0 + 15) // P0.15 #define PIN_LED1 (0 + 15) // P0.15
#define LED_BUILTIN PIN_LED1
// Actually red // Actually red
#define LED_BLUE PIN_LED1 #define LED_BLUE PIN_LED1
#define LED_STATE_ON 1 // State when LED is lit #define LED_STATE_ON 1 // State when LED is lit

View File

@@ -38,7 +38,6 @@ extern "C" {
#define PIN_LED PIN_LED1 #define PIN_LED PIN_LED1
#define LED_PWR (PINS_COUNT) #define LED_PWR (PINS_COUNT)
#define LED_BUILTIN PIN_LED
#define LED_STATE_ON 1 // State when LED is lit #define LED_STATE_ON 1 // State when LED is lit
// XIAO Wio-SX1262 Shield User button // XIAO Wio-SX1262 Shield User button

View File

@@ -49,8 +49,6 @@ extern "C" {
#define PIN_LED1 (32 + 15) // P1.15 3 #define PIN_LED1 (32 + 15) // P1.15 3
#define PIN_LED2 (32 + 10) // P1.10 4 #define PIN_LED2 (32 + 10) // P1.10 4
#define LED_BUILTIN PIN_LED1
#define LED_GREEN PIN_LED2 // Actually red #define LED_GREEN PIN_LED2 // Actually red
#define LED_BLUE PIN_LED1 #define LED_BLUE PIN_LED1

View File

@@ -48,7 +48,6 @@ extern "C" {
#define PIN_LED1 (35) #define PIN_LED1 (35)
#define PIN_LED2 (36) #define PIN_LED2 (36)
#define LED_BUILTIN PIN_LED1
#define LED_CONN PIN_LED2 #define LED_CONN PIN_LED2
#define LED_GREEN PIN_LED1 #define LED_GREEN PIN_LED1

View File

@@ -14,8 +14,6 @@ build_src_filter =
lib_deps = lib_deps =
${inkhud.lib_deps} ; InkHUD libs first, so we get GFXRoot instead of AdafruitGFX ${inkhud.lib_deps} ; InkHUD libs first, so we get GFXRoot instead of AdafruitGFX
${nrf52840_base.lib_deps} ${nrf52840_base.lib_deps}
# renovate: datasource=custom.pio depName=PCF8563 packageName=lewisxhe/library/PCF8563_Library
lewisxhe/PCF8563_Library@1.0.1
extra_scripts = extra_scripts =
${env.extra_scripts} ${env.extra_scripts}
variants/nrf52840/diy/nrf52_promicro_diy_tcxo/custom_build_tasks.py ; Add to PIO's Project Tasks pane: preset builds for common displays variants/nrf52840/diy/nrf52_promicro_diy_tcxo/custom_build_tasks.py ; Add to PIO's Project Tasks pane: preset builds for common displays

View File

@@ -30,7 +30,6 @@ extern "C" {
#define PIN_LED1 (32 + 3) // green (confirmed on 1.0 board) #define PIN_LED1 (32 + 3) // green (confirmed on 1.0 board)
#define LED_BLUE PIN_LED1 // fake for bluefruit library #define LED_BLUE PIN_LED1 // fake for bluefruit library
#define LED_GREEN PIN_LED1 #define LED_GREEN PIN_LED1
#define LED_BUILTIN LED_GREEN
#define LED_STATE_ON 0 // State when LED is lit #define LED_STATE_ON 0 // State when LED is lit
#define HAS_NEOPIXEL // Enable the use of neopixels #define HAS_NEOPIXEL // Enable the use of neopixels
@@ -124,9 +123,6 @@ No longer populated on PCB
#define PIN_SERIAL1_RX GPS_RX_PIN #define PIN_SERIAL1_RX GPS_RX_PIN
#define PIN_SERIAL1_TX GPS_TX_PIN #define PIN_SERIAL1_TX GPS_TX_PIN
// PCF8563 RTC Module
#define PCF8563_RTC 0x51
/* /*
* SPI Interfaces * SPI Interfaces
*/ */
@@ -163,7 +159,6 @@ No longer populated on PCB
#define VBAT_AR_INTERNAL AR_INTERNAL_3_0 #define VBAT_AR_INTERNAL AR_INTERNAL_3_0
#define ADC_MULTIPLIER (4.90F) #define ADC_MULTIPLIER (4.90F)
#define HAS_RTC 0
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@@ -13,7 +13,5 @@ build_flags = ${nrf52840_base.build_flags}
build_src_filter = ${nrf52_base.build_src_filter} +<../variants/nrf52840/heltec_mesh_node_t114> build_src_filter = ${nrf52_base.build_src_filter} +<../variants/nrf52840/heltec_mesh_node_t114>
lib_deps = lib_deps =
${nrf52840_base.lib_deps} ${nrf52840_base.lib_deps}
# renovate: datasource=custom.pio depName=PCF8563 packageName=lewisxhe/library/PCF8563_Library
lewisxhe/PCF8563_Library@1.0.1
# renovate: datasource=git-refs depName=meshtastic-st7789 packageName=https://github.com/meshtastic/st7789 gitBranch=main # renovate: datasource=git-refs depName=meshtastic-st7789 packageName=https://github.com/meshtastic/st7789 gitBranch=main
https://github.com/meshtastic/st7789/archive/bd33ea58ddfe4a5e4a66d53300ccbd38d66ac21f.zip https://github.com/meshtastic/st7789/archive/bd33ea58ddfe4a5e4a66d53300ccbd38d66ac21f.zip

View File

@@ -74,7 +74,6 @@ extern "C" {
#define PIN_LED1 (32 + 3) // green (confirmed on 1.0 board) #define PIN_LED1 (32 + 3) // green (confirmed on 1.0 board)
#define LED_BLUE PIN_LED1 // fake for bluefruit library #define LED_BLUE PIN_LED1 // fake for bluefruit library
#define LED_GREEN PIN_LED1 #define LED_GREEN PIN_LED1
#define LED_BUILTIN LED_GREEN
#define LED_STATE_ON 0 // State when LED is lit #define LED_STATE_ON 0 // State when LED is lit
#define HAS_NEOPIXEL // Enable the use of neopixels #define HAS_NEOPIXEL // Enable the use of neopixels
@@ -175,9 +174,6 @@ No longer populated on PCB
#define PIN_SERIAL1_RX GPS_RX_PIN #define PIN_SERIAL1_RX GPS_RX_PIN
#define PIN_SERIAL1_TX GPS_TX_PIN #define PIN_SERIAL1_TX GPS_TX_PIN
// PCF8563 RTC Module
#define PCF8563_RTC 0x51
/* /*
* SPI Interfaces * SPI Interfaces
*/ */

View File

@@ -25,8 +25,6 @@ build_flags = ${nrf52840_base.build_flags}
build_src_filter = ${nrf52_base.build_src_filter} +<../variants/nrf52840/heltec_mesh_pocket> build_src_filter = ${nrf52_base.build_src_filter} +<../variants/nrf52840/heltec_mesh_pocket>
lib_deps = lib_deps =
${nrf52840_base.lib_deps} ${nrf52840_base.lib_deps}
# renovate: datasource=custom.pio depName=PCF8563 packageName=lewisxhe/library/PCF8563_Library
lewisxhe/PCF8563_Library@1.0.1
# renovate: datasource=git-refs depName=meshtastic-GxEPD2 packageName=https://github.com/meshtastic/GxEPD2 gitBranch=master # renovate: datasource=git-refs depName=meshtastic-GxEPD2 packageName=https://github.com/meshtastic/GxEPD2 gitBranch=master
https://github.com/meshtastic/GxEPD2/archive/b202ebfec6a4821e098cf7a625ba0f6f2400292d.zip https://github.com/meshtastic/GxEPD2/archive/b202ebfec6a4821e098cf7a625ba0f6f2400292d.zip
@@ -72,8 +70,6 @@ build_flags = ${nrf52840_base.build_flags}
build_src_filter = ${nrf52_base.build_src_filter} +<../variants/nrf52840/heltec_mesh_pocket> build_src_filter = ${nrf52_base.build_src_filter} +<../variants/nrf52840/heltec_mesh_pocket>
lib_deps = lib_deps =
${nrf52840_base.lib_deps} ${nrf52840_base.lib_deps}
# renovate: datasource=custom.pio depName=PCF8563 packageName=lewisxhe/library/PCF8563_Library
lewisxhe/PCF8563_Library@1.0.1
# renovate: datasource=git-refs depName=meshtastic-GxEPD2 packageName=https://github.com/meshtastic/GxEPD2 gitBranch=master # renovate: datasource=git-refs depName=meshtastic-GxEPD2 packageName=https://github.com/meshtastic/GxEPD2 gitBranch=master
https://github.com/meshtastic/GxEPD2/archive/b202ebfec6a4821e098cf7a625ba0f6f2400292d.zip https://github.com/meshtastic/GxEPD2/archive/b202ebfec6a4821e098cf7a625ba0f6f2400292d.zip

View File

@@ -26,7 +26,6 @@ extern "C" {
#define LED_RED PIN_LED1 #define LED_RED PIN_LED1
#define LED_BLUE PIN_LED1 #define LED_BLUE PIN_LED1
#define LED_GREEN PIN_LED1 #define LED_GREEN PIN_LED1
#define LED_BUILTIN LED_BLUE
#define LED_CONN LED_BLUE #define LED_CONN LED_BLUE
#define LED_STATE_ON 0 // State when LED is lit #define LED_STATE_ON 0 // State when LED is lit
@@ -130,7 +129,6 @@ No longer populated on PCB
#undef HAS_GPS #undef HAS_GPS
#define HAS_GPS 0 #define HAS_GPS 0
#define HAS_RTC 0
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@@ -15,8 +15,6 @@ lib_deps =
${nrf52840_base.lib_deps} ${nrf52840_base.lib_deps}
# renovate: datasource=git-refs depName=NMIoT-meshsolar packageName=https://github.com/NMIoT/meshsolar gitBranch=main # renovate: datasource=git-refs depName=NMIoT-meshsolar packageName=https://github.com/NMIoT/meshsolar gitBranch=main
https://github.com/NMIoT/meshsolar/archive/dfc5330dad443982e6cdd37a61d33fc7252f468b.zip https://github.com/NMIoT/meshsolar/archive/dfc5330dad443982e6cdd37a61d33fc7252f468b.zip
# renovate: datasource=custom.pio depName=PCF8563 packageName=lewisxhe/library/PCF8563_Library
lewisxhe/PCF8563_Library@1.0.1
# renovate: datasource=custom.pio depName=ArduinoJson packageName=bblanchon/library/ArduinoJson # renovate: datasource=custom.pio depName=ArduinoJson packageName=bblanchon/library/ArduinoJson
bblanchon/ArduinoJson@6.21.4 bblanchon/ArduinoJson@6.21.4

View File

@@ -42,7 +42,6 @@ extern "C" {
#define PIN_LED1 (0 + 4) // green (confirmed on 1.0 board) #define PIN_LED1 (0 + 4) // green (confirmed on 1.0 board)
#define LED_BLUE PIN_LED1 // fake for bluefruit library #define LED_BLUE PIN_LED1 // fake for bluefruit library
#define LED_GREEN PIN_LED1 #define LED_GREEN PIN_LED1
#define LED_BUILTIN LED_GREEN
#define LED_STATE_ON 0 // State when LED is lit #define LED_STATE_ON 0 // State when LED is lit
#define HAS_NEOPIXEL // Enable the use of neopixels #define HAS_NEOPIXEL // Enable the use of neopixels
@@ -142,7 +141,6 @@ No longer populated on PCB
#define BQ4050_SCL_PIN (32 + 0) // I2C clock line pin #define BQ4050_SCL_PIN (32 + 0) // I2C clock line pin
#define BQ4050_EMERGENCY_SHUTDOWN_PIN (32 + 3) // Emergency shutdown pin #define BQ4050_EMERGENCY_SHUTDOWN_PIN (32 + 3) // Emergency shutdown pin
#define HAS_RTC 0
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@@ -31,7 +31,6 @@ extern "C" {
// LEDs // LEDs
#define PIN_LED1 (24) // Built in white led for status #define PIN_LED1 (24) // Built in white led for status
#define LED_BLUE PIN_LED1 #define LED_BLUE PIN_LED1
#define LED_BUILTIN PIN_LED1
#define LED_STATE_ON 0 // State when LED is litted #define LED_STATE_ON 0 // State when LED is litted
#define LED_INVERTED 1 #define LED_INVERTED 1

View File

@@ -49,7 +49,6 @@ extern "C" {
#define PIN_LED1 (35) #define PIN_LED1 (35)
#define PIN_LED2 (36) #define PIN_LED2 (36)
#define LED_BUILTIN PIN_LED1
#define LED_CONN PIN_LED2 #define LED_CONN PIN_LED2
#define LED_GREEN PIN_LED1 #define LED_GREEN PIN_LED1

View File

@@ -52,7 +52,6 @@ extern "C" {
#define PIN_LED1 (35) #define PIN_LED1 (35)
#define PIN_LED2 (36) // Connected to WWAN host LED (if present) #define PIN_LED2 (36) // Connected to WWAN host LED (if present)
#define LED_BUILTIN PIN_LED1
#define LED_CONN PIN_LED2 #define LED_CONN PIN_LED2
#define LED_GREEN PIN_LED1 #define LED_GREEN PIN_LED1

View File

@@ -45,7 +45,6 @@ extern "C" {
#define PIN_LED1 (32 + 3) // P1.03, Green #define PIN_LED1 (32 + 3) // P1.03, Green
#define PIN_LED2 (32 + 4) // P1.04, Blue #define PIN_LED2 (32 + 4) // P1.04, Blue
#define LED_BUILTIN -1 // PIN_LED1
#define LED_BLUE PIN_LED2 #define LED_BLUE PIN_LED2
#define LED_STATE_ON 0 // State when LED is lit #define LED_STATE_ON 0 // State when LED is lit

Some files were not shown because too many files have changed in this diff Show More