diff --git a/README.md b/README.md index 6017774620..6663c4d27b 100644 --- a/README.md +++ b/README.md @@ -103,10 +103,10 @@ Hard resetting via RTS pin... ``` 5. cd into the directory where the release zip file was expanded. -6. Install the correct firmware for your board with `device-install.sh firmware-_board_-_country_.bin`. - - Example: `./device-install.sh firmware-HELTEC-US-0.0.3.bin`. -7. To update run `device-update.sh firmware-_board_-_country_.bin` - - Example: `./device-update.sh firmware-HELTEC-US-0.0.3.bin`. +6. Install the correct firmware for your board with `device-install.sh -f firmware-_board_-_country_.bin`. + - Example: `./device-install.sh -f firmware-HELTEC-US-0.0.3.bin`. +7. To update run `device-update.sh -f firmware-_board_-_country_.bin` + - Example: `./device-update.sh -f firmware-HELTEC-US-0.0.3.bin`. Note: If you have previously installed meshtastic, you don't need to run this full script instead just run `esptool.py --baud 921600 write_flash 0x10000 firmware-_board_-_country_-_version_.bin`. This will be faster, also all of your current preferences will be preserved. diff --git a/bin/install-bootloader.sh b/bin/install-bootloader.sh new file mode 100755 index 0000000000..5dde70505b --- /dev/null +++ b/bin/install-bootloader.sh @@ -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 diff --git a/bin/qspi-flash-test.sh b/bin/qspi-flash-test.sh new file mode 100755 index 0000000000..7fc186b5d3 --- /dev/null +++ b/bin/qspi-flash-test.sh @@ -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 diff --git a/nrf52/ttgo_eink_qpsi.ini b/nrf52/ttgo_eink_qpsi.ini new file mode 100644 index 0000000000..d477db8ef7 --- /dev/null +++ b/nrf52/ttgo_eink_qpsi.ini @@ -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] diff --git a/src/configuration.h b/src/configuration.h index 026bb1880c..ad783d0d5c 100644 --- a/src/configuration.h +++ b/src/configuration.h @@ -77,6 +77,10 @@ along with this program. If not, see . #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) diff --git a/src/gps/Air530GPS.cpp b/src/gps/Air530GPS.cpp new file mode 100644 index 0000000000..db0ddd445c --- /dev/null +++ b/src/gps/Air530GPS.cpp @@ -0,0 +1,87 @@ +#include "Air530GPS.h" +#include + +/* +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 +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 +} \ No newline at end of file diff --git a/src/gps/Air530GPS.h b/src/gps/Air530GPS.h new file mode 100644 index 0000000000..bbb9f80038 --- /dev/null +++ b/src/gps/Air530GPS.h @@ -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); +}; diff --git a/src/gps/GPS.cpp b/src/gps/GPS.cpp index b3ab28d290..f8b29de3dc 100644 --- a/src/gps/GPS.cpp +++ b/src/gps/GPS.cpp @@ -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(); + } +} \ No newline at end of file diff --git a/src/gps/GPS.h b/src/gps/GPS.h index 409c6da9db..3b81b54f7e 100644 --- a/src/gps/GPS.h +++ b/src/gps/GPS.h @@ -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; diff --git a/src/gps/NMEAGPS.cpp b/src/gps/NMEAGPS.cpp index 08918d6d85..2d8af6d72a 100644 --- a/src/gps/NMEAGPS.cpp +++ b/src/gps/NMEAGPS.cpp @@ -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 -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); + } } } \ No newline at end of file diff --git a/src/gps/UBloxGPS.cpp b/src/gps/UBloxGPS.cpp index 93e8a01cfe..0d133891e2 100644 --- a/src/gps/UBloxGPS.cpp +++ b/src/gps/UBloxGPS.cpp @@ -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 = diff --git a/src/gps/UBloxGPS.h b/src/gps/UBloxGPS.h index 7a2d3cdba3..03f2d2a1c0 100644 --- a/src/gps/UBloxGPS.h +++ b/src/gps/UBloxGPS.h @@ -14,8 +14,6 @@ class UBloxGPS : public GPS, public concurrency::PeriodicTask { SFE_UBLOX_GPS ublox; - bool wantNewLocation = true; - CallbackObserver notifySleepObserver = CallbackObserver(this, &UBloxGPS::prepareSleep); public: diff --git a/src/graphics/EInkDisplay.cpp b/src/graphics/EInkDisplay.cpp index 2156f59190..7a6e02df0d 100644 --- a/src/graphics/EInkDisplay.cpp +++ b/src/graphics/EInkDisplay.cpp @@ -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) } } + ePaper.Reset(); // wake the screen from sleep + + DEBUG_MSG("Updating eink... "); updateDisplay(); // Send image to display and refresh + DEBUG_MSG("done\n"); - // Put screen to sleep to save power (if wanted) - // ePaper.Sleep(); + // 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); diff --git a/src/main.cpp b/src/main.cpp index c53fdfeffe..37e9077df5 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -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(); } } diff --git a/src/nrf52/main-nrf52.cpp b/src/nrf52/main-nrf52.cpp index 4a5c93f75f..867cdeefcc 100644 --- a/src/nrf52/main-nrf52.cpp +++ b/src/nrf52/main-nrf52.cpp @@ -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(); diff --git a/variants/eink/variant.h b/variants/eink/variant.h index e0cdda0d25..1dd2e9dc2a 100644 --- a/variants/eink/variant.h +++ b/variants/eink/variant.h @@ -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)