sforkowany z mirror/meshtastic-firmware
Merge branch 'eink' into power
commit
d66cede7fc
|
@ -0,0 +1,22 @@
|
|||
# You probably don't want to use this script, it programs a custom bootloader build onto a nrf52 board
|
||||
|
||||
set -e
|
||||
|
||||
BOOTDIR=/home/kevinh/development/meshtastic/Adafruit_nRF52_Bootloader
|
||||
|
||||
nrfjprog --eraseall -f nrf52
|
||||
|
||||
# this generates an intel hex file that can be programmed into a NRF52 to tell the adafruit bootloader that the current app image is valid
|
||||
# Bootloader settings are at BOOTLOADER_SETTINGS (rw) : ORIGIN = 0xFF000, LENGTH = 0x1000
|
||||
# first 4 bytes should be 0x01 to indicate valid app image
|
||||
# second 4 bytes should be 0x00 to indicate no CRC required for image
|
||||
echo "01 00 00 00 00 00 00 00" | xxd -r -p - >/tmp/bootconf.bin
|
||||
srec_cat /tmp/bootconf.bin -binary -offset 0xff000 -output /tmp/bootconf.hex -intel
|
||||
|
||||
echo Generating merged hex file
|
||||
mergehex -m $BOOTDIR/_build/build-ttgo_eink/ttgo_eink_bootloader-0.3.2-124-g69bd8eb-dirty_s140_6.1.1.hex .pio/build/eink/firmware.hex /tmp/bootconf.hex -o ttgo_eink_full.hex
|
||||
|
||||
echo Telling bootloader app region is valid and telling CPU to run
|
||||
nrfjprog --program ttgo_eink_full.hex -f nrf52 --reset
|
||||
|
||||
# nrfjprog --readuicr /tmp/uicr.hex; objdump -s /tmp/uicr.hex | less
|
|
@ -0,0 +1,6 @@
|
|||
# You probably don't need this - it is a basic test of the serial flash on the TTGO eink board
|
||||
|
||||
nrfjprog -qspiini nrf52/ttgo_eink_qpsi.ini --qspieraseall
|
||||
nrfjprog --qspiini nrf52/ttgo_eink_qpsi.ini --memwr 0x12000000 --val 0xdeadbeef --verify
|
||||
nrfjprog --qspiini nrf52/ttgo_eink_qpsi.ini --readqspi spi.hex
|
||||
objdump -s spi.hex | less
|
|
@ -0,0 +1,69 @@
|
|||
; nrfjprog.exe configuration file.
|
||||
|
||||
; Note: QSPI flash is mapped into memory at address 0x12000000
|
||||
|
||||
[DEFAULT_CONFIGURATION]
|
||||
; Define the capacity of the flash memory device in bytes. Set to 0 if no external memory device is present in your board.
|
||||
; MX25R1635F is 16Mbit/2Mbyte
|
||||
MemSize = 0x200000
|
||||
|
||||
; Define the desired ReadMode. Valid options are FASTREAD, READ2O, READ2IO, READ4O and READ4IO
|
||||
ReadMode = READ2IO
|
||||
|
||||
; Define the desired WriteMode. Valid options are PP, PP2O, PP4O and PP4IO
|
||||
WriteMode = PP
|
||||
|
||||
; Define the desired AddressMode. Valid options are BIT24 and BIT32
|
||||
AddressMode = BIT24
|
||||
|
||||
; Define the desired Frequency. Valid options are M2, M4, M8, M16 and M32
|
||||
Frequency = M16
|
||||
|
||||
; Define the desired SPI mode. Valid options are MODE0 and MODE3
|
||||
SpiMode = MODE0
|
||||
|
||||
; Define the desired SckDelay. Valid options are in the range 0 to 255
|
||||
SckDelay = 0x80
|
||||
|
||||
; Define the desired IO level for DIO2 and DIO3 during a custom instruction. Valid options are LEVEL_HIGH and LEVEL_LOW
|
||||
CustomInstructionIO2Level = LEVEL_LOW
|
||||
CustomInstructionIO3Level = LEVEL_HIGH
|
||||
|
||||
; Define the assigned pins for the QSPI peripheral. Valid options are those existing in your device
|
||||
CSNPin = 15
|
||||
CSNPort = 1
|
||||
SCKPin = 14
|
||||
SCKPort = 1
|
||||
DIO0Pin = 12
|
||||
DIO0Port = 1
|
||||
DIO1Pin = 13
|
||||
DIO1Port = 1
|
||||
|
||||
;These two pins are not connected, but we must name something
|
||||
DIO2Pin = 3
|
||||
DIO2Port = 1
|
||||
DIO3Pin = 5
|
||||
DIO3Port = 1
|
||||
|
||||
; Define the Index of the Write In Progress (WIP) bit in the status register. Valid options are in the range of 0 to 7.
|
||||
WIPIndex = 0
|
||||
|
||||
; Define page size for commands. Valid sizes are PAGE256 and PAGE512.
|
||||
PPSize = PAGE256
|
||||
|
||||
; Custom instructions to send to the external memory after initialization. Format is instruction code plus data to send in between optional brakets.
|
||||
; These instructions will be executed each time the qspi peripheral is initiated by nrfjprog.
|
||||
; To improve execution speed on consecutive interations with QSPI, you can run nrfjprog once with custom initialization, and then comment out the lines below.
|
||||
; Numbers can be given in decimal, hex (starting with either 0x or 0X) and binary (starting with either 0b or 0B) formats.
|
||||
; The custom instructions will be executed in the order found.
|
||||
|
||||
; This example includes two commands, first a WREN (WRite ENable) and then a WRSR (WRite Satus Register) enabling the Quad Operation and the High Performance
|
||||
; mode for the MX25R6435F memory present in the nRF52840 DK.
|
||||
;InitializationCustomInstruction = 0x06
|
||||
;InitializationCustomInstruction = 0x01, [0x40, 0, 0x2]
|
||||
|
||||
; For MX25R1635F on TTGO board, only two data lines are connected
|
||||
; This example includes two commands, first a WREN (WRite ENable) and then a WRSR (WRite Satus Register) disabling Quad Operation and the High Performance
|
||||
; mode. For normal operation you might want low power mode instead.
|
||||
InitializationCustomInstruction = 0x06
|
||||
InitializationCustomInstruction = 0x01, [0x00, 0, 0x2]
|
|
@ -77,6 +77,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#define BUTTON_PIN PIN_BUTTON1
|
||||
#endif
|
||||
|
||||
#ifdef PIN_BUTTON2
|
||||
#define BUTTON_PIN_ALT PIN_BUTTON2
|
||||
#endif
|
||||
|
||||
// FIXME, use variant.h defs for all of this!!! (even on the ESP32 targets)
|
||||
#elif defined(CubeCell_BoardPlus)
|
||||
|
||||
|
|
|
@ -0,0 +1,87 @@
|
|||
#include "Air530GPS.h"
|
||||
#include <assert.h>
|
||||
|
||||
/*
|
||||
Helpful translations from the Air530 GPS datasheet
|
||||
|
||||
Sat acquision mode
|
||||
捕获电流值@3.3v 42.6 mA
|
||||
|
||||
sat tracking mode
|
||||
跟踪电流值@3.3v 36.7 mA
|
||||
|
||||
Low power mode
|
||||
低功耗模式@3.3V 0.85 mA
|
||||
(发送指令:$PGKC051,0)
|
||||
|
||||
Super low power mode
|
||||
超低功耗模式@3.3V 31 uA
|
||||
(发送指令:$PGKC105,4)
|
||||
|
||||
To exit sleep use WAKE pin
|
||||
|
||||
Commands to enter sleep
|
||||
6、Command: 105
|
||||
进入周期性低功耗模式
|
||||
Arguments:
|
||||
|
||||
Arg1: “0”,正常运行模式 (normal mode)
|
||||
“1”,周期超低功耗跟踪模式,需要拉高 WAKE 来唤醒 (periodic low power tracking mode - keeps sat positions, use wake to wake up)
|
||||
“2”,周期低功耗模式 (periodic low power mode)
|
||||
“4”,直接进入超低功耗跟踪模式,需要拉高 WAKE 来唤醒 (super low power consumption mode immediately, need WAKE to resume)
|
||||
“8”,自动低功耗模式,可以通过串口唤醒 (automatic low power mode, wake by sending characters to serial port)
|
||||
“9”, 自动超低功耗跟踪模式,需要拉高 WAKE 来唤醒 (automatic low power tracking when possible, need wake pin to resume)
|
||||
|
||||
(Arg 2 & 3 only valid if Arg1 is "1" or "2")
|
||||
Arg2:运行时间(毫秒),在 Arg1 为 1、2 的周期模式下,此参数起作用
|
||||
ON time in msecs
|
||||
|
||||
Arg3:睡眠时间(毫秒),在 Arg1 为 1、2 的周期模式下,此参数起作用
|
||||
Sleep time in msecs
|
||||
|
||||
Example:
|
||||
$PGKC105,8*3F<CR><LF>
|
||||
This will set automatic low power mode with waking when we send chars to the serial port. Possibly do this as soon as we get a
|
||||
new location. When we wake again in a minute we send a character to wake up.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
void Air530GPS::sendCommand(const char *cmd) {
|
||||
uint8_t sum = 0;
|
||||
|
||||
// Skip the $
|
||||
assert(cmd[0] == '$');
|
||||
const char *p = cmd + 1;
|
||||
while(*p)
|
||||
sum ^= *p++;
|
||||
|
||||
assert(_serial_gps);
|
||||
|
||||
_serial_gps->write(cmd);
|
||||
_serial_gps->printf("*%02x\r\n", sum);
|
||||
|
||||
// DEBUG_MSG("xsum %02x\n", sum);
|
||||
}
|
||||
|
||||
void Air530GPS::sleep() {
|
||||
#ifdef PIN_GPS_WAKE
|
||||
digitalWrite(PIN_GPS_WAKE, 0);
|
||||
pinMode(PIN_GPS_WAKE, OUTPUT);
|
||||
sendCommand("$PGKC105,4");
|
||||
#endif
|
||||
}
|
||||
|
||||
/// wake the GPS into normal operation mode
|
||||
void Air530GPS::wake()
|
||||
{
|
||||
#if 1
|
||||
#ifdef PIN_GPS_WAKE
|
||||
digitalWrite(PIN_GPS_WAKE, 1);
|
||||
pinMode(PIN_GPS_WAKE, OUTPUT);
|
||||
#endif
|
||||
#else
|
||||
// For power testing - keep GPS sleeping forever
|
||||
sleep();
|
||||
#endif
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
#pragma once
|
||||
|
||||
#include "NMEAGPS.h"
|
||||
|
||||
/**
|
||||
* A gps class thatreads from a NMEA GPS stream (and FIXME - eventually keeps the gps powered down except when reading)
|
||||
*
|
||||
* When new data is available it will notify observers.
|
||||
*/
|
||||
class Air530GPS : public NMEAGPS
|
||||
{
|
||||
protected:
|
||||
/// If possible force the GPS into sleep/low power mode
|
||||
virtual void sleep();
|
||||
|
||||
/// wake the GPS into normal operation mode
|
||||
virtual void wake();
|
||||
|
||||
private:
|
||||
/// Send a NMEA cmd with checksum
|
||||
void sendCommand(const char *str);
|
||||
};
|
|
@ -85,3 +85,20 @@ uint32_t getValidTime()
|
|||
{
|
||||
return timeSetFromGPS ? getTime() : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Switch the GPS into a mode where we are actively looking for a lock, or alternatively switch GPS into a low power mode
|
||||
*
|
||||
* calls sleep/wake
|
||||
*/
|
||||
void GPS::setWantLocation(bool on)
|
||||
{
|
||||
if (wantNewLocation != on) {
|
||||
wantNewLocation = on;
|
||||
DEBUG_MSG("WANT GPS=%d\n", on);
|
||||
if (on)
|
||||
wake();
|
||||
else
|
||||
sleep();
|
||||
}
|
||||
}
|
|
@ -30,6 +30,8 @@ class GPS
|
|||
protected:
|
||||
bool hasValidLocation = false; // default to false, until we complete our first read
|
||||
|
||||
bool wantNewLocation = false; // true if we want a location right now
|
||||
|
||||
public:
|
||||
/** If !NULL we will use this serial port to construct our GPS */
|
||||
static HardwareSerial *_serial_gps;
|
||||
|
@ -62,10 +64,24 @@ class GPS
|
|||
/// Returns ture if we have acquired GPS lock.
|
||||
bool hasLock() const { return hasValidLocation; }
|
||||
|
||||
/**
|
||||
* Switch the GPS into a mode where we are actively looking for a lock, or alternatively switch GPS into a low power mode
|
||||
*
|
||||
* calls sleep/wake
|
||||
*/
|
||||
void setWantLocation(bool on);
|
||||
|
||||
/**
|
||||
* Restart our lock attempt - try to get and broadcast a GPS reading ASAP
|
||||
* called after the CPU wakes from light-sleep state */
|
||||
virtual void startLock() {}
|
||||
|
||||
protected:
|
||||
/// If possible force the GPS into sleep/low power mode
|
||||
virtual void sleep() {}
|
||||
|
||||
/// wake the GPS into normal operation mode
|
||||
virtual void wake() {}
|
||||
};
|
||||
|
||||
extern GPS *gps;
|
||||
|
|
|
@ -1,50 +1,6 @@
|
|||
#include "NMEAGPS.h"
|
||||
#include "configuration.h"
|
||||
|
||||
/*
|
||||
Helpful translations from the Air530 GPS datasheet
|
||||
|
||||
Sat acquision mode
|
||||
捕获电流值@3.3v 42.6 mA
|
||||
|
||||
sat tracking mode
|
||||
跟踪电流值@3.3v 36.7 mA
|
||||
|
||||
Low power mode
|
||||
低功耗模式@3.3V 0.85 mA
|
||||
(发送指令:$PGKC051,0)
|
||||
|
||||
Super low power mode
|
||||
超低功耗模式@3.3V 31 uA
|
||||
(发送指令:$PGKC105,4)
|
||||
|
||||
To exit sleep use WAKE pin
|
||||
|
||||
Commands to enter sleep
|
||||
6、Command: 105
|
||||
进入周期性低功耗模式
|
||||
Arguments:
|
||||
|
||||
Arg1: “0”,正常运行模式 (normal mode)
|
||||
“1”,周期超低功耗跟踪模式,需要拉高 WAKE 来唤醒 (periodic low power tracking mode - keeps sat positions, use wake to wake up)
|
||||
“2”,周期低功耗模式 (periodic low power mode)
|
||||
“4”,直接进入超低功耗跟踪模式,需要拉高 WAKE 来唤醒 (super low power consumption mode immediately, need WAKE to resume)
|
||||
“8”,自动低功耗模式,可以通过串口唤醒 (automatic low power mode, wake by sending characters to serial port)
|
||||
“9”, 自动超低功耗跟踪模式,需要拉高 WAKE 来唤醒 (automatic low power tracking when possible, need wake pin to resume)
|
||||
|
||||
(Arg 2 & 3 only valid if Arg1 is "1" or "2")
|
||||
Arg2:运行时间(毫秒),在 Arg1 为 1、2 的周期模式下,此参数起作用
|
||||
ON time in msecs
|
||||
|
||||
Arg3:睡眠时间(毫秒),在 Arg1 为 1、2 的周期模式下,此参数起作用
|
||||
Sleep time in msecs
|
||||
|
||||
Example:
|
||||
$PGKC105,8*3F<CR><LF>
|
||||
This will set automatic low power mode with waking when we send chars to the serial port. Possibly do this as soon as we get a new
|
||||
location. When we wake again in a minute we send a character to wake up.
|
||||
|
||||
*/
|
||||
|
||||
static int32_t toDegInt(RawDegrees d)
|
||||
{
|
||||
|
@ -68,6 +24,7 @@ bool NMEAGPS::setup()
|
|||
|
||||
void NMEAGPS::loop()
|
||||
{
|
||||
// First consume any chars that have piled up at the receiver
|
||||
while (_serial_gps->available() > 0) {
|
||||
int c = _serial_gps->read();
|
||||
// DEBUG_MSG("%c", c);
|
||||
|
@ -78,11 +35,18 @@ void NMEAGPS::loop()
|
|||
isConnected = true;
|
||||
}
|
||||
|
||||
// If we are overdue for an update, turn on the GPS and at least publish the current status
|
||||
uint32_t now = millis();
|
||||
if ((now - lastUpdateMsec) > 20 * 1000) { // Ugly hack for now - limit update checks to once every 20 secs (but still consume
|
||||
// serial chars at whatever rate)
|
||||
lastUpdateMsec = now;
|
||||
bool mustPublishUpdate = false;
|
||||
if ((now - lastUpdateMsec) > 30 * 1000 && !wantNewLocation) {
|
||||
// Ugly hack for now - limit update checks to once every 30 secs
|
||||
setWantLocation(true);
|
||||
mustPublishUpdate =
|
||||
true; // Even if we don't have an update this time, we at least want to occasionally publish the current state
|
||||
}
|
||||
|
||||
// Only bother looking at GPS state if we are interested in what it has to say
|
||||
if (wantNewLocation) {
|
||||
auto ti = reader.time;
|
||||
auto d = reader.date;
|
||||
if (ti.isUpdated() && ti.isValid() && d.isValid()) {
|
||||
|
@ -105,6 +69,8 @@ void NMEAGPS::loop()
|
|||
hasValidLocation = ((fixtype >= 1) && (fixtype <= 5));
|
||||
|
||||
if (reader.location.isUpdated()) {
|
||||
lastUpdateMsec = now;
|
||||
|
||||
if (reader.altitude.isValid())
|
||||
altitude = reader.altitude.meters();
|
||||
|
||||
|
@ -112,6 +78,9 @@ void NMEAGPS::loop()
|
|||
auto loc = reader.location.value();
|
||||
latitude = toDegInt(loc.lat);
|
||||
longitude = toDegInt(loc.lng);
|
||||
|
||||
// Once we get a location we no longer desperately want an update
|
||||
setWantLocation(false);
|
||||
}
|
||||
// Diminution of precision (an accuracy metric) is reported in 10^2 units, so we need to scale down when we use it
|
||||
if (reader.hdop.isValid()) {
|
||||
|
@ -128,11 +97,14 @@ void NMEAGPS::loop()
|
|||
// expect gps pos lat=37.520825, lon=-122.309162, alt=158
|
||||
DEBUG_MSG("new NMEA GPS pos lat=%f, lon=%f, alt=%d, hdop=%g, heading=%f\n", latitude * 1e-7, longitude * 1e-7,
|
||||
altitude, dop * 1e-2, heading * 1e-5);
|
||||
mustPublishUpdate = true;
|
||||
}
|
||||
|
||||
// Notify any status instances that are observing us
|
||||
const meshtastic::GPSStatus status =
|
||||
meshtastic::GPSStatus(hasLock(), isConnected, latitude, longitude, altitude, dop, heading, numSatellites);
|
||||
newStatus.notifyObservers(&status);
|
||||
if (mustPublishUpdate) {
|
||||
// Notify any status instances that are observing us
|
||||
const meshtastic::GPSStatus status =
|
||||
meshtastic::GPSStatus(hasLock(), isConnected, latitude, longitude, altitude, dop, heading, numSatellites);
|
||||
newStatus.notifyObservers(&status);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -183,11 +183,11 @@ void UBloxGPS::doTask()
|
|||
if ((fixtype >= 3 && fixtype <= 4) && ublox.getP(maxWait)) // rd fixes only
|
||||
{
|
||||
if (hasValidLocation) {
|
||||
wantNewLocation = false;
|
||||
setWantLocation(false);
|
||||
// ublox.powerOff();
|
||||
}
|
||||
} else // we didn't get a location update, go back to sleep and hope the characters show up
|
||||
wantNewLocation = true;
|
||||
setWantLocation(true);
|
||||
|
||||
// Notify any status instances that are observing us
|
||||
const meshtastic::GPSStatus status =
|
||||
|
|
|
@ -14,8 +14,6 @@ class UBloxGPS : public GPS, public concurrency::PeriodicTask
|
|||
{
|
||||
SFE_UBLOX_GPS ublox;
|
||||
|
||||
bool wantNewLocation = true;
|
||||
|
||||
CallbackObserver<UBloxGPS, void *> notifySleepObserver = CallbackObserver<UBloxGPS, void *>(this, &UBloxGPS::prepareSleep);
|
||||
|
||||
public:
|
||||
|
|
|
@ -56,12 +56,13 @@ uint32_t lastDrawMsec;
|
|||
// Write the buffer to the display memory
|
||||
void EInkDisplay::display(void)
|
||||
{
|
||||
concurrency::LockGuard g(spiLock);
|
||||
// No need to grab this lock because we are on our own SPI bus
|
||||
// concurrency::LockGuard g(spiLock);
|
||||
|
||||
uint32_t now = millis();
|
||||
uint32_t sinceLast = now - lastDrawMsec;
|
||||
|
||||
if (framePtr && (sinceLast > 30 * 1000 || lastDrawMsec == 0)) {
|
||||
if (framePtr && (sinceLast > 60 * 1000 || lastDrawMsec == 0)) {
|
||||
lastDrawMsec = now;
|
||||
|
||||
// FIXME - only draw bits have changed (use backbuf similar to the other displays)
|
||||
|
@ -76,10 +77,14 @@ void EInkDisplay::display(void)
|
|||
}
|
||||
}
|
||||
|
||||
updateDisplay(); // Send image to display and refresh
|
||||
ePaper.Reset(); // wake the screen from sleep
|
||||
|
||||
// Put screen to sleep to save power (if wanted)
|
||||
// ePaper.Sleep();
|
||||
DEBUG_MSG("Updating eink... ");
|
||||
updateDisplay(); // Send image to display and refresh
|
||||
DEBUG_MSG("done\n");
|
||||
|
||||
// Put screen to sleep to save power
|
||||
ePaper.Sleep();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -95,6 +100,11 @@ bool EInkDisplay::connect()
|
|||
{
|
||||
DEBUG_MSG("Doing EInk init\n");
|
||||
|
||||
#ifdef PIN_EINK_PWR_ON
|
||||
digitalWrite(PIN_EINK_PWR_ON, HIGH); // If we need to assert a pin to power external peripherals
|
||||
pinMode(PIN_EINK_PWR_ON, OUTPUT);
|
||||
#endif
|
||||
|
||||
#ifdef PIN_EINK_EN
|
||||
digitalWrite(PIN_EINK_EN, HIGH);
|
||||
pinMode(PIN_EINK_EN, OUTPUT);
|
||||
|
|
|
@ -241,16 +241,15 @@ static void drawGPS(OLEDDisplay *display, int16_t x, int16_t y, const GPSStatus
|
|||
}
|
||||
}
|
||||
|
||||
//asdf
|
||||
static void drawGPSAltitude(OLEDDisplay *display, int16_t x, int16_t y, const GPSStatus *gps)
|
||||
{
|
||||
String displayLine = "";
|
||||
if (!gps->getIsConnected()) {
|
||||
//displayLine = "No GPS Module";
|
||||
//display->drawString(x + (SCREEN_WIDTH - (display->getStringWidth(displayLine))) / 2, y, displayLine);
|
||||
// displayLine = "No GPS Module";
|
||||
// display->drawString(x + (SCREEN_WIDTH - (display->getStringWidth(displayLine))) / 2, y, displayLine);
|
||||
} else if (!gps->getHasLock()) {
|
||||
//displayLine = "No GPS Lock";
|
||||
//display->drawString(x + (SCREEN_WIDTH - (display->getStringWidth(displayLine))) / 2, y, displayLine);
|
||||
// displayLine = "No GPS Lock";
|
||||
// display->drawString(x + (SCREEN_WIDTH - (display->getStringWidth(displayLine))) / 2, y, displayLine);
|
||||
} else {
|
||||
|
||||
displayLine = "Altitude: " + String(gps->getAltitude()) + "m";
|
||||
|
@ -905,8 +904,8 @@ void DebugInfo::drawFrameWiFi(OLEDDisplay *display, OLEDDisplayUiState *state, i
|
|||
display->drawString(x, y + FONT_HEIGHT * 1, "Connection Lost");
|
||||
} else if (WiFi.status() == WL_CONNECT_FAILED) {
|
||||
display->drawString(x, y + FONT_HEIGHT * 1, "Connection Failed");
|
||||
//} else if (WiFi.status() == WL_DISCONNECTED) {
|
||||
// display->drawString(x, y + FONT_HEIGHT * 1, "Disconnected");
|
||||
//} else if (WiFi.status() == WL_DISCONNECTED) {
|
||||
// display->drawString(x, y + FONT_HEIGHT * 1, "Disconnected");
|
||||
} else if (WiFi.status() == WL_IDLE_STATUS) {
|
||||
display->drawString(x, y + FONT_HEIGHT * 1, "Idle ... Reconnecting");
|
||||
} else {
|
||||
|
@ -1009,10 +1008,8 @@ void DebugInfo::drawFrameSettings(OLEDDisplay *display, OLEDDisplayUiState *stat
|
|||
display->drawString(x, y, String("USB"));
|
||||
}
|
||||
|
||||
display->drawString(x + SCREEN_WIDTH - display->getStringWidth("Mode " + String(channelSettings.modem_config)),
|
||||
y, "Mode " + String(channelSettings.modem_config));
|
||||
|
||||
|
||||
display->drawString(x + SCREEN_WIDTH - display->getStringWidth("Mode " + String(channelSettings.modem_config)), y,
|
||||
"Mode " + String(channelSettings.modem_config));
|
||||
|
||||
// Line 2
|
||||
uint32_t currentMillis = millis();
|
||||
|
@ -1029,6 +1026,7 @@ void DebugInfo::drawFrameSettings(OLEDDisplay *display, OLEDDisplayUiState *stat
|
|||
String(days) + "d " + (hours < 10 ? "0" : "") + String(hours) + ":" + (minutes < 10 ? "0" : "") +
|
||||
String(minutes) + ":" + (seconds < 10 ? "0" : "") + String(seconds));
|
||||
|
||||
// Line 3
|
||||
drawGPSAltitude(display, x, y + FONT_HEIGHT * 2, gpsStatus);
|
||||
|
||||
// Line 4
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
|
||||
#include "MeshRadio.h"
|
||||
#include "MeshService.h"
|
||||
#include "NMEAGPS.h"
|
||||
#include "Air530GPS.h"
|
||||
#include "NodeDB.h"
|
||||
#include "PowerFSM.h"
|
||||
#include "UBloxGPS.h"
|
||||
|
@ -259,10 +259,14 @@ void setup()
|
|||
if (GPS::_serial_gps) {
|
||||
// Some boards might have only the TX line from the GPS connected, in that case, we can't configure it at all. Just
|
||||
// assume NMEA at 9600 baud.
|
||||
// dumb NMEA access only work for serial GPSes)
|
||||
DEBUG_MSG("Hoping that NMEA might work\n");
|
||||
|
||||
// dumb NMEA access only work for serial GPSes)
|
||||
#ifdef HAS_AIR530_GPS
|
||||
gps = new Air530GPS();
|
||||
#else
|
||||
gps = new NMEAGPS();
|
||||
#endif
|
||||
gps->setup();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -162,6 +162,11 @@ void RadioInterface::applyModemConfig()
|
|||
|
||||
DEBUG_MSG("Set radio: name=%s, config=%u, ch=%d, power=%d\n", channelSettings.name, channelSettings.modem_config, channel_num,
|
||||
power);
|
||||
DEBUG_MSG("Radio myRegion->freq: %f\n", myRegion->freq);
|
||||
DEBUG_MSG("Radio myRegion->spacing: %f\n", myRegion->spacing);
|
||||
DEBUG_MSG("Radio myRegion->numChannels: %d\n", myRegion->numChannels);
|
||||
DEBUG_MSG("Radio channel_num: %d\n", channel_num);
|
||||
DEBUG_MSG("Radio frequency: %f\n", freq);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -25,8 +25,8 @@ bool isWifiAvailable()
|
|||
const char *wifiName = radioConfig.preferences.wifi_ssid;
|
||||
const char *wifiPsw = radioConfig.preferences.wifi_password;
|
||||
|
||||
//strcpy(radioConfig.preferences.wifi_ssid, "");
|
||||
//strcpy(radioConfig.preferences.wifi_password, "");
|
||||
// strcpy(radioConfig.preferences.wifi_ssid, "");
|
||||
// strcpy(radioConfig.preferences.wifi_password, "");
|
||||
|
||||
if (*wifiName && *wifiPsw) {
|
||||
|
||||
|
|
|
@ -93,11 +93,6 @@ void nrf52Setup()
|
|||
// This is the recommended setting for Monitor Mode Debugging
|
||||
NVIC_SetPriority(DebugMonitor_IRQn, 6UL);
|
||||
|
||||
#ifdef PIN_PWR_ON
|
||||
digitalWrite(PIN_PWR_ON, HIGH); // If we need to assert a pin to power external peripherals
|
||||
pinMode(PIN_PWR_ON, OUTPUT);
|
||||
#endif
|
||||
|
||||
// Not yet on board
|
||||
// pmu.init();
|
||||
|
||||
|
|
|
@ -27,25 +27,59 @@
|
|||
/*
|
||||
@geeksville eink TODO:
|
||||
|
||||
confirm that watchdog reset (i.e. all pins now become inputs) won't cause the board to power down when we are not connected to USB
|
||||
(I bet it will). If this happens recommended fix is to add an external pullup on PWR_ON GPIO.
|
||||
|
||||
fix bootloader to use two buttons - remove bootloader hacks
|
||||
fix battery voltage sensing
|
||||
fix floating point SEGGER printf on nrf52 - see "new NMEA GPS pos"
|
||||
get second button working in app load
|
||||
if battery falls too low deassert PWR_ON (to force board to shutdown)
|
||||
soonish:
|
||||
DONE hook cdc acm device to debug output
|
||||
DONE fix bootloader to use two buttons - remove bootloader hacks
|
||||
DONE get second button working in app load
|
||||
DONE use tp_ser_io as a button, it goes high when pressed unify eink display classes
|
||||
fix display width and height
|
||||
clean up eink drawing to not have the nasty timeout hack
|
||||
put eink to sleep when we think the screen is off
|
||||
enable flash on spi0, share chip selects on spi1.
|
||||
https://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.nrf52832.ps.v1.1%2Fspi.html enable reset as a button in
|
||||
bootloader fix battery pin usage drive TCXO DIO3 enable high whenever we want the clock use PIN_GPS_WAKE to sleep the GPS use
|
||||
tp_ser_io as a button, it goes high when pressed unify eink display classes
|
||||
make screen.adjustBrightness() a nop on eink screens
|
||||
measure current draws
|
||||
DONE put eink to sleep when we think the screen is off
|
||||
enable gps sleep mode
|
||||
use new flash chip
|
||||
turn off txco on lora?
|
||||
make screen.adjustBrightness() a nop on eink screens
|
||||
|
||||
later:
|
||||
enable flash on qspi.
|
||||
fix floating point SEGGER printf on nrf52 - see "new NMEA GPS pos"
|
||||
add factory/power on self test
|
||||
|
||||
feedback to give:
|
||||
|
||||
* bootloader is finished
|
||||
|
||||
* the capacitive touch sensor works, though I'm not sure what use you are intending for it
|
||||
|
||||
* remove ipx connector for nfc, instead use two caps and loop traces on the back of the board as an antenna?
|
||||
|
||||
* the i2c RTC seems to talk fine on the i2c bus. However, I'm not sure of the utility of that part. Instead I'd be in favor of
|
||||
the following:
|
||||
|
||||
* move BAT1 to power the GPS VBACKUP instead per page 6 of the Air530 datasheet. And remove the i2c RTC entirely.
|
||||
|
||||
* remove the cp2014 chip.
|
||||
|
||||
* I've made the serial flash chip work, but if you do a new spin of the board I recommend:
|
||||
connect pin 3 and pin 7 of U4 to spare GPIOs on the processor (instead of their current connections),
|
||||
This would allow using 4 bit wide interface mode to the serial flash - doubling the transfer speed! see example here:
|
||||
https://infocenter.nordicsemi.com/topic/ug_nrf52840_dk/UG/nrf52840_DK/hw_external_memory.html?cp=4_0_4_7_4
|
||||
Once again - I'm glad you added that external flash chip.
|
||||
|
||||
* Power measurements
|
||||
When powered by 4V battery
|
||||
|
||||
CPU on, lora radio RX mode, bluetooth enabled, GPS trying to lock. total draw 43mA
|
||||
CPU on, lora radio RX mode, bluetooth enabled, GPS super low power sleep mode. Total draw 20mA
|
||||
CPU on, lora radio TX mode, bluetooth enabled, GPS super low power sleep mode. Total draw 132mA
|
||||
|
||||
Note: power consumption while connected via BLE to a phone almost identical.
|
||||
|
||||
Note: eink display for all tests was in sleep mode most of the time. Current draw during the brief periods while the eink was being drawn was not
|
||||
measured (but it was low).
|
||||
|
||||
Note: Turning off EINK PWR_ON produces no noticeable power savings over just putting the eink display into sleep mode.
|
||||
|
||||
*/
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
|
@ -83,6 +117,7 @@ extern "C" {
|
|||
* Buttons
|
||||
*/
|
||||
#define PIN_BUTTON1 (32 + 10)
|
||||
#define PIN_BUTTON2 (0 + 18) // 0.18 is labeled on the board as RESET but we configure it in the bootloader as a regular GPIO
|
||||
|
||||
/*
|
||||
* Analog pins
|
||||
|
@ -103,11 +138,10 @@ static const uint8_t A0 = PIN_A0;
|
|||
*/
|
||||
|
||||
/*
|
||||
This serial port is _also_ connected to the incoming D+/D- pins from the USB header. FIXME, figure out how that is supposed to
|
||||
work.
|
||||
No longer populated on PCB
|
||||
*/
|
||||
#define PIN_SERIAL2_RX (0 + 6)
|
||||
#define PIN_SERIAL2_TX (0 + 8)
|
||||
//#define PIN_SERIAL2_RX (0 + 6)
|
||||
//#define PIN_SERIAL2_TX (0 + 8)
|
||||
// #define PIN_SERIAL2_EN (0 + 17)
|
||||
|
||||
/**
|
||||
|
@ -122,29 +156,24 @@ work.
|
|||
|
||||
#define TP_SER_IO (0 + 11)
|
||||
|
||||
// Board power is enabled either by VBUS from USB or the CPU asserting PWR_ON
|
||||
#define PIN_PWR_ON (0 + 12)
|
||||
|
||||
#define PIN_RTC_INT (0 + 16) // Interrupt from the PCF8563 RTC
|
||||
|
||||
/*
|
||||
|
||||
FIXME define/FIX flash access
|
||||
External serial flash WP25R1635FZUIL0
|
||||
*/
|
||||
|
||||
// QSPI Pins
|
||||
#define PIN_QSPI_SCK 19
|
||||
#define PIN_QSPI_CS 17
|
||||
#define PIN_QSPI_IO0 20
|
||||
#define PIN_QSPI_IO1 21
|
||||
#define PIN_QSPI_IO2 22
|
||||
#define PIN_QSPI_IO3 23
|
||||
#define PIN_QSPI_SCK (32 + 14)
|
||||
#define PIN_QSPI_CS (32 + 15)
|
||||
#define PIN_QSPI_IO0 (32 + 12) // MOSI if using two bit interface
|
||||
#define PIN_QSPI_IO1 (32 + 13) // MISO if using two bit interface
|
||||
//#define PIN_QSPI_IO2 22 // WP if using two bit interface (i.e. not used)
|
||||
//#define PIN_QSPI_IO3 23 // HOLD if using two bit interface (i.e. not used)
|
||||
|
||||
// On-board QSPI Flash
|
||||
#define EXTERNAL_FLASH_DEVICES MX25R6435F
|
||||
#define EXTERNAL_FLASH_DEVICES MX25R1635F
|
||||
#define EXTERNAL_FLASH_USE_QSPI
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
* Lora radio
|
||||
*/
|
||||
|
@ -175,6 +204,9 @@ FIXME define/FIX flash access
|
|||
#define PIN_EINK_SCLK (0 + 31)
|
||||
#define PIN_EINK_MOSI (0 + 29) // also called SDI
|
||||
|
||||
// Controls power for the eink display - Board power is enabled either by VBUS from USB or the CPU asserting PWR_ON
|
||||
#define PIN_EINK_PWR_ON (0 + 12)
|
||||
|
||||
#define HAS_EINK
|
||||
|
||||
#define PIN_SPI1_MISO \
|
||||
|
@ -186,10 +218,12 @@ FIXME define/FIX flash access
|
|||
* Air530 GPS pins
|
||||
*/
|
||||
|
||||
#define PIN_GPS_WAKE (32 + 2)
|
||||
#define PIN_GPS_PPS (32 + 4)
|
||||
#define PIN_GPS_TX (32 + 9) // This is for bits going TOWARDS the CPU
|
||||
#define PIN_GPS_RX (32 + 8) // This is for bits going TOWARDS the GPS
|
||||
#define PIN_GPS_WAKE (32 + 2) // An output to wake GPS, low means allow sleep, high means force wake
|
||||
#define PIN_GPS_PPS (32 + 4) // Pulse per second input from the GPS
|
||||
#define PIN_GPS_TX (32 + 9) // This is for bits going TOWARDS the CPU
|
||||
#define PIN_GPS_RX (32 + 8) // This is for bits going TOWARDS the GPS
|
||||
|
||||
#define HAS_AIR530_GPS
|
||||
|
||||
#define PIN_SERIAL1_RX PIN_GPS_TX
|
||||
#define PIN_SERIAL1_TX PIN_GPS_RX
|
||||
|
@ -199,7 +233,7 @@ FIXME define/FIX flash access
|
|||
*/
|
||||
#define SPI_INTERFACES_COUNT 2
|
||||
|
||||
// For LORA
|
||||
// For LORA, spi 0
|
||||
#define PIN_SPI_MISO (0 + 23)
|
||||
#define PIN_SPI_MOSI (0 + 22)
|
||||
#define PIN_SPI_SCK (0 + 19)
|
||||
|
|
Ładowanie…
Reference in New Issue