mirror of
https://github.com/meshtastic/firmware.git
synced 2025-12-22 10:42:49 +00:00
Compare commits
9 Commits
sfpp
...
kill-led-b
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e0a720d667 | ||
|
|
5a3855b208 | ||
|
|
8fdba1f1e2 | ||
|
|
db64a5b51e | ||
|
|
3371d3372c | ||
|
|
a14505cafa | ||
|
|
2ae409ff8b | ||
|
|
e500ae6415 | ||
|
|
8fb0365833 |
13
.github/workflows/build_firmware.yml
vendored
13
.github/workflows/build_firmware.yml
vendored
@@ -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
|
||||||
|
|||||||
34
.github/workflows/main_matrix.yml
vendored
34
.github/workflows/main_matrix.yml
vendored
@@ -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
95
bin/shame.py
Normal 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)
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -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 */
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -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
|
||||||
@@ -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,
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|
||||||
|
|||||||
523
src/graphics/niche/Inputs/TwoButtonExtended.cpp
Normal file
523
src/graphics/niche/Inputs/TwoButtonExtended.cpp
Normal 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(¬ifyLightSleep);
|
||||||
|
lsEndObserver.observe(¬ifyLightSleepEnd);
|
||||||
|
#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
|
||||||
136
src/graphics/niche/Inputs/TwoButtonExtended.h
Normal file
136
src/graphics/niche/Inputs/TwoButtonExtended.h
Normal 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
|
||||||
@@ -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;
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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]
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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]
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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]
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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]
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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 */
|
||||||
|
|||||||
@@ -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 */
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
Reference in New Issue
Block a user