Merge branch 'eink' into power

1.2-legacy
geeksville 2020-10-01 07:51:01 -07:00
commit d66cede7fc
18 zmienionych plików z 378 dodań i 119 usunięć

Wyświetl plik

@ -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

Wyświetl plik

@ -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

Wyświetl plik

@ -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]

Wyświetl plik

@ -77,6 +77,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define BUTTON_PIN PIN_BUTTON1 #define BUTTON_PIN PIN_BUTTON1
#endif #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) // FIXME, use variant.h defs for all of this!!! (even on the ESP32 targets)
#elif defined(CubeCell_BoardPlus) #elif defined(CubeCell_BoardPlus)

Wyświetl plik

@ -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
6Command: 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 12 ,
ON time in msecs
Arg3:(), Arg1 12 ,
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
}

Wyświetl plik

@ -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);
};

Wyświetl plik

@ -85,3 +85,20 @@ uint32_t getValidTime()
{ {
return timeSetFromGPS ? getTime() : 0; 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();
}
}

Wyświetl plik

@ -30,6 +30,8 @@ class GPS
protected: protected:
bool hasValidLocation = false; // default to false, until we complete our first read bool hasValidLocation = false; // default to false, until we complete our first read
bool wantNewLocation = false; // true if we want a location right now
public: public:
/** If !NULL we will use this serial port to construct our GPS */ /** If !NULL we will use this serial port to construct our GPS */
static HardwareSerial *_serial_gps; static HardwareSerial *_serial_gps;
@ -62,10 +64,24 @@ class GPS
/// Returns ture if we have acquired GPS lock. /// Returns ture if we have acquired GPS lock.
bool hasLock() const { return hasValidLocation; } 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 * Restart our lock attempt - try to get and broadcast a GPS reading ASAP
* called after the CPU wakes from light-sleep state */ * called after the CPU wakes from light-sleep state */
virtual void startLock() {} 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; extern GPS *gps;

Wyświetl plik

@ -1,50 +1,6 @@
#include "NMEAGPS.h" #include "NMEAGPS.h"
#include "configuration.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
6Command: 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 12 ,
ON time in msecs
Arg3:(), Arg1 12 ,
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) static int32_t toDegInt(RawDegrees d)
{ {
@ -68,6 +24,7 @@ bool NMEAGPS::setup()
void NMEAGPS::loop() void NMEAGPS::loop()
{ {
// First consume any chars that have piled up at the receiver
while (_serial_gps->available() > 0) { while (_serial_gps->available() > 0) {
int c = _serial_gps->read(); int c = _serial_gps->read();
// DEBUG_MSG("%c", c); // DEBUG_MSG("%c", c);
@ -78,11 +35,18 @@ void NMEAGPS::loop()
isConnected = true; isConnected = true;
} }
// If we are overdue for an update, turn on the GPS and at least publish the current status
uint32_t now = millis(); uint32_t now = millis();
if ((now - lastUpdateMsec) > 20 * 1000) { // Ugly hack for now - limit update checks to once every 20 secs (but still consume bool mustPublishUpdate = false;
// serial chars at whatever rate) if ((now - lastUpdateMsec) > 30 * 1000 && !wantNewLocation) {
lastUpdateMsec = now; // 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 ti = reader.time;
auto d = reader.date; auto d = reader.date;
if (ti.isUpdated() && ti.isValid() && d.isValid()) { if (ti.isUpdated() && ti.isValid() && d.isValid()) {
@ -105,6 +69,8 @@ void NMEAGPS::loop()
hasValidLocation = ((fixtype >= 1) && (fixtype <= 5)); hasValidLocation = ((fixtype >= 1) && (fixtype <= 5));
if (reader.location.isUpdated()) { if (reader.location.isUpdated()) {
lastUpdateMsec = now;
if (reader.altitude.isValid()) if (reader.altitude.isValid())
altitude = reader.altitude.meters(); altitude = reader.altitude.meters();
@ -112,6 +78,9 @@ void NMEAGPS::loop()
auto loc = reader.location.value(); auto loc = reader.location.value();
latitude = toDegInt(loc.lat); latitude = toDegInt(loc.lat);
longitude = toDegInt(loc.lng); 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 // 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()) { if (reader.hdop.isValid()) {
@ -128,11 +97,14 @@ void NMEAGPS::loop()
// expect gps pos lat=37.520825, lon=-122.309162, alt=158 // 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, 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); altitude, dop * 1e-2, heading * 1e-5);
mustPublishUpdate = true;
} }
if (mustPublishUpdate) {
// Notify any status instances that are observing us // Notify any status instances that are observing us
const meshtastic::GPSStatus status = const meshtastic::GPSStatus status =
meshtastic::GPSStatus(hasLock(), isConnected, latitude, longitude, altitude, dop, heading, numSatellites); meshtastic::GPSStatus(hasLock(), isConnected, latitude, longitude, altitude, dop, heading, numSatellites);
newStatus.notifyObservers(&status); newStatus.notifyObservers(&status);
} }
}
} }

Wyświetl plik

@ -183,11 +183,11 @@ void UBloxGPS::doTask()
if ((fixtype >= 3 && fixtype <= 4) && ublox.getP(maxWait)) // rd fixes only if ((fixtype >= 3 && fixtype <= 4) && ublox.getP(maxWait)) // rd fixes only
{ {
if (hasValidLocation) { if (hasValidLocation) {
wantNewLocation = false; setWantLocation(false);
// ublox.powerOff(); // ublox.powerOff();
} }
} else // we didn't get a location update, go back to sleep and hope the characters show up } 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 // Notify any status instances that are observing us
const meshtastic::GPSStatus status = const meshtastic::GPSStatus status =

Wyświetl plik

@ -14,8 +14,6 @@ class UBloxGPS : public GPS, public concurrency::PeriodicTask
{ {
SFE_UBLOX_GPS ublox; SFE_UBLOX_GPS ublox;
bool wantNewLocation = true;
CallbackObserver<UBloxGPS, void *> notifySleepObserver = CallbackObserver<UBloxGPS, void *>(this, &UBloxGPS::prepareSleep); CallbackObserver<UBloxGPS, void *> notifySleepObserver = CallbackObserver<UBloxGPS, void *>(this, &UBloxGPS::prepareSleep);
public: public:

Wyświetl plik

@ -56,12 +56,13 @@ uint32_t lastDrawMsec;
// Write the buffer to the display memory // Write the buffer to the display memory
void EInkDisplay::display(void) 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 now = millis();
uint32_t sinceLast = now - lastDrawMsec; uint32_t sinceLast = now - lastDrawMsec;
if (framePtr && (sinceLast > 30 * 1000 || lastDrawMsec == 0)) { if (framePtr && (sinceLast > 60 * 1000 || lastDrawMsec == 0)) {
lastDrawMsec = now; lastDrawMsec = now;
// FIXME - only draw bits have changed (use backbuf similar to the other displays) // 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) DEBUG_MSG("Updating eink... ");
// ePaper.Sleep(); 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"); 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 #ifdef PIN_EINK_EN
digitalWrite(PIN_EINK_EN, HIGH); digitalWrite(PIN_EINK_EN, HIGH);
pinMode(PIN_EINK_EN, OUTPUT); pinMode(PIN_EINK_EN, OUTPUT);

Wyświetl plik

@ -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) static void drawGPSAltitude(OLEDDisplay *display, int16_t x, int16_t y, const GPSStatus *gps)
{ {
String displayLine = ""; String displayLine = "";
if (!gps->getIsConnected()) { if (!gps->getIsConnected()) {
//displayLine = "No GPS Module"; // displayLine = "No GPS Module";
//display->drawString(x + (SCREEN_WIDTH - (display->getStringWidth(displayLine))) / 2, y, displayLine); // display->drawString(x + (SCREEN_WIDTH - (display->getStringWidth(displayLine))) / 2, y, displayLine);
} else if (!gps->getHasLock()) { } else if (!gps->getHasLock()) {
//displayLine = "No GPS Lock"; // displayLine = "No GPS Lock";
//display->drawString(x + (SCREEN_WIDTH - (display->getStringWidth(displayLine))) / 2, y, displayLine); // display->drawString(x + (SCREEN_WIDTH - (display->getStringWidth(displayLine))) / 2, y, displayLine);
} else { } else {
displayLine = "Altitude: " + String(gps->getAltitude()) + "m"; displayLine = "Altitude: " + String(gps->getAltitude()) + "m";
@ -1009,10 +1008,8 @@ void DebugInfo::drawFrameSettings(OLEDDisplay *display, OLEDDisplayUiState *stat
display->drawString(x, y, String("USB")); display->drawString(x, y, String("USB"));
} }
display->drawString(x + SCREEN_WIDTH - display->getStringWidth("Mode " + String(channelSettings.modem_config)), display->drawString(x + SCREEN_WIDTH - display->getStringWidth("Mode " + String(channelSettings.modem_config)), y,
y, "Mode " + String(channelSettings.modem_config)); "Mode " + String(channelSettings.modem_config));
// Line 2 // Line 2
uint32_t currentMillis = millis(); 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(days) + "d " + (hours < 10 ? "0" : "") + String(hours) + ":" + (minutes < 10 ? "0" : "") +
String(minutes) + ":" + (seconds < 10 ? "0" : "") + String(seconds)); String(minutes) + ":" + (seconds < 10 ? "0" : "") + String(seconds));
// Line 3
drawGPSAltitude(display, x, y + FONT_HEIGHT * 2, gpsStatus); drawGPSAltitude(display, x, y + FONT_HEIGHT * 2, gpsStatus);
// Line 4 // Line 4

Wyświetl plik

@ -23,7 +23,7 @@
#include "MeshRadio.h" #include "MeshRadio.h"
#include "MeshService.h" #include "MeshService.h"
#include "NMEAGPS.h" #include "Air530GPS.h"
#include "NodeDB.h" #include "NodeDB.h"
#include "PowerFSM.h" #include "PowerFSM.h"
#include "UBloxGPS.h" #include "UBloxGPS.h"
@ -259,10 +259,14 @@ void setup()
if (GPS::_serial_gps) { 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 // 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. // assume NMEA at 9600 baud.
// dumb NMEA access only work for serial GPSes)
DEBUG_MSG("Hoping that NMEA might work\n"); 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(); gps = new NMEAGPS();
#endif
gps->setup(); gps->setup();
} }
} }

Wyświetl plik

@ -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, DEBUG_MSG("Set radio: name=%s, config=%u, ch=%d, power=%d\n", channelSettings.name, channelSettings.modem_config, channel_num,
power); 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);
} }
/** /**

Wyświetl plik

@ -25,8 +25,8 @@ bool isWifiAvailable()
const char *wifiName = radioConfig.preferences.wifi_ssid; const char *wifiName = radioConfig.preferences.wifi_ssid;
const char *wifiPsw = radioConfig.preferences.wifi_password; const char *wifiPsw = radioConfig.preferences.wifi_password;
//strcpy(radioConfig.preferences.wifi_ssid, ""); // strcpy(radioConfig.preferences.wifi_ssid, "");
//strcpy(radioConfig.preferences.wifi_password, ""); // strcpy(radioConfig.preferences.wifi_password, "");
if (*wifiName && *wifiPsw) { if (*wifiName && *wifiPsw) {

Wyświetl plik

@ -93,11 +93,6 @@ void nrf52Setup()
// This is the recommended setting for Monitor Mode Debugging // This is the recommended setting for Monitor Mode Debugging
NVIC_SetPriority(DebugMonitor_IRQn, 6UL); 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 // Not yet on board
// pmu.init(); // pmu.init();

Wyświetl plik

@ -27,25 +27,59 @@
/* /*
@geeksville eink TODO: @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 soonish:
(I bet it will). If this happens recommended fix is to add an external pullup on PWR_ON GPIO. DONE hook cdc acm device to debug output
DONE fix bootloader to use two buttons - remove bootloader hacks
fix bootloader to use two buttons - remove bootloader hacks DONE get second button working in app load
fix battery voltage sensing DONE use tp_ser_io as a button, it goes high when pressed unify eink display classes
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)
fix display width and height fix display width and height
clean up eink drawing to not have the nasty timeout hack clean up eink drawing to not have the nasty timeout hack
put eink to sleep when we think the screen is off measure current draws
enable flash on spi0, share chip selects on spi1. DONE put eink to sleep when we think the screen is off
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
enable gps sleep mode 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 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 * Buttons
*/ */
#define PIN_BUTTON1 (32 + 10) #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 * 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 No longer populated on PCB
work.
*/ */
#define PIN_SERIAL2_RX (0 + 6) //#define PIN_SERIAL2_RX (0 + 6)
#define PIN_SERIAL2_TX (0 + 8) //#define PIN_SERIAL2_TX (0 + 8)
// #define PIN_SERIAL2_EN (0 + 17) // #define PIN_SERIAL2_EN (0 + 17)
/** /**
@ -122,29 +156,24 @@ work.
#define TP_SER_IO (0 + 11) #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 #define PIN_RTC_INT (0 + 16) // Interrupt from the PCF8563 RTC
/* /*
External serial flash WP25R1635FZUIL0
FIXME define/FIX flash access */
// QSPI Pins // QSPI Pins
#define PIN_QSPI_SCK 19 #define PIN_QSPI_SCK (32 + 14)
#define PIN_QSPI_CS 17 #define PIN_QSPI_CS (32 + 15)
#define PIN_QSPI_IO0 20 #define PIN_QSPI_IO0 (32 + 12) // MOSI if using two bit interface
#define PIN_QSPI_IO1 21 #define PIN_QSPI_IO1 (32 + 13) // MISO if using two bit interface
#define PIN_QSPI_IO2 22 //#define PIN_QSPI_IO2 22 // WP if using two bit interface (i.e. not used)
#define PIN_QSPI_IO3 23 //#define PIN_QSPI_IO3 23 // HOLD if using two bit interface (i.e. not used)
// On-board QSPI Flash // On-board QSPI Flash
#define EXTERNAL_FLASH_DEVICES MX25R6435F #define EXTERNAL_FLASH_DEVICES MX25R1635F
#define EXTERNAL_FLASH_USE_QSPI #define EXTERNAL_FLASH_USE_QSPI
*/
/* /*
* Lora radio * Lora radio
*/ */
@ -175,6 +204,9 @@ FIXME define/FIX flash access
#define PIN_EINK_SCLK (0 + 31) #define PIN_EINK_SCLK (0 + 31)
#define PIN_EINK_MOSI (0 + 29) // also called SDI #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 HAS_EINK
#define PIN_SPI1_MISO \ #define PIN_SPI1_MISO \
@ -186,11 +218,13 @@ FIXME define/FIX flash access
* Air530 GPS pins * Air530 GPS pins
*/ */
#define PIN_GPS_WAKE (32 + 2) #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) #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_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_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_RX PIN_GPS_TX
#define PIN_SERIAL1_TX PIN_GPS_RX #define PIN_SERIAL1_TX PIN_GPS_RX
@ -199,7 +233,7 @@ FIXME define/FIX flash access
*/ */
#define SPI_INTERFACES_COUNT 2 #define SPI_INTERFACES_COUNT 2
// For LORA // For LORA, spi 0
#define PIN_SPI_MISO (0 + 23) #define PIN_SPI_MISO (0 + 23)
#define PIN_SPI_MOSI (0 + 22) #define PIN_SPI_MOSI (0 + 22)
#define PIN_SPI_SCK (0 + 19) #define PIN_SPI_SCK (0 + 19)