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