mirror of
https://github.com/meshtastic/firmware.git
synced 2025-04-26 18:09:04 +00:00
Merge branch 'eink' into bug513
This commit is contained in:
commit
f346b4f0f2
BIN
docs/hardware/pinetab/SX1302/DS_SX1302_V1.0.pdf
Normal file
BIN
docs/hardware/pinetab/SX1302/DS_SX1302_V1.0.pdf
Normal file
Binary file not shown.
BIN
docs/hardware/pinetab/SX1302/M-GW1302S 用户手册(2)(1)(1).pdf
Normal file
BIN
docs/hardware/pinetab/SX1302/M-GW1302S 用户手册(2)(1)(1).pdf
Normal file
Binary file not shown.
BIN
docs/hardware/pinetab/SX1302/M-GW1302S(射频版)硬件设计手册_V1.1.pdf
Normal file
BIN
docs/hardware/pinetab/SX1302/M-GW1302S(射频版)硬件设计手册_V1.1.pdf
Normal file
Binary file not shown.
BIN
docs/hardware/pinetab/SX1302/M-GW1302(透传版)_硬件设计手册.pdf
Normal file
BIN
docs/hardware/pinetab/SX1302/M-GW1302(透传版)_硬件设计手册.pdf
Normal file
Binary file not shown.
@ -1,4 +1,5 @@
|
|||||||
#include "RedirectablePrint.h"
|
#include "RedirectablePrint.h"
|
||||||
|
#include "configuration.h"
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -10,4 +11,14 @@ void RedirectablePrint::setDestination(Print *_dest)
|
|||||||
{
|
{
|
||||||
assert(_dest);
|
assert(_dest);
|
||||||
dest = _dest;
|
dest = _dest;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t RedirectablePrint::write(uint8_t c)
|
||||||
|
{
|
||||||
|
#ifdef SEGGER_STDOUT_CH
|
||||||
|
SEGGER_RTT_PutCharSkip(SEGGER_STDOUT_CH, c);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
dest->write(c);
|
||||||
|
return 1; // We always claim one was written, rather than trusting what the serial port said (which could be zero)
|
||||||
}
|
}
|
@ -19,7 +19,7 @@ class RedirectablePrint : public Print
|
|||||||
*/
|
*/
|
||||||
void setDestination(Print *dest);
|
void setDestination(Print *dest);
|
||||||
|
|
||||||
virtual size_t write(uint8_t c) { return dest->write(c); }
|
virtual size_t write(uint8_t c);
|
||||||
};
|
};
|
||||||
|
|
||||||
class NoopPrint : public Print
|
class NoopPrint : public Print
|
||||||
|
@ -404,8 +404,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||||||
// Always include the SEGGER code on NRF52 - because useful for debugging
|
// Always include the SEGGER code on NRF52 - because useful for debugging
|
||||||
#include "SEGGER_RTT.h"
|
#include "SEGGER_RTT.h"
|
||||||
|
|
||||||
|
// The channel we send stdout data to
|
||||||
|
#define SEGGER_STDOUT_CH 0
|
||||||
|
|
||||||
// Debug printing to segger console
|
// Debug printing to segger console
|
||||||
#define SEGGER_MSG(...) SEGGER_RTT_printf(0, __VA_ARGS__)
|
#define SEGGER_MSG(...) SEGGER_RTT_printf(SEGGER_STDOUT_CH, __VA_ARGS__)
|
||||||
|
|
||||||
// If we are not on a NRF52840 (which has built in USB-ACM serial support) and we don't have serial pins hooked up, then we MUST
|
// If we are not on a NRF52840 (which has built in USB-ACM serial support) and we don't have serial pins hooked up, then we MUST
|
||||||
// use SEGGER for debug output
|
// use SEGGER for debug output
|
||||||
|
@ -85,13 +85,16 @@ static uint16_t displayWidth, displayHeight;
|
|||||||
#define SCREEN_TRANSITION_MSECS 300
|
#define SCREEN_TRANSITION_MSECS 300
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void drawBootScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
/**
|
||||||
|
* Draw the icon with extra info printed around the corners
|
||||||
|
*/
|
||||||
|
static void drawIconScreen(const char *upperMsg, OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
||||||
{
|
{
|
||||||
// draw an xbm image.
|
// draw an xbm image.
|
||||||
// Please note that everything that should be transitioned
|
// Please note that everything that should be transitioned
|
||||||
// needs to be drawn relative to x and y
|
// needs to be drawn relative to x and y
|
||||||
|
|
||||||
// draw centered left to right and centered above the one line of app text
|
// draw centered icon left to right and centered above the one line of app text
|
||||||
display->drawXbm(x + (SCREEN_WIDTH - icon_width) / 2, y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - icon_height) / 2 + 2,
|
display->drawXbm(x + (SCREEN_WIDTH - icon_width) / 2, y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - icon_height) / 2 + 2,
|
||||||
icon_width, icon_height, (const uint8_t *)icon_bits);
|
icon_width, icon_height, (const uint8_t *)icon_bits);
|
||||||
|
|
||||||
@ -101,15 +104,31 @@ static void drawBootScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int1
|
|||||||
display->drawString(x + getStringCenteredX(title), y + SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM, title);
|
display->drawString(x + getStringCenteredX(title), y + SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM, title);
|
||||||
display->setFont(FONT_SMALL);
|
display->setFont(FONT_SMALL);
|
||||||
|
|
||||||
const char *region = myRegion ? myRegion->name : NULL;
|
// Draw region in upper left
|
||||||
if (region)
|
if (upperMsg)
|
||||||
display->drawString(x + 0, y + 0, region);
|
display->drawString(x + 0, y + 0, upperMsg);
|
||||||
|
|
||||||
|
// Draw version in upper right
|
||||||
char buf[16];
|
char buf[16];
|
||||||
snprintf(buf, sizeof(buf), "%s",
|
snprintf(buf, sizeof(buf), "%s",
|
||||||
xstr(APP_VERSION)); // Note: we don't bother printing region or now, it makes the string too long
|
xstr(APP_VERSION)); // Note: we don't bother printing region or now, it makes the string too long
|
||||||
display->drawString(x + SCREEN_WIDTH - display->getStringWidth(buf), y + 0, buf);
|
display->drawString(x + SCREEN_WIDTH - display->getStringWidth(buf), y + 0, buf);
|
||||||
screen->forceDisplay();
|
screen->forceDisplay();
|
||||||
|
|
||||||
|
// FIXME - draw serial # somewhere?
|
||||||
|
}
|
||||||
|
|
||||||
|
static void drawBootScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
||||||
|
{
|
||||||
|
// Draw region in upper left
|
||||||
|
const char *region = myRegion ? myRegion->name : NULL;
|
||||||
|
drawIconScreen(region, display, state, x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Used on eink displays while in deep sleep
|
||||||
|
static void drawSleepScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
||||||
|
{
|
||||||
|
drawIconScreen("Sleeping...", display, state, x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void drawFrameBluetooth(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
static void drawFrameBluetooth(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
||||||
@ -600,6 +619,21 @@ Screen::Screen(uint8_t address, int sda, int scl) : OSThread("Screen"), cmdQueue
|
|||||||
cmdQueue.setReader(this);
|
cmdQueue.setReader(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepare the display for the unit going to the lowest power mode possible. Most screens will just
|
||||||
|
* poweroff, but eink screens will show a "I'm sleeping" graphic, possibly with a QR code
|
||||||
|
*/
|
||||||
|
void Screen::doDeepSleep()
|
||||||
|
{
|
||||||
|
#ifdef HAS_EINK
|
||||||
|
static FrameCallback sleepFrames[] = {drawSleepScreen};
|
||||||
|
static const int sleepFrameCount = sizeof(sleepFrames) / sizeof(sleepFrames[0]);
|
||||||
|
ui.setFrames(sleepFrames, sleepFrameCount);
|
||||||
|
ui.update();
|
||||||
|
#endif
|
||||||
|
setOn(false);
|
||||||
|
}
|
||||||
|
|
||||||
void Screen::handleSetOn(bool on)
|
void Screen::handleSetOn(bool on)
|
||||||
{
|
{
|
||||||
if (!useDisplay)
|
if (!useDisplay)
|
||||||
@ -636,7 +670,7 @@ void Screen::setup()
|
|||||||
displayWidth = dispdev.width();
|
displayWidth = dispdev.width();
|
||||||
displayHeight = dispdev.height();
|
displayHeight = dispdev.height();
|
||||||
|
|
||||||
ui.setTimePerTransition(SCREEN_TRANSITION_MSECS);
|
ui.setTimePerTransition(SCREEN_TRANSITION_MSECS);
|
||||||
|
|
||||||
ui.setIndicatorPosition(BOTTOM);
|
ui.setIndicatorPosition(BOTTOM);
|
||||||
// Defines where the first frame is located in the bar.
|
// Defines where the first frame is located in the bar.
|
||||||
|
@ -99,6 +99,12 @@ class Screen : public concurrency::OSThread
|
|||||||
enqueueCmd(ScreenCmd{.cmd = on ? Cmd::SET_ON : Cmd::SET_OFF});
|
enqueueCmd(ScreenCmd{.cmd = on ? Cmd::SET_ON : Cmd::SET_OFF});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepare the display for the unit going to the lowest power mode possible. Most screens will just
|
||||||
|
* poweroff, but eink screens will show a "I'm sleeping" graphic, possibly with a QR code
|
||||||
|
*/
|
||||||
|
void doDeepSleep();
|
||||||
|
|
||||||
/// Handles a button press.
|
/// Handles a button press.
|
||||||
void onPress() { enqueueCmd(ScreenCmd{.cmd = Cmd::ON_PRESS}); }
|
void onPress() { enqueueCmd(ScreenCmd{.cmd = Cmd::ON_PRESS}); }
|
||||||
|
|
||||||
|
12
src/main.cpp
12
src/main.cpp
@ -172,6 +172,10 @@ class ButtonThread : public OSThread
|
|||||||
{
|
{
|
||||||
#ifdef BUTTON_PIN
|
#ifdef BUTTON_PIN
|
||||||
userButton = OneButton(BUTTON_PIN, true, true);
|
userButton = OneButton(BUTTON_PIN, true, true);
|
||||||
|
#ifdef INPUT_PULLUP_SENSE
|
||||||
|
// Some platforms (nrf52) have a SENSE variant which allows wake from sleep - override what OneButton did
|
||||||
|
pinMode(BUTTON_PIN, INPUT_PULLUP_SENSE);
|
||||||
|
#endif
|
||||||
userButton.attachClick(userButtonPressed);
|
userButton.attachClick(userButtonPressed);
|
||||||
userButton.attachDuringLongPress(userButtonPressedLong);
|
userButton.attachDuringLongPress(userButtonPressedLong);
|
||||||
userButton.attachDoubleClick(userButtonDoublePressed);
|
userButton.attachDoubleClick(userButtonDoublePressed);
|
||||||
@ -179,6 +183,10 @@ class ButtonThread : public OSThread
|
|||||||
#endif
|
#endif
|
||||||
#ifdef BUTTON_PIN_ALT
|
#ifdef BUTTON_PIN_ALT
|
||||||
userButtonAlt = OneButton(BUTTON_PIN_ALT, true, true);
|
userButtonAlt = OneButton(BUTTON_PIN_ALT, true, true);
|
||||||
|
#ifdef INPUT_PULLUP_SENSE
|
||||||
|
// Some platforms (nrf52) have a SENSE variant which allows wake from sleep - override what OneButton did
|
||||||
|
pinMode(BUTTON_PIN_ALT, INPUT_PULLUP_SENSE);
|
||||||
|
#endif
|
||||||
userButtonAlt.attachClick(userButtonPressed);
|
userButtonAlt.attachClick(userButtonPressed);
|
||||||
userButtonAlt.attachDuringLongPress(userButtonPressedLong);
|
userButtonAlt.attachDuringLongPress(userButtonPressedLong);
|
||||||
userButtonAlt.attachDoubleClick(userButtonDoublePressed);
|
userButtonAlt.attachDoubleClick(userButtonDoublePressed);
|
||||||
@ -233,8 +241,8 @@ RadioInterface *rIf = NULL;
|
|||||||
|
|
||||||
void setup()
|
void setup()
|
||||||
{
|
{
|
||||||
#ifdef USE_SEGGER
|
#ifdef SEGGER_STDOUT_CH
|
||||||
SEGGER_RTT_ConfigUpBuffer(0, NULL, NULL, 0, SEGGER_RTT_MODE_NO_BLOCK_TRIM);
|
SEGGER_RTT_ConfigUpBuffer(SEGGER_STDOUT_CH, NULL, NULL, 1024, SEGGER_RTT_MODE_NO_BLOCK_TRIM);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Debug
|
// Debug
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
#include "NRF52Bluetooth.h"
|
#include "NRF52Bluetooth.h"
|
||||||
#include "configuration.h"
|
#include "configuration.h"
|
||||||
#include "graphics/TFTDisplay.h"
|
#include "graphics/TFTDisplay.h"
|
||||||
|
#include <SPI.h>
|
||||||
|
#include <Wire.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <ble_gap.h>
|
#include <ble_gap.h>
|
||||||
#include <memory.h>
|
#include <memory.h>
|
||||||
@ -64,7 +66,7 @@ void setBluetoothEnable(bool on)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if(nrf52Bluetooth)
|
if (nrf52Bluetooth)
|
||||||
nrf52Bluetooth->shutdown();
|
nrf52Bluetooth->shutdown();
|
||||||
}
|
}
|
||||||
bleOn = on;
|
bleOn = on;
|
||||||
@ -98,7 +100,7 @@ void nrf52Setup()
|
|||||||
|
|
||||||
#ifdef BQ25703A_ADDR
|
#ifdef BQ25703A_ADDR
|
||||||
auto *bq = new BQ25713();
|
auto *bq = new BQ25713();
|
||||||
if(!bq->setup())
|
if (!bq->setup())
|
||||||
DEBUG_MSG("ERROR! Charge controller init failed\n");
|
DEBUG_MSG("ERROR! Charge controller init failed\n");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -114,18 +116,26 @@ void nrf52Setup()
|
|||||||
|
|
||||||
void cpuDeepSleep(uint64_t msecToWake)
|
void cpuDeepSleep(uint64_t msecToWake)
|
||||||
{
|
{
|
||||||
DEBUG_MSG("FIXME: implement NRF52 deep sleep enter actions\n");
|
// FIXME, configure RTC or button press to wake us
|
||||||
// FIXME, configure RTC to wake us
|
// FIXME, power down SPI, I2C, RAMs
|
||||||
// FIXME, power down SPI, I2C, RAMs
|
Wire.end();
|
||||||
|
SPI.end();
|
||||||
|
Serial.end();
|
||||||
|
Serial1.end();
|
||||||
|
|
||||||
// FIXME, use system off mode with ram retention for key state?
|
// FIXME, use system off mode with ram retention for key state?
|
||||||
// FIXME, use non-init RAM per https://devzone.nordicsemi.com/f/nordic-q-a/48919/ram-retention-settings-with-softdevice-enabled
|
// FIXME, use non-init RAM per
|
||||||
|
// https://devzone.nordicsemi.com/f/nordic-q-a/48919/ram-retention-settings-with-softdevice-enabled
|
||||||
|
|
||||||
while(1) {
|
auto ok = sd_power_system_off();
|
||||||
delay(5000);
|
if(ok != NRF_SUCCESS) {
|
||||||
DEBUG_MSG(".");
|
DEBUG_MSG("FIXME: Ignoring soft device (EasyDMA pending?) and forcing system-off!\n");
|
||||||
}
|
NRF_POWER->SYSTEMOFF = 1;
|
||||||
|
}
|
||||||
|
|
||||||
// FIXME, after wake power up SPI, I2C, RAMs, reinit LORA
|
// The following code should not be run, because we are off
|
||||||
DEBUG_MSG("FIXME: implement NRF52 deep sleep wake actions\n");
|
while (1) {
|
||||||
|
delay(5000);
|
||||||
|
DEBUG_MSG(".");
|
||||||
|
}
|
||||||
}
|
}
|
@ -142,14 +142,14 @@ static void waitEnterSleep()
|
|||||||
|
|
||||||
void doDeepSleep(uint64_t msecToWake)
|
void doDeepSleep(uint64_t msecToWake)
|
||||||
{
|
{
|
||||||
DEBUG_MSG("Entering deep sleep for %llu seconds\n", msecToWake / 1000);
|
DEBUG_MSG("Entering deep sleep for %lu seconds\n", msecToWake / 1000);
|
||||||
|
|
||||||
// not using wifi yet, but once we are this is needed to shutoff the radio hw
|
// not using wifi yet, but once we are this is needed to shutoff the radio hw
|
||||||
// esp_wifi_stop();
|
// esp_wifi_stop();
|
||||||
waitEnterSleep();
|
waitEnterSleep();
|
||||||
notifyDeepSleep.notifyObservers(NULL);
|
notifyDeepSleep.notifyObservers(NULL);
|
||||||
|
|
||||||
screen->setOn(false); // datasheet says this will draw only 10ua
|
screen->doDeepSleep(); // datasheet says this will draw only 10ua
|
||||||
|
|
||||||
nodeDB.saveToDisk();
|
nodeDB.saveToDisk();
|
||||||
|
|
||||||
|
@ -243,7 +243,7 @@ External serial flash WP25R1635FZUIL0
|
|||||||
#define PIN_SPI_SCK (0 + 19)
|
#define PIN_SPI_SCK (0 + 19)
|
||||||
|
|
||||||
// To debug via the segger JLINK console rather than the CDC-ACM serial device
|
// To debug via the segger JLINK console rather than the CDC-ACM serial device
|
||||||
#define USE_SEGGER
|
// #define USE_SEGGER
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
@ -147,7 +147,7 @@ static const uint8_t SCK = PIN_SPI_SCK;
|
|||||||
#define SX1262_ANT_SW (32 + 10) // P1.10
|
#define SX1262_ANT_SW (32 + 10) // P1.10
|
||||||
|
|
||||||
// To debug via the segger JLINK console rather than the CDC-ACM serial device
|
// To debug via the segger JLINK console rather than the CDC-ACM serial device
|
||||||
#define USE_SEGGER
|
// #define USE_SEGGER
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
@ -168,7 +168,7 @@ static const uint8_t SCK = PIN_SPI_SCK;
|
|||||||
#define LORA_DISABLE_SENDING // Define this to disable transmission for testing (power testing etc...)
|
#define LORA_DISABLE_SENDING // Define this to disable transmission for testing (power testing etc...)
|
||||||
|
|
||||||
// To debug via the segger JLINK console rather than the CDC-ACM serial device
|
// To debug via the segger JLINK console rather than the CDC-ACM serial device
|
||||||
#define USE_SEGGER
|
// #define USE_SEGGER
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user