diff --git a/src/ButtonThread.h b/src/ButtonThread.h index 8a6603888..3a6f67a72 100644 --- a/src/ButtonThread.h +++ b/src/ButtonThread.h @@ -135,7 +135,7 @@ class ButtonThread : public concurrency::OSThread screen->adjustBrightness(); #endif // If user button is held down for 5 seconds, shutdown the device. - if (millis() - longPressTime > 5 * 1000) { + if ((millis() - longPressTime > 5 * 1000) && (longPressTime > 0)) { #ifdef TBEAM_V10 if (axp192_found == true) { setLed(false); @@ -144,7 +144,7 @@ class ButtonThread : public concurrency::OSThread #elif NRF52_SERIES // Do actual shutdown when button released, otherwise the button release // may wake the board immediatedly. - if (!shutdown_on_long_stop) { + if ((!shutdown_on_long_stop) && (millis() > 30 * 1000)) { screen->startShutdownScreen(); DEBUG_MSG("Shutdown from long press"); playBeep(); @@ -180,18 +180,22 @@ class ButtonThread : public concurrency::OSThread static void userButtonPressedLongStart() { - DEBUG_MSG("Long press start!\n"); - longPressTime = millis(); + if (millis() > 30 * 1000) { + DEBUG_MSG("Long press start!\n"); + longPressTime = millis(); + } } static void userButtonPressedLongStop() { - DEBUG_MSG("Long press stop!\n"); - longPressTime = 0; - if (shutdown_on_long_stop) { - playShutdownMelody(); - delay(3000); - power->shutdown(); + if (millis() > 30 * 1000){ + DEBUG_MSG("Long press stop!\n"); + longPressTime = 0; + if (shutdown_on_long_stop) { + playShutdownMelody(); + delay(3000); + power->shutdown(); + } } } }; diff --git a/src/GPSStatus.h b/src/GPSStatus.h index bcd371eb8..a15e385a8 100644 --- a/src/GPSStatus.h +++ b/src/GPSStatus.h @@ -63,7 +63,7 @@ class GPSStatus : public Status int32_t getLatitude() const { if (radioConfig.preferences.fixed_position){ -#if GPS_EXTRAVERBOSE +#ifdef GPS_EXTRAVERBOSE DEBUG_MSG("WARNING: Using fixed latitude\n"); #endif NodeInfo *node = nodeDB.getNode(nodeDB.getNodeNum()); @@ -75,7 +75,7 @@ class GPSStatus : public Status int32_t getLongitude() const { if (radioConfig.preferences.fixed_position){ -#if GPS_EXTRAVERBOSE +#ifdef GPS_EXTRAVERBOSE DEBUG_MSG("WARNING: Using fixed longitude\n"); #endif NodeInfo *node = nodeDB.getNode(nodeDB.getNodeNum()); @@ -87,7 +87,7 @@ class GPSStatus : public Status int32_t getAltitude() const { if (radioConfig.preferences.fixed_position){ -#if GPS_EXTRAVERBOSE +#ifdef GPS_EXTRAVERBOSE DEBUG_MSG("WARNING: Using fixed altitude\n"); #endif NodeInfo *node = nodeDB.getNode(nodeDB.getNodeNum()); @@ -105,7 +105,7 @@ class GPSStatus : public Status bool matches(const GPSStatus *newStatus) const { -#if GPS_EXTRAVERBOSE +#ifdef GPS_EXTRAVERBOSE DEBUG_MSG("GPSStatus.match() new pos@%x to old pos@%x\n", newStatus->p.pos_timestamp, p.pos_timestamp); #endif diff --git a/src/RedirectablePrint.cpp b/src/RedirectablePrint.cpp index dc0f3b958..a2f048f8e 100644 --- a/src/RedirectablePrint.cpp +++ b/src/RedirectablePrint.cpp @@ -72,7 +72,7 @@ size_t RedirectablePrint::logDebug(const char *format, ...) // If we are the first message on a report, include the header if (!isContinuationMessage) { - uint32_t rtc_sec = getValidTime(RTCQuality::RTCQualityFromNet); + uint32_t rtc_sec = getValidTime(RTCQuality::RTCQualityDevice); if (rtc_sec > 0) { long hms = rtc_sec % SEC_PER_DAY; // hms += tz.tz_dsttime * SEC_PER_HOUR; diff --git a/src/configuration.h b/src/configuration.h index 8f0d3cfa5..60cf7512b 100644 --- a/src/configuration.h +++ b/src/configuration.h @@ -25,6 +25,10 @@ along with this program. If not, see . #pragma once #include +#ifdef RV3028_RTC + #include "Melopero_RV3028.h" +#endif + // ----------------------------------------------------------------------------- // Version // ----------------------------------------------------------------------------- @@ -100,6 +104,10 @@ along with this program. If not, see . #define GPS_TX_PIN 12 #endif +#ifndef TTGO_T_ECHO +#define GPS_UBLOX +#endif + // ----------------------------------------------------------------------------- // LoRa SPI // ----------------------------------------------------------------------------- diff --git a/src/debug/i2cScan.h b/src/debug/i2cScan.h index 4279a5122..ae6384fbc 100644 --- a/src/debug/i2cScan.h +++ b/src/debug/i2cScan.h @@ -54,7 +54,16 @@ void scanI2Cdevice(void) DEBUG_MSG("unknown display found\n"); } } - +#ifdef RV3028_RTC + if (addr == RV3028_RTC){ + rtc_found = addr; + DEBUG_MSG("RV3028 RTC found\n"); + Melopero_RV3028 rtc; + rtc.initI2C(); + rtc.writeToRegister(0x35,0x07); // no Clkout + rtc.writeToRegister(0x37,0xB4); + } +#endif if (addr == CARDKB_ADDR) { cardkb_found = addr; DEBUG_MSG("m5 cardKB found\n"); @@ -81,7 +90,7 @@ void scanI2Cdevice(void) if (nDevices == 0) DEBUG_MSG("No I2C devices found\n"); else - DEBUG_MSG("done\n"); + DEBUG_MSG("%i I2C devices found\n",nDevices); } #else void scanI2Cdevice(void) {} diff --git a/src/gps/GPS.cpp b/src/gps/GPS.cpp index 57647472c..45e3eb1a1 100644 --- a/src/gps/GPS.cpp +++ b/src/gps/GPS.cpp @@ -54,6 +54,56 @@ bool GPS::setupGPS() _serial_gps->write("$PCAS11,3*1E\r\n"); delay(250); +#endif +#ifdef GPS_UBLOX + // Set the UART port to output NMEA only + byte _message_nmea[] = {0xB5, 0x62, 0x06, 0x00, 0x14, 0x00, + 0x01, 0x00, 0x00, 0x00, 0xC0, 0x08, 0x00, 0x00, 0x80, 0x25, 0x00, 0x00, 0x07, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x91, 0xAF}; + _serial_gps->write(_message_nmea,sizeof(_message_nmea)); + delay(250); + + // disable GGL + byte _message_GGL[] = {0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, + 0xF0, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, + 0x05,0x3A}; + _serial_gps->write(_message_GGL,sizeof(_message_GGL)); + delay(250); + + // disable GSA + byte _message_GSA[] = {0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, + 0xF0, 0x02, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, + 0x06,0x41}; + _serial_gps->write(_message_GSA,sizeof(_message_GSA)); + delay(250); + + // disable GSV + byte _message_GSV[] = {0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, + 0xF0, 0x03, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, + 0x07,0x48}; + _serial_gps->write(_message_GSV,sizeof(_message_GSV)); + delay(250); + + // disable VTG + byte _message_VTG[] = {0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, + 0xF0, 0x05, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, + 0x09,0x56}; + _serial_gps->write(_message_VTG,sizeof(_message_VTG)); + delay(250); + + // enable RMC + byte _message_RMC[] = {0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, + 0xF0, 0x04, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x09,0x54}; + _serial_gps->write(_message_RMC,sizeof(_message_RMC)); + delay(250); + + // enable GGA + byte _message_GGA[] = {0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, + 0xF0, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x05, 0x38}; + _serial_gps->write(_message_GGA,sizeof(_message_GGA)); + delay(250); #endif } diff --git a/src/gps/NMEAGPS.cpp b/src/gps/NMEAGPS.cpp index 73031139a..8a8181f3b 100644 --- a/src/gps/NMEAGPS.cpp +++ b/src/gps/NMEAGPS.cpp @@ -65,7 +65,7 @@ The Unix epoch (or Unix time or POSIX time or Unix timestamp) is the number of s t.tm_year = d.year() - 1900; t.tm_isdst = false; if (t.tm_mon > -1){ - DEBUG_MSG("NMEA GPS time %d-%d-%d %d:%d:%d\n", d.year(), d.month(), t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec); + DEBUG_MSG("NMEA GPS time %02d-%02d-%02d %02d:%02d:%02d\n", d.year(), d.month(), t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec); perhapsSetRTC(RTCQualityGPS, t); return true; } else @@ -129,10 +129,16 @@ bool NMEAGPS::lookForLocation() auto loc = reader.location.value(); // Bail out EARLY to avoid overwriting previous good data (like #857) - if((toDegInt(loc.lat) == 0) || (toDegInt(loc.lat) > 90)) { + if (toDegInt(loc.lat) > 900000000) { +#ifdef GPS_EXTRAVERBOSE + DEBUG_MSG("Bail out EARLY on LAT %i\n",toDegInt(loc.lat)); +#endif return false; } - if((toDegInt(loc.lng) == 0) || (toDegInt(loc.lng) > 180)) { + if (toDegInt(loc.lng) > 1800000000) { +#ifdef GPS_EXTRAVERBOSE + DEBUG_MSG("Bail out EARLY on LNG %i\n",toDegInt(loc.lng)); +#endif return false; } diff --git a/src/gps/RTC.cpp b/src/gps/RTC.cpp index bc7e816cb..e717f97ba 100644 --- a/src/gps/RTC.cpp +++ b/src/gps/RTC.cpp @@ -1,5 +1,6 @@ #include "RTC.h" #include "configuration.h" +#include "main.h" #include #include @@ -18,14 +19,35 @@ static uint64_t zeroOffsetSecs; // GPS based time in secs since 1970 - only upda void readFromRTC() { struct timeval tv; /* btw settimeofday() is helpfull here too*/ - +#ifdef RV3028_RTC + if(rtc_found == RV3028_RTC) { + uint32_t now = millis(); + Melopero_RV3028 rtc; + rtc.initI2C(); + tm t; + t.tm_year = rtc.getYear() - 1900; + t.tm_mon = rtc.getMonth() - 1; + t.tm_mday = rtc.getDate(); + t.tm_hour = rtc.getHour(); + t.tm_min = rtc.getMinute(); + t.tm_sec = rtc.getSecond(); + tv.tv_sec = mktime(&t); + tv.tv_usec = 0; + DEBUG_MSG("Read RTC time from RV3028 as %ld\n", tv.tv_sec); + timeStartMsec = now; + zeroOffsetSecs = tv.tv_sec; + if (currentQuality == RTCQualityNone) { + currentQuality = RTCQualityDevice; + } + } +#else if (!gettimeofday(&tv, NULL)) { uint32_t now = millis(); - - DEBUG_MSG("Read RTC time as %ld (cur millis %u) quality=%d\n", tv.tv_sec, now, currentQuality); + DEBUG_MSG("Read RTC time as %ld\n", tv.tv_sec); timeStartMsec = now; zeroOffsetSecs = tv.tv_sec; } +#endif } /// If we haven't yet set our RTC this boot, set it from a GPS derived time @@ -55,12 +77,20 @@ bool perhapsSetRTC(RTCQuality q, const struct timeval *tv) zeroOffsetSecs = tv->tv_sec; // If this platform has a setable RTC, set it -#ifndef NO_ESP32 +#ifdef RV3028_RTC + if(rtc_found == RV3028_RTC) { + Melopero_RV3028 rtc; + rtc.initI2C(); + tm *t = localtime(&tv->tv_sec); + rtc.setTime(t->tm_year + 1900, t->tm_mon + 1, t->tm_wday, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec); + DEBUG_MSG("RV3028_RTC setTime %02d-%02d-%02d %02d:%02d:%02d %ld\n", t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec, tv->tv_sec); + } +#elif !defined(NO_ESP32) settimeofday(tv, NULL); #endif // nrf52 doesn't have a readable RTC (yet - software not written) -#if defined(PORTDUINO) || !defined(NO_ESP32) +#if defined(PORTDUINO) || !defined(NO_ESP32) || defined(RV3028_RTC) readFromRTC(); #endif diff --git a/src/gps/RTC.h b/src/gps/RTC.h index 730d1914e..f2df3c757 100644 --- a/src/gps/RTC.h +++ b/src/gps/RTC.h @@ -5,17 +5,21 @@ #include enum RTCQuality { + /// We haven't had our RTC set yet RTCQualityNone = 0, + /// We got time from an onboard peripheral after boot. + RTCQualityDevice = 1, + /// Some other node gave us a time we can use - RTCQualityFromNet = 1, + RTCQualityFromNet = 2, /// Our time is based on NTP - RTCQualityNTP= 2, + RTCQualityNTP= 3, /// Our time is based on our own GPS - RTCQualityGPS = 3 + RTCQualityGPS = 4 }; RTCQuality getRTCQuality(); diff --git a/src/graphics/Screen.cpp b/src/graphics/Screen.cpp index edb3ebc45..136964006 100644 --- a/src/graphics/Screen.cpp +++ b/src/graphics/Screen.cpp @@ -1557,7 +1557,7 @@ void DebugInfo::drawFrameSettings(OLEDDisplay *display, OLEDDisplayUiState *stat else uptime += String(seconds) + "s "; - uint32_t rtc_sec = getValidTime(RTCQuality::RTCQualityFromNet); + uint32_t rtc_sec = getValidTime(RTCQuality::RTCQualityDevice); if (rtc_sec > 0) { long hms = rtc_sec % SEC_PER_DAY; // hms += tz.tz_dsttime * SEC_PER_HOUR; diff --git a/src/main.cpp b/src/main.cpp index 7328feb79..666a59831 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -79,6 +79,9 @@ uint8_t cardkb_found; // The I2C address of the Faces Keyboard (if found) uint8_t faceskb_found; +// The I2C address of the RTC Module (if found) +uint8_t rtc_found; + bool eink_found = true; uint32_t serialSinceMsec; diff --git a/src/main.h b/src/main.h index fc91f396a..de79435bb 100644 --- a/src/main.h +++ b/src/main.h @@ -9,6 +9,7 @@ extern uint8_t screen_found; extern uint8_t screen_model; extern uint8_t cardkb_found; extern uint8_t faceskb_found; +extern uint8_t rtc_found; extern bool eink_found; extern bool axp192_found; diff --git a/src/mesh/MeshService.cpp b/src/mesh/MeshService.cpp index 36d3b2251..6fe8cd38d 100644 --- a/src/mesh/MeshService.cpp +++ b/src/mesh/MeshService.cpp @@ -71,17 +71,7 @@ int MeshService::handleFromRadio(const MeshPacket *mp) printPacket("Forwarding to phone", mp); nodeDB.updateFrom(*mp); // update our DB state based off sniffing every RX packet from the radio - fromNum++; - - if (toPhoneQueue.numFree() == 0) { - DEBUG_MSG("NOTE: tophone queue is full, discarding oldest\n"); - MeshPacket *d = toPhoneQueue.dequeuePtr(0); - if (d) - releaseToPool(d); - } - - MeshPacket *copied = packetPool.allocCopy(*mp); - assert(toPhoneQueue.enqueue(copied, 0)); // FIXME, instead of failing for full queue, delete the oldest mssages + sendToPhone((MeshPacket *)mp); return 0; } @@ -161,12 +151,16 @@ bool MeshService::cancelSending(PacketId id) return router->cancelSending(nodeDB.getNodeNum(), id); } -void MeshService::sendToMesh(MeshPacket *p, RxSource src) +void MeshService::sendToMesh(MeshPacket *p, RxSource src, bool ccToPhone) { nodeDB.updateFrom(*p); // update our local DB for this packet (because phone might have sent position packets etc...) // Note: We might return !OK if our fifo was full, at that point the only option we have is to drop it router->sendLocal(p, src); + + if (ccToPhone) { + sendToPhone(p); + } } void MeshService::sendNetworkPing(NodeNum dest, bool wantReplies) @@ -187,6 +181,20 @@ void MeshService::sendNetworkPing(NodeNum dest, bool wantReplies) } } +void MeshService::sendToPhone(MeshPacket *p) { + if (toPhoneQueue.numFree() == 0) { + DEBUG_MSG("NOTE: tophone queue is full, discarding oldest\n"); + MeshPacket *d = toPhoneQueue.dequeuePtr(0); + if (d) + releaseToPool(d); + } + + MeshPacket *copied = packetPool.allocCopy(*p); + perhapsDecode(copied); + assert(toPhoneQueue.enqueue(copied, 0)); // FIXME, instead of failing for full queue, delete the oldest mssages + fromNum++; +} + NodeInfo *MeshService::refreshMyNodeInfo() { NodeInfo *node = nodeDB.getNode(nodeDB.getNodeNum()); @@ -224,7 +232,7 @@ int MeshService::onGPSChanged(const meshtastic::GPSStatus *newStatus) } else { // The GPS has lost lock, if we are fixed position we should just keep using // the old position -#if GPS_EXTRAVERBOSE +#ifdef GPS_EXTRAVERBOSE DEBUG_MSG("onGPSchanged() - lost validLocation\n"); #endif if (radioConfig.preferences.fixed_position) { diff --git a/src/mesh/MeshService.h b/src/mesh/MeshService.h index 3abae8efe..45559d3a2 100644 --- a/src/mesh/MeshService.h +++ b/src/mesh/MeshService.h @@ -75,7 +75,7 @@ class MeshService /// Send a packet into the mesh - note p must have been allocated from packetPool. We will return it to that pool after /// sending. This is the ONLY function you should use for sending messages into the mesh, because it also updates the nodedb /// cache - void sendToMesh(MeshPacket *p, RxSource src = RX_SRC_LOCAL); + void sendToMesh(MeshPacket *p, RxSource src = RX_SRC_LOCAL, bool ccToPhone = false); /** Attempt to cancel a previously sent packet from this _local_ node. Returns true if a packet was found we could cancel */ bool cancelSending(PacketId id); @@ -83,6 +83,9 @@ class MeshService /// Pull the latest power and time info into my nodeinfo NodeInfo *refreshMyNodeInfo(); + /// Send a packet to the phone + void sendToPhone(MeshPacket *p); + private: /// Called when our gps position has changed - updates nodedb and sends Location message out into the mesh /// returns 0 to allow futher processing diff --git a/src/modules/PositionModule.cpp b/src/modules/PositionModule.cpp index da34ed69e..750920714 100644 --- a/src/modules/PositionModule.cpp +++ b/src/modules/PositionModule.cpp @@ -118,7 +118,7 @@ void PositionModule::sendOurPosition(NodeNum dest, bool wantReplies) p->priority = MeshPacket_Priority_BACKGROUND; prevPacketId = p->id; - service.sendToMesh(p); + service.sendToMesh(p, RX_SRC_LOCAL, true); } int32_t PositionModule::runOnce() diff --git a/src/nrf52/NRF52CryptoEngine.cpp b/src/nrf52/NRF52CryptoEngine.cpp index 49f85a857..b508ed554 100644 --- a/src/nrf52/NRF52CryptoEngine.cpp +++ b/src/nrf52/NRF52CryptoEngine.cpp @@ -1,7 +1,7 @@ #include "configuration.h" #include "CryptoEngine.h" #include - +#include "aes-256/tiny-aes.h" class NRF52CryptoEngine : public CryptoEngine { public: @@ -18,7 +18,12 @@ class NRF52CryptoEngine : public CryptoEngine { // DEBUG_MSG("NRF52 encrypt!\n"); - if (key.length > 0) { + if (key.length > 16) { + AES_ctx ctx; + initNonce(fromNode, packetId); + AES_init_ctx_iv(&ctx, key.bytes, nonce); + AES_CTR_xcrypt_buffer(&ctx, bytes, numBytes); + } else if (key.length > 0) { nRFCrypto.begin(); nRFCrypto_AES ctx; uint8_t myLen = ctx.blockLen(numBytes); @@ -36,7 +41,12 @@ class NRF52CryptoEngine : public CryptoEngine { // DEBUG_MSG("NRF52 decrypt!\n"); - if (key.length > 0) { + if (key.length > 16) { + AES_ctx ctx; + initNonce(fromNode, packetId); + AES_init_ctx_iv(&ctx, key.bytes, nonce); + AES_CTR_xcrypt_buffer(&ctx, bytes, numBytes); + } else if (key.length > 0) { nRFCrypto.begin(); nRFCrypto_AES ctx; uint8_t myLen = ctx.blockLen(numBytes); diff --git a/src/nrf52/aes-256/tiny-aes.cpp b/src/nrf52/aes-256/tiny-aes.cpp new file mode 100644 index 000000000..dc28a5249 --- /dev/null +++ b/src/nrf52/aes-256/tiny-aes.cpp @@ -0,0 +1,229 @@ +/* +AES-256 Software Implementation + +based on https://github.com/kokke/tiny-AES-C/ which is in public domain + +NOTE: String length must be evenly divisible by 16byte (str_len % 16 == 0) + You should pad the end of the string with zeros if this is not the case. + For AES192/256 the key size is proportionally larger. +*/ + +#include +#include "tiny-aes.h" + +#define Nb 4 +#define Nk 8 +#define Nr 14 + +typedef uint8_t state_t[4][4]; + +static const uint8_t sbox[256] = { + //0 1 2 3 4 5 6 7 8 9 A B C D E F + 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, + 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, + 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, + 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, + 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, + 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, + 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, + 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, + 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, + 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, + 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, + 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, + 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, + 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, + 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, + 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 }; + +static const uint8_t Rcon[11] = { + 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36 }; + +#define getSBoxValue(num) (sbox[(num)]) + +static void KeyExpansion(uint8_t* RoundKey, const uint8_t* Key) +{ + uint8_t tempa[4]; + + for (unsigned i = 0; i < Nk; ++i) + { + RoundKey[(i * 4) + 0] = Key[(i * 4) + 0]; + RoundKey[(i * 4) + 1] = Key[(i * 4) + 1]; + RoundKey[(i * 4) + 2] = Key[(i * 4) + 2]; + RoundKey[(i * 4) + 3] = Key[(i * 4) + 3]; + } + + for (unsigned i = Nk; i < Nb * (Nr + 1); ++i) + { + unsigned k = (i - 1) * 4; + tempa[0]=RoundKey[k + 0]; + tempa[1]=RoundKey[k + 1]; + tempa[2]=RoundKey[k + 2]; + tempa[3]=RoundKey[k + 3]; + + if (i % Nk == 0) + { + const uint8_t u8tmp = tempa[0]; + tempa[0] = tempa[1]; + tempa[1] = tempa[2]; + tempa[2] = tempa[3]; + tempa[3] = u8tmp; + + tempa[0] = getSBoxValue(tempa[0]); + tempa[1] = getSBoxValue(tempa[1]); + tempa[2] = getSBoxValue(tempa[2]); + tempa[3] = getSBoxValue(tempa[3]); + + tempa[0] = tempa[0] ^ Rcon[i/Nk]; + } + + if (i % Nk == 4) + { + tempa[0] = getSBoxValue(tempa[0]); + tempa[1] = getSBoxValue(tempa[1]); + tempa[2] = getSBoxValue(tempa[2]); + tempa[3] = getSBoxValue(tempa[3]); + } + + unsigned j = i * 4; k=(i - Nk) * 4; + RoundKey[j + 0] = RoundKey[k + 0] ^ tempa[0]; + RoundKey[j + 1] = RoundKey[k + 1] ^ tempa[1]; + RoundKey[j + 2] = RoundKey[k + 2] ^ tempa[2]; + RoundKey[j + 3] = RoundKey[k + 3] ^ tempa[3]; + } +} + +void AES_init_ctx(struct AES_ctx* ctx, const uint8_t* key) +{ + KeyExpansion(ctx->RoundKey, key); +} +void AES_init_ctx_iv(struct AES_ctx* ctx, const uint8_t* key, const uint8_t* iv) +{ + KeyExpansion(ctx->RoundKey, key); + memcpy (ctx->Iv, iv, AES_BLOCKLEN); +} +void AES_ctx_set_iv(struct AES_ctx* ctx, const uint8_t* iv) +{ + memcpy (ctx->Iv, iv, AES_BLOCKLEN); +} + +static void AddRoundKey(uint8_t round, state_t* state, const uint8_t* RoundKey) +{ + for (uint8_t i = 0; i < 4; ++i) + { + for (uint8_t j = 0; j < 4; ++j) + { + (*state)[i][j] ^= RoundKey[(round * Nb * 4) + (i * Nb) + j]; + } + } +} + +static void SubBytes(state_t* state) +{ + for (uint8_t i = 0; i < 4; ++i) + { + for (uint8_t j = 0; j < 4; ++j) + { + (*state)[j][i] = getSBoxValue((*state)[j][i]); + } + } +} + +static void ShiftRows(state_t* state) +{ + uint8_t temp = (*state)[0][1]; + (*state)[0][1] = (*state)[1][1]; + (*state)[1][1] = (*state)[2][1]; + (*state)[2][1] = (*state)[3][1]; + (*state)[3][1] = temp; + + temp = (*state)[0][2]; + (*state)[0][2] = (*state)[2][2]; + (*state)[2][2] = temp; + + temp = (*state)[1][2]; + (*state)[1][2] = (*state)[3][2]; + (*state)[3][2] = temp; + + temp = (*state)[0][3]; + (*state)[0][3] = (*state)[3][3]; + (*state)[3][3] = (*state)[2][3]; + (*state)[2][3] = (*state)[1][3]; + (*state)[1][3] = temp; +} + +static uint8_t xtime(uint8_t x) +{ + return ((x<<1) ^ (((x>>7) & 1) * 0x1b)); +} + +static void MixColumns(state_t* state) +{ + for (uint8_t i = 0; i < 4; ++i) + { + uint8_t t = (*state)[i][0]; + uint8_t Tmp = (*state)[i][0] ^ (*state)[i][1] ^ (*state)[i][2] ^ (*state)[i][3] ; + uint8_t Tm = (*state)[i][0] ^ (*state)[i][1] ; Tm = xtime(Tm); (*state)[i][0] ^= Tm ^ Tmp ; + Tm = (*state)[i][1] ^ (*state)[i][2] ; Tm = xtime(Tm); (*state)[i][1] ^= Tm ^ Tmp ; + Tm = (*state)[i][2] ^ (*state)[i][3] ; Tm = xtime(Tm); (*state)[i][2] ^= Tm ^ Tmp ; + Tm = (*state)[i][3] ^ t ; Tm = xtime(Tm); (*state)[i][3] ^= Tm ^ Tmp ; + } +} + +#define Multiply(x, y) \ + ( ((y & 1) * x) ^ \ + ((y>>1 & 1) * xtime(x)) ^ \ + ((y>>2 & 1) * xtime(xtime(x))) ^ \ + ((y>>3 & 1) * xtime(xtime(xtime(x)))) ^ \ + ((y>>4 & 1) * xtime(xtime(xtime(xtime(x)))))) \ + + +static void Cipher(state_t* state, const uint8_t* RoundKey) +{ + uint8_t round = 0; + + AddRoundKey(0, state, RoundKey); + + for (round = 1; ; ++round) + { + SubBytes(state); + ShiftRows(state); + if (round == Nr) { + break; + } + MixColumns(state); + AddRoundKey(round, state, RoundKey); + } + AddRoundKey(Nr, state, RoundKey); +} + +void AES_CTR_xcrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, size_t length) +{ + uint8_t buffer[AES_BLOCKLEN]; + + size_t i; + int bi; + for (i = 0, bi = AES_BLOCKLEN; i < length; ++i, ++bi) + { + if (bi == AES_BLOCKLEN) + { + + memcpy(buffer, ctx->Iv, AES_BLOCKLEN); + Cipher((state_t*)buffer,ctx->RoundKey); + + for (bi = (AES_BLOCKLEN - 1); bi >= 0; --bi) + { + if (ctx->Iv[bi] == 255) + { + ctx->Iv[bi] = 0; + continue; + } + ctx->Iv[bi] += 1; + break; + } + bi = 0; + } + + buf[i] = (buf[i] ^ buffer[bi]); + } +} diff --git a/src/nrf52/aes-256/tiny-aes.h b/src/nrf52/aes-256/tiny-aes.h new file mode 100644 index 000000000..eded2c77f --- /dev/null +++ b/src/nrf52/aes-256/tiny-aes.h @@ -0,0 +1,23 @@ +#ifndef _TINY_AES_H_ +#define _TINY_AES_H_ + +#include +#include + +#define AES_BLOCKLEN 16 // Block length in bytes - AES is 128b block only +// #define AES_KEYLEN 32 +#define AES_keyExpSize 240 + +struct AES_ctx +{ + uint8_t RoundKey[AES_keyExpSize]; + uint8_t Iv[AES_BLOCKLEN]; +}; + +void AES_init_ctx(struct AES_ctx* ctx, const uint8_t* key); +void AES_init_ctx_iv(struct AES_ctx* ctx, const uint8_t* key, const uint8_t* iv); +void AES_ctx_set_iv(struct AES_ctx* ctx, const uint8_t* iv); + +void AES_CTR_xcrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, size_t length); + +#endif // _TINY_AES_H_ diff --git a/src/nrf52/main-nrf52.cpp b/src/nrf52/main-nrf52.cpp index 655170c36..90ab0113f 100644 --- a/src/nrf52/main-nrf52.cpp +++ b/src/nrf52/main-nrf52.cpp @@ -33,8 +33,8 @@ void __attribute__((noreturn)) __assert_func(const char *file, int line, const c { DEBUG_MSG("assert failed %s: %d, %s, test=%s\n", file, line, func, failedexpr); // debugger_break(); FIXME doesn't work, possibly not for segger - while (1) - ; // FIXME, reboot! + // Reboot cpu + NVIC_SystemReset(); } void getMacAddr(uint8_t *dmac) @@ -196,4 +196,4 @@ void clearBonds() { nrf52Bluetooth->setup(); } nrf52Bluetooth->clearBonds(); -} \ No newline at end of file +} diff --git a/src/shutdown.h b/src/shutdown.h index 10c93bde2..17ceb75dd 100644 --- a/src/shutdown.h +++ b/src/shutdown.h @@ -7,9 +7,11 @@ void powerCommandsCheck() { if (rebootAtMsec && millis() > rebootAtMsec) { + DEBUG_MSG("Rebooting\n"); #ifndef NO_ESP32 - DEBUG_MSG("Rebooting for update\n"); ESP.restart(); +#elif NRF52_SERIES + NVIC_SystemReset(); #else DEBUG_MSG("FIXME implement reboot for this platform"); #endif diff --git a/variants/rak4631/platformio.ini b/variants/rak4631/platformio.ini index 6e0563598..fd9fbcd89 100644 --- a/variants/rak4631/platformio.ini +++ b/variants/rak4631/platformio.ini @@ -6,6 +6,7 @@ build_flags = ${nrf52840_base.build_flags} -Ivariants/rak4631 -D RAK_4631 src_filter = ${nrf52_base.src_filter} +<../variants/rak4631> lib_deps = ${nrf52840_base.lib_deps} + melopero/Melopero RV3028@^1.1.0 debug_tool = jlink ; If not set we will default to uploading over serial (first it forces bootloader entry by talking 1200bps to cdcacm) ;upload_protocol = jlink \ No newline at end of file diff --git a/variants/rak4631/variant.h b/variants/rak4631/variant.h index c211ec4a1..bae5d957a 100644 --- a/variants/rak4631/variant.h +++ b/variants/rak4631/variant.h @@ -198,6 +198,9 @@ static const uint8_t SCK = PIN_SPI_SCK; #define GPS_RX_PIN PIN_SERIAL1_RX #define GPS_TX_PIN PIN_SERIAL1_TX +// RAK12002 RTC Module +#define RV3028_RTC (uint8_t) 0b1010010 + // Battery // The battery sense is hooked to pin A0 (5) #define BATTERY_PIN PIN_A0 diff --git a/variants/rak4631_epaper/platformio.ini b/variants/rak4631_epaper/platformio.ini index fc65ac2c8..55f799e25 100644 --- a/variants/rak4631_epaper/platformio.ini +++ b/variants/rak4631_epaper/platformio.ini @@ -7,6 +7,7 @@ src_filter = ${nrf52_base.src_filter} +<../variants/rak4631_epaper> lib_deps = ${nrf52840_base.lib_deps} https://github.com/ZinggJM/GxEPD2.git + melopero/Melopero RV3028@^1.1.0 debug_tool = jlink ; If not set we will default to uploading over serial (first it forces bootloader entry by talking 1200bps to cdcacm) ;upload_protocol = jlink \ No newline at end of file diff --git a/variants/rak4631_epaper/variant.h b/variants/rak4631_epaper/variant.h index 071c659e1..12f379d06 100644 --- a/variants/rak4631_epaper/variant.h +++ b/variants/rak4631_epaper/variant.h @@ -198,6 +198,9 @@ static const uint8_t SCK = PIN_SPI_SCK; #define GPS_RX_PIN PIN_SERIAL1_RX #define GPS_TX_PIN PIN_SERIAL1_TX +// RAK12002 RTC Module +#define RV3028_RTC (uint8_t) 0b1010010 + // Battery // The battery sense is hooked to pin A0 (5) #define BATTERY_PIN PIN_A0 diff --git a/version.properties b/version.properties index d46454914..ed0a18ceb 100644 --- a/version.properties +++ b/version.properties @@ -1,4 +1,4 @@ [VERSION] major = 1 minor = 3 -build = 8 +build = 10