Repo restyled using astyle (#683)
The rules are in .tools/astyle/config/style.cfg and can also be reviewed at https://www.mysensors.org/view/260#coding-guidelines-core-library
This commit is contained in:
@@ -14,7 +14,7 @@ max-code-length=100
|
||||
break-after-logical
|
||||
|
||||
# Preprocessor blocks should be indented
|
||||
indent-preproc-block
|
||||
#indent-preproc-block
|
||||
|
||||
# Preprocessor definitions should be indented if linebroken
|
||||
indent-preproc-define
|
||||
@@ -25,7 +25,8 @@ extern bool transportSendRoute(MyMessage &message);
|
||||
extern MyMessage _msg;
|
||||
extern MyMessage _msgTmp;
|
||||
|
||||
inline void gatewayTransportProcess() {
|
||||
inline void gatewayTransportProcess()
|
||||
{
|
||||
if (gatewayTransportAvailable()) {
|
||||
_msg = gatewayTransportReceive();
|
||||
if (_msg.destination == GATEWAY_ADDRESS) {
|
||||
@@ -34,7 +35,8 @@ inline void gatewayTransportProcess() {
|
||||
if (mGetRequestAck(_msg)) {
|
||||
// Copy message
|
||||
_msgTmp = _msg;
|
||||
mSetRequestAck(_msgTmp, false); // Reply without ack flag (otherwise we would end up in an eternal loop)
|
||||
mSetRequestAck(_msgTmp,
|
||||
false); // Reply without ack flag (otherwise we would end up in an eternal loop)
|
||||
mSetAck(_msgTmp, true);
|
||||
_msgTmp.sender = getNodeId();
|
||||
_msgTmp.destination = _msg.sender;
|
||||
|
||||
@@ -35,8 +35,7 @@ MyMessage _ethernetMsg;
|
||||
|
||||
#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
|
||||
|
||||
typedef struct
|
||||
{
|
||||
typedef struct {
|
||||
char string[MY_GATEWAY_MAX_RECEIVE_LENGTH];
|
||||
uint8_t idx;
|
||||
} inputBuffer;
|
||||
@@ -84,14 +83,11 @@ typedef struct
|
||||
#ifdef MY_W5100_SPI_EN
|
||||
void _w5100_spi_en(bool enable)
|
||||
{
|
||||
if (enable)
|
||||
{
|
||||
if (enable) {
|
||||
// Pull up pin
|
||||
hwPinMode(MY_W5100_SPI_EN, INPUT);
|
||||
hwDigitalWrite(MY_W5100_SPI_EN, HIGH);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
// Ground pin
|
||||
hwPinMode(MY_W5100_SPI_EN, OUTPUT);
|
||||
hwDigitalWrite(MY_W5100_SPI_EN, LOW);
|
||||
@@ -101,7 +97,8 @@ typedef struct
|
||||
#define _w5100_spi_en(x)
|
||||
#endif
|
||||
|
||||
bool gatewayTransportInit() {
|
||||
bool gatewayTransportInit()
|
||||
{
|
||||
_w5100_spi_en(true);
|
||||
#if defined(MY_GATEWAY_ESP8266)
|
||||
#if defined(MY_ESP8266_SSID)
|
||||
@@ -114,8 +111,7 @@ bool gatewayTransportInit() {
|
||||
WiFi.config(_ethernetGatewayIP, _gatewayIp, _subnetIp);
|
||||
#endif
|
||||
(void)WiFi.begin(MY_ESP8266_SSID, MY_ESP8266_PASSWORD);
|
||||
while (WiFi.status() != WL_CONNECTED)
|
||||
{
|
||||
while (WiFi.status() != WL_CONNECTED) {
|
||||
wait(500);
|
||||
MY_SERIALDEVICE.print(F("."));
|
||||
}
|
||||
@@ -213,10 +209,8 @@ bool gatewayTransportSend(MyMessage &message)
|
||||
#else
|
||||
// Send message to connected clients
|
||||
#if defined(MY_GATEWAY_ESP8266)
|
||||
for (uint8_t i = 0; i < ARRAY_SIZE(clients); i++)
|
||||
{
|
||||
if (clients[i] && clients[i].connected())
|
||||
{
|
||||
for (uint8_t i = 0; i < ARRAY_SIZE(clients); i++) {
|
||||
if (clients[i] && clients[i].connected()) {
|
||||
nbytes += clients[i].write((uint8_t*)_ethernetMsg, strlen(_ethernetMsg));
|
||||
}
|
||||
}
|
||||
@@ -229,7 +223,8 @@ bool gatewayTransportSend(MyMessage &message)
|
||||
}
|
||||
|
||||
#if (defined(MY_GATEWAY_ESP8266) || defined(MY_GATEWAY_LINUX)) && !defined(MY_GATEWAY_CLIENT_MODE)
|
||||
bool _readFromClient(uint8_t i) {
|
||||
bool _readFromClient(uint8_t i)
|
||||
{
|
||||
while (clients[i].connected() && clients[i].available()) {
|
||||
char inChar = clients[i].read();
|
||||
if (inputString[i].idx < MY_GATEWAY_MAX_RECEIVE_LENGTH - 1) {
|
||||
@@ -258,7 +253,8 @@ bool gatewayTransportSend(MyMessage &message)
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
bool _readFromClient() {
|
||||
bool _readFromClient()
|
||||
{
|
||||
while (client.connected() && client.available()) {
|
||||
char inChar = client.read();
|
||||
if (inputString.idx < MY_GATEWAY_MAX_RECEIVE_LENGTH - 1) {
|
||||
@@ -314,8 +310,7 @@ bool gatewayTransportAvailable()
|
||||
_w5100_spi_en(false);
|
||||
const bool ok = protocolParse(_ethernetMsg, inputString.string);
|
||||
#endif
|
||||
if (ok)
|
||||
{
|
||||
if (ok) {
|
||||
setIndication(INDICATION_GW_RX);
|
||||
}
|
||||
return ok;
|
||||
|
||||
@@ -48,7 +48,8 @@ static bool _MQTT_connecting = true;
|
||||
static bool _MQTT_available = false;
|
||||
static MyMessage _MQTT_msg;
|
||||
|
||||
bool gatewayTransportSend(MyMessage &message) {
|
||||
bool gatewayTransportSend(MyMessage &message)
|
||||
{
|
||||
if (!_MQTT_client.connected()) {
|
||||
return false;
|
||||
}
|
||||
@@ -58,12 +59,14 @@ bool gatewayTransportSend(MyMessage &message) {
|
||||
return _MQTT_client.publish(topic, message.getString(_convBuffer));
|
||||
}
|
||||
|
||||
void incomingMQTT(char* topic, uint8_t* payload, unsigned int length) {
|
||||
void incomingMQTT(char* topic, uint8_t* payload, unsigned int length)
|
||||
{
|
||||
debug(PSTR("Message arrived on topic: %s\n"), topic);
|
||||
_MQTT_available = protocolMQTTParse(_MQTT_msg, topic, payload, length);
|
||||
}
|
||||
|
||||
bool reconnectMQTT() {
|
||||
bool reconnectMQTT()
|
||||
{
|
||||
debug(PSTR("Attempting MQTT connection...\n"));
|
||||
// Attempt to connect
|
||||
if (_MQTT_client.connect(MY_MQTT_CLIENT_ID
|
||||
@@ -85,7 +88,8 @@ bool reconnectMQTT() {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool gatewayTransportConnect() {
|
||||
bool gatewayTransportConnect()
|
||||
{
|
||||
#if defined(MY_GATEWAY_ESP8266)
|
||||
while (WiFi.status() != WL_CONNECTED) {
|
||||
wait(500);
|
||||
@@ -116,7 +120,8 @@ bool gatewayTransportConnect() {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool gatewayTransportInit() {
|
||||
bool gatewayTransportInit()
|
||||
{
|
||||
_MQTT_connecting = true;
|
||||
#if defined(MY_CONTROLLER_IP_ADDRESS)
|
||||
_MQTT_client.setServer(_brokerIp, MY_PORT);
|
||||
@@ -144,7 +149,8 @@ bool gatewayTransportInit() {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool gatewayTransportAvailable() {
|
||||
bool gatewayTransportAvailable()
|
||||
{
|
||||
if (_MQTT_connecting) {
|
||||
return false;
|
||||
}
|
||||
@@ -161,7 +167,8 @@ bool gatewayTransportAvailable() {
|
||||
return _MQTT_available;
|
||||
}
|
||||
|
||||
MyMessage & gatewayTransportReceive() {
|
||||
MyMessage & gatewayTransportReceive()
|
||||
{
|
||||
// Return the last parsed message
|
||||
_MQTT_available = false;
|
||||
return _MQTT_msg;
|
||||
|
||||
@@ -30,14 +30,16 @@ char _serialInputString[MY_GATEWAY_MAX_RECEIVE_LENGTH]; // A buffer for incom
|
||||
uint8_t _serialInputPos;
|
||||
MyMessage _serialMsg;
|
||||
|
||||
bool gatewayTransportSend(MyMessage &message) {
|
||||
bool gatewayTransportSend(MyMessage &message)
|
||||
{
|
||||
setIndication(INDICATION_GW_TX);
|
||||
MY_SERIALDEVICE.print(protocolFormat(message));
|
||||
// Serial print is always successful
|
||||
return true;
|
||||
}
|
||||
|
||||
bool gatewayTransportInit() {
|
||||
bool gatewayTransportInit()
|
||||
{
|
||||
gatewayTransportSend(buildGw(_msgTmp, I_GATEWAY_READY).set("Gateway startup complete."));
|
||||
// Send presentation of locally attached sensors (and node if applicable)
|
||||
presentNode();
|
||||
@@ -45,7 +47,8 @@ bool gatewayTransportInit() {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool gatewayTransportAvailable() {
|
||||
bool gatewayTransportAvailable()
|
||||
{
|
||||
while (MY_SERIALDEVICE.available()) {
|
||||
// get the new byte:
|
||||
char inChar = (char) MY_SERIALDEVICE.read();
|
||||
@@ -55,8 +58,7 @@ bool gatewayTransportAvailable() {
|
||||
if (inChar == '\n') {
|
||||
_serialInputString[_serialInputPos] = 0;
|
||||
bool ok = protocolParse(_serialMsg, _serialInputString);
|
||||
if (ok)
|
||||
{
|
||||
if (ok) {
|
||||
setIndication(INDICATION_GW_RX);
|
||||
}
|
||||
_serialInputPos = 0;
|
||||
@@ -74,7 +76,8 @@ bool gatewayTransportAvailable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
MyMessage & gatewayTransportReceive() {
|
||||
MyMessage & gatewayTransportReceive()
|
||||
{
|
||||
// Return the last parsed message
|
||||
return _serialMsg;
|
||||
}
|
||||
|
||||
+2
-1
@@ -76,7 +76,8 @@ int8_t hwSleep(uint8_t interrupt, uint8_t mode, unsigned long ms);
|
||||
* @param ms Time to sleep, in [ms].
|
||||
* @return -1 when woken by timer, or interrupt number when woken by interrupt.
|
||||
*/
|
||||
int8_t hwSleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2, unsigned long ms);
|
||||
int8_t hwSleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2,
|
||||
unsigned long ms);
|
||||
|
||||
#if defined(MY_DEBUG) || defined(MY_SPECIAL_DEBUG)
|
||||
/**
|
||||
|
||||
+68
-28
@@ -23,15 +23,17 @@
|
||||
|
||||
#define INVALID_INTERRUPT_NUM (0xFFu)
|
||||
|
||||
volatile uint8_t _wokeUpByInterrupt = INVALID_INTERRUPT_NUM; // Interrupt number that woke the mcu.
|
||||
volatile uint8_t _wakeUp1Interrupt = INVALID_INTERRUPT_NUM; // Interrupt number for wakeUp1-callback.
|
||||
volatile uint8_t _wakeUp2Interrupt = INVALID_INTERRUPT_NUM; // Interrupt number for wakeUp2-callback.
|
||||
volatile uint8_t _wokeUpByInterrupt =
|
||||
INVALID_INTERRUPT_NUM; // Interrupt number that woke the mcu.
|
||||
volatile uint8_t _wakeUp1Interrupt =
|
||||
INVALID_INTERRUPT_NUM; // Interrupt number for wakeUp1-callback.
|
||||
volatile uint8_t _wakeUp2Interrupt =
|
||||
INVALID_INTERRUPT_NUM; // Interrupt number for wakeUp2-callback.
|
||||
|
||||
void wakeUp1() //place to send the interrupts
|
||||
{
|
||||
detachInterrupt(_wakeUp1Interrupt);
|
||||
if (_wakeUp2Interrupt != INVALID_INTERRUPT_NUM)
|
||||
{
|
||||
if (_wakeUp2Interrupt != INVALID_INTERRUPT_NUM) {
|
||||
detachInterrupt(_wakeUp2Interrupt);
|
||||
}
|
||||
_wokeUpByInterrupt = _wakeUp1Interrupt;
|
||||
@@ -39,8 +41,7 @@ void wakeUp1() //place to send the interrupts
|
||||
void wakeUp2() //place to send the second interrupts
|
||||
{
|
||||
detachInterrupt(_wakeUp2Interrupt);
|
||||
if (_wakeUp1Interrupt != INVALID_INTERRUPT_NUM)
|
||||
{
|
||||
if (_wakeUp1Interrupt != INVALID_INTERRUPT_NUM) {
|
||||
detachInterrupt(_wakeUp1Interrupt);
|
||||
}
|
||||
_wokeUpByInterrupt = _wakeUp2Interrupt;
|
||||
@@ -57,13 +58,13 @@ ISR (WDT_vect)
|
||||
{
|
||||
}
|
||||
|
||||
void hwPowerDown(period_t period) {
|
||||
void hwPowerDown(period_t period)
|
||||
{
|
||||
// disable ADC for power saving
|
||||
ADCSRA &= ~(1 << ADEN);
|
||||
// save WDT settings
|
||||
uint8_t WDTsave = WDTCSR;
|
||||
if (period != SLEEP_FOREVER)
|
||||
{
|
||||
if (period != SLEEP_FOREVER) {
|
||||
wdt_enable(period);
|
||||
// enable WDT interrupt before system reset
|
||||
WDTCSR |= (1 << WDCE) | (1 << WDIE);
|
||||
@@ -94,33 +95,68 @@ void hwPowerDown(period_t period) {
|
||||
ADCSRA |= (1 << ADEN);
|
||||
}
|
||||
|
||||
void hwInternalSleep(unsigned long ms) {
|
||||
void hwInternalSleep(unsigned long ms)
|
||||
{
|
||||
// Let serial prints finish (debug, log etc)
|
||||
#ifndef MY_DISABLED_SERIAL
|
||||
MY_SERIALDEVICE.flush();
|
||||
#endif
|
||||
while (!interruptWakeUp() && ms >= 8000) { hwPowerDown(SLEEP_8S); ms -= 8000; }
|
||||
if (!interruptWakeUp() && ms >= 4000) { hwPowerDown(SLEEP_4S); ms -= 4000; }
|
||||
if (!interruptWakeUp() && ms >= 2000) { hwPowerDown(SLEEP_2S); ms -= 2000; }
|
||||
if (!interruptWakeUp() && ms >= 1000) { hwPowerDown(SLEEP_1S); ms -= 1000; }
|
||||
if (!interruptWakeUp() && ms >= 500) { hwPowerDown(SLEEP_500MS); ms -= 500; }
|
||||
if (!interruptWakeUp() && ms >= 250) { hwPowerDown(SLEEP_250MS); ms -= 250; }
|
||||
if (!interruptWakeUp() && ms >= 125) { hwPowerDown(SLEEP_120MS); ms -= 120; }
|
||||
if (!interruptWakeUp() && ms >= 64) { hwPowerDown(SLEEP_60MS); ms -= 60; }
|
||||
if (!interruptWakeUp() && ms >= 32) { hwPowerDown(SLEEP_30MS); ms -= 30; }
|
||||
if (!interruptWakeUp() && ms >= 16) { hwPowerDown(SLEEP_15MS); ms -= 15; }
|
||||
while (!interruptWakeUp() && ms >= 8000) {
|
||||
hwPowerDown(SLEEP_8S);
|
||||
ms -= 8000;
|
||||
}
|
||||
if (!interruptWakeUp() && ms >= 4000) {
|
||||
hwPowerDown(SLEEP_4S);
|
||||
ms -= 4000;
|
||||
}
|
||||
if (!interruptWakeUp() && ms >= 2000) {
|
||||
hwPowerDown(SLEEP_2S);
|
||||
ms -= 2000;
|
||||
}
|
||||
if (!interruptWakeUp() && ms >= 1000) {
|
||||
hwPowerDown(SLEEP_1S);
|
||||
ms -= 1000;
|
||||
}
|
||||
if (!interruptWakeUp() && ms >= 500) {
|
||||
hwPowerDown(SLEEP_500MS);
|
||||
ms -= 500;
|
||||
}
|
||||
if (!interruptWakeUp() && ms >= 250) {
|
||||
hwPowerDown(SLEEP_250MS);
|
||||
ms -= 250;
|
||||
}
|
||||
if (!interruptWakeUp() && ms >= 125) {
|
||||
hwPowerDown(SLEEP_120MS);
|
||||
ms -= 120;
|
||||
}
|
||||
if (!interruptWakeUp() && ms >= 64) {
|
||||
hwPowerDown(SLEEP_60MS);
|
||||
ms -= 60;
|
||||
}
|
||||
if (!interruptWakeUp() && ms >= 32) {
|
||||
hwPowerDown(SLEEP_30MS);
|
||||
ms -= 30;
|
||||
}
|
||||
if (!interruptWakeUp() && ms >= 16) {
|
||||
hwPowerDown(SLEEP_15MS);
|
||||
ms -= 15;
|
||||
}
|
||||
}
|
||||
|
||||
int8_t hwSleep(unsigned long ms) {
|
||||
int8_t hwSleep(unsigned long ms)
|
||||
{
|
||||
hwInternalSleep(ms);
|
||||
return MY_WAKE_UP_BY_TIMER;
|
||||
}
|
||||
|
||||
int8_t hwSleep(uint8_t interrupt, uint8_t mode, unsigned long ms) {
|
||||
int8_t hwSleep(uint8_t interrupt, uint8_t mode, unsigned long ms)
|
||||
{
|
||||
return hwSleep(interrupt,mode,INVALID_INTERRUPT_NUM,0u,ms);
|
||||
}
|
||||
|
||||
int8_t hwSleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2, unsigned long ms) {
|
||||
int8_t hwSleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2,
|
||||
unsigned long ms)
|
||||
{
|
||||
// Disable interrupts until going to sleep, otherwise interrupts occurring between attachInterrupt()
|
||||
// and sleep might cause the ATMega to not wakeup from sleep as interrupt has already be handled!
|
||||
cli();
|
||||
@@ -162,7 +198,8 @@ int8_t hwSleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mo
|
||||
}
|
||||
|
||||
#if defined(MY_DEBUG) || defined(MY_SPECIAL_DEBUG)
|
||||
uint16_t hwCPUVoltage() {
|
||||
uint16_t hwCPUVoltage()
|
||||
{
|
||||
// Measure Vcc against 1.1V Vref
|
||||
#if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
|
||||
ADMUX = (_BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1));
|
||||
@@ -182,7 +219,8 @@ uint16_t hwCPUVoltage() {
|
||||
return (1125300UL) / ADC;
|
||||
}
|
||||
|
||||
uint16_t hwCPUFrequency() {
|
||||
uint16_t hwCPUFrequency()
|
||||
{
|
||||
cli();
|
||||
// setup timer1
|
||||
TIFR1 = 0xFF;
|
||||
@@ -210,7 +248,8 @@ uint16_t hwCPUFrequency() {
|
||||
return TCNT1 * 2048UL / 100000UL;
|
||||
}
|
||||
|
||||
uint16_t hwFreeMem() {
|
||||
uint16_t hwFreeMem()
|
||||
{
|
||||
extern int __heap_start, *__brkval;
|
||||
int v;
|
||||
return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
|
||||
@@ -218,7 +257,8 @@ uint16_t hwFreeMem() {
|
||||
#endif
|
||||
|
||||
#ifdef MY_DEBUG
|
||||
void hwDebugPrint(const char *fmt, ... ) {
|
||||
void hwDebugPrint(const char *fmt, ... )
|
||||
{
|
||||
char fmtBuffer[MY_SERIAL_OUTPUT_SIZE];
|
||||
#ifdef MY_GATEWAY_FEATURE
|
||||
// prepend debug message to be handled correctly by controller (C_INTERNAL, I_LOG_MESSAGE)
|
||||
|
||||
+16
-9
@@ -33,8 +33,7 @@ void hwReadConfigBlock(void* buf, void* addr, size_t length)
|
||||
{
|
||||
uint8_t* dst = static_cast<uint8_t*>(buf);
|
||||
int pos = reinterpret_cast<int>(addr);
|
||||
while (length-- > 0)
|
||||
{
|
||||
while (length-- > 0) {
|
||||
*dst++ = EEPROM.read(pos++);
|
||||
}
|
||||
}
|
||||
@@ -63,13 +62,15 @@ void hwWriteConfig(const int addr, uint8_t value)
|
||||
}
|
||||
|
||||
|
||||
int8_t hwSleep(unsigned long ms) {
|
||||
int8_t hwSleep(unsigned long ms)
|
||||
{
|
||||
// TODO: Not supported!
|
||||
(void)ms;
|
||||
return MY_SLEEP_NOT_POSSIBLE;
|
||||
}
|
||||
|
||||
int8_t hwSleep(uint8_t interrupt, uint8_t mode, unsigned long ms) {
|
||||
int8_t hwSleep(uint8_t interrupt, uint8_t mode, unsigned long ms)
|
||||
{
|
||||
// TODO: Not supported!
|
||||
(void)interrupt;
|
||||
(void)mode;
|
||||
@@ -77,7 +78,9 @@ int8_t hwSleep(uint8_t interrupt, uint8_t mode, unsigned long ms) {
|
||||
return MY_SLEEP_NOT_POSSIBLE;
|
||||
}
|
||||
|
||||
int8_t hwSleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2, unsigned long ms) {
|
||||
int8_t hwSleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2,
|
||||
unsigned long ms)
|
||||
{
|
||||
// TODO: Not supported!
|
||||
(void)interrupt1;
|
||||
(void)mode1;
|
||||
@@ -90,23 +93,27 @@ int8_t hwSleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mo
|
||||
#if defined(MY_DEBUG) || defined(MY_SPECIAL_DEBUG)
|
||||
ADC_MODE(ADC_VCC);
|
||||
|
||||
uint16_t hwCPUVoltage() {
|
||||
uint16_t hwCPUVoltage()
|
||||
{
|
||||
// in mV
|
||||
return ESP.getVcc();
|
||||
}
|
||||
|
||||
uint16_t hwCPUFrequency() {
|
||||
uint16_t hwCPUFrequency()
|
||||
{
|
||||
// in 1/10Mhz
|
||||
return ESP.getCpuFreqMHz()*10;
|
||||
}
|
||||
|
||||
uint16_t hwFreeMem() {
|
||||
uint16_t hwFreeMem()
|
||||
{
|
||||
return ESP.getFreeHeap();
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef MY_DEBUG
|
||||
void hwDebugPrint(const char *fmt, ... ) {
|
||||
void hwDebugPrint(const char *fmt, ... )
|
||||
{
|
||||
char fmtBuffer[MY_SERIAL_OUTPUT_SIZE];
|
||||
#ifdef MY_GATEWAY_FEATURE
|
||||
// prepend debug message to be handled correctly by controller (C_INTERNAL, I_LOG_MESSAGE)
|
||||
|
||||
@@ -88,7 +88,8 @@ int8_t hwSleep(uint8_t interrupt, uint8_t mode, unsigned long ms)
|
||||
}
|
||||
|
||||
// Not supported!
|
||||
int8_t hwSleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2, unsigned long ms)
|
||||
int8_t hwSleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2,
|
||||
unsigned long ms)
|
||||
{
|
||||
(void)interrupt1;
|
||||
(void)mode1;
|
||||
|
||||
@@ -52,12 +52,14 @@ inline unsigned long hwMillis();
|
||||
#ifdef MY_RF24_IRQ_PIN
|
||||
static pthread_mutex_t hw_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
static __inline__ void __hwUnlock(const uint8_t *__s) {
|
||||
static __inline__ void __hwUnlock(const uint8_t *__s)
|
||||
{
|
||||
pthread_mutex_unlock(&hw_mutex);
|
||||
(void)__s;
|
||||
}
|
||||
|
||||
static __inline__ void __hwLock() {
|
||||
static __inline__ void __hwLock()
|
||||
{
|
||||
pthread_mutex_lock(&hw_mutex);
|
||||
}
|
||||
#endif
|
||||
|
||||
+2
-1
@@ -87,7 +87,8 @@ int8_t hwSleep(uint8_t interrupt, uint8_t mode, unsigned long ms)
|
||||
}
|
||||
|
||||
// Not supported!
|
||||
int8_t hwSleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2, unsigned long ms)
|
||||
int8_t hwSleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2,
|
||||
unsigned long ms)
|
||||
{
|
||||
(void)interrupt1;
|
||||
(void)mode1;
|
||||
|
||||
+6
-3
@@ -26,15 +26,18 @@
|
||||
#include "log.h"
|
||||
#include "bcm2835.h"
|
||||
|
||||
class Bcm2835Init {
|
||||
class Bcm2835Init
|
||||
{
|
||||
public:
|
||||
Bcm2835Init() {
|
||||
Bcm2835Init()
|
||||
{
|
||||
if (!bcm2835_init()) {
|
||||
logError("Failed to initialized bcm2835.\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
~Bcm2835Init() {
|
||||
~Bcm2835Init()
|
||||
{
|
||||
bcm2835_close();
|
||||
}
|
||||
};
|
||||
|
||||
+28
-18
@@ -42,7 +42,8 @@ ISR (WDT_vect)
|
||||
|
||||
|
||||
|
||||
void i2c_eeprom_write_byte(unsigned int eeaddress, byte data ) {
|
||||
void i2c_eeprom_write_byte(unsigned int eeaddress, byte data )
|
||||
{
|
||||
int rdata = data;
|
||||
Wire.beginTransmission(I2C_EEP_ADDRESS);
|
||||
Wire.write((int)(eeaddress >> 8)); // MSB
|
||||
@@ -51,7 +52,8 @@ void i2c_eeprom_write_byte(unsigned int eeaddress, byte data ) {
|
||||
Wire.endTransmission();
|
||||
}
|
||||
|
||||
byte i2c_eeprom_read_byte(unsigned int eeaddress ) {
|
||||
byte i2c_eeprom_read_byte(unsigned int eeaddress )
|
||||
{
|
||||
byte rdata = 0xFF;
|
||||
Wire.beginTransmission(I2C_EEP_ADDRESS);
|
||||
Wire.write((int)(eeaddress >> 8)); // MSB
|
||||
@@ -68,8 +70,7 @@ void hwReadConfigBlock(void* buf, void* adr, size_t length)
|
||||
{
|
||||
uint8_t* dst = static_cast<uint8_t*>(buf);
|
||||
int offs = reinterpret_cast<int>(adr);
|
||||
while (length-- > 0)
|
||||
{
|
||||
while (length-- > 0) {
|
||||
*dst++ = i2c_eeprom_read_byte(offs++);
|
||||
}
|
||||
}
|
||||
@@ -78,8 +79,7 @@ void hwWriteConfigBlock(void* buf, void* adr, size_t length)
|
||||
{
|
||||
uint8_t* src = static_cast<uint8_t*>(buf);
|
||||
int offs = reinterpret_cast<int>(adr);
|
||||
while (length-- > 0)
|
||||
{
|
||||
while (length-- > 0) {
|
||||
i2c_eeprom_write_byte(offs++, *src++);
|
||||
}
|
||||
}
|
||||
@@ -94,13 +94,13 @@ uint8_t hwReadConfig(int adr)
|
||||
void hwWriteConfig(int adr, uint8_t value)
|
||||
{
|
||||
uint8_t curr = hwReadConfig(adr);
|
||||
if (curr != value)
|
||||
{
|
||||
if (curr != value) {
|
||||
hwWriteConfigBlock(&value, reinterpret_cast<void*>(adr), 1);
|
||||
}
|
||||
}
|
||||
|
||||
void hwInit() {
|
||||
void hwInit()
|
||||
{
|
||||
MY_SERIALDEVICE.begin(MY_BAUD_RATE);
|
||||
#if defined(MY_GATEWAY_SERIAL)
|
||||
while (!MY_SERIALDEVICE) {}
|
||||
@@ -108,22 +108,26 @@ void hwInit() {
|
||||
Wire.begin();
|
||||
}
|
||||
|
||||
void hwWatchdogReset() {
|
||||
void hwWatchdogReset()
|
||||
{
|
||||
// TODO: Not supported!
|
||||
}
|
||||
|
||||
void hwReboot() {
|
||||
void hwReboot()
|
||||
{
|
||||
NVIC_SystemReset();
|
||||
while (true);
|
||||
}
|
||||
|
||||
int8_t hwSleep(unsigned long ms) {
|
||||
int8_t hwSleep(unsigned long ms)
|
||||
{
|
||||
// TODO: Not supported!
|
||||
(void)ms;
|
||||
return MY_SLEEP_NOT_POSSIBLE;
|
||||
}
|
||||
|
||||
int8_t hwSleep(uint8_t interrupt, uint8_t mode, unsigned long ms) {
|
||||
int8_t hwSleep(uint8_t interrupt, uint8_t mode, unsigned long ms)
|
||||
{
|
||||
// TODO: Not supported!
|
||||
(void)interrupt;
|
||||
(void)mode;
|
||||
@@ -131,7 +135,9 @@ int8_t hwSleep(uint8_t interrupt, uint8_t mode, unsigned long ms) {
|
||||
return MY_SLEEP_NOT_POSSIBLE;
|
||||
}
|
||||
|
||||
int8_t hwSleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2, unsigned long ms) {
|
||||
int8_t hwSleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2,
|
||||
unsigned long ms)
|
||||
{
|
||||
// TODO: Not supported!
|
||||
(void)interrupt1;
|
||||
(void)mode1;
|
||||
@@ -142,7 +148,8 @@ int8_t hwSleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mo
|
||||
}
|
||||
|
||||
#if defined(MY_DEBUG) || defined(MY_SPECIAL_DEBUG)
|
||||
uint16_t hwCPUVoltage() {
|
||||
uint16_t hwCPUVoltage()
|
||||
{
|
||||
|
||||
// disable ADC
|
||||
while (ADC->STATUS.bit.SYNCBUSY);
|
||||
@@ -178,19 +185,22 @@ uint16_t hwCPUVoltage() {
|
||||
return valueRead * 4;
|
||||
}
|
||||
|
||||
uint16_t hwCPUFrequency() {
|
||||
uint16_t hwCPUFrequency()
|
||||
{
|
||||
// TODO: currently reporting compile time frequency (in 1/10MHz)
|
||||
return F_CPU / 100000UL;
|
||||
}
|
||||
|
||||
uint16_t hwFreeMem() {
|
||||
uint16_t hwFreeMem()
|
||||
{
|
||||
// TODO: Not supported!
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef MY_DEBUG
|
||||
void hwDebugPrint(const char *fmt, ... ) {
|
||||
void hwDebugPrint(const char *fmt, ... )
|
||||
{
|
||||
if (MY_SERIALDEVICE) {
|
||||
char fmtBuffer[MY_SERIAL_OUTPUT_SIZE];
|
||||
#ifdef MY_GATEWAY_FEATURE
|
||||
|
||||
@@ -25,7 +25,8 @@ extern MyMessage _msgTmp;
|
||||
unsigned long _inclusionStartTime;
|
||||
bool _inclusionMode;
|
||||
|
||||
inline void inclusionInit() {
|
||||
inline void inclusionInit()
|
||||
{
|
||||
_inclusionMode = false;
|
||||
#if defined(MY_INCLUSION_BUTTON_FEATURE)
|
||||
// Setup digital in that triggers inclusion mode
|
||||
@@ -36,7 +37,8 @@ inline void inclusionInit() {
|
||||
}
|
||||
|
||||
|
||||
void inclusionModeSet(bool newMode) {
|
||||
void inclusionModeSet(bool newMode)
|
||||
{
|
||||
if (newMode != _inclusionMode) {
|
||||
_inclusionMode = newMode;
|
||||
// Send back mode change to controller
|
||||
@@ -47,7 +49,8 @@ void inclusionModeSet(bool newMode) {
|
||||
}
|
||||
}
|
||||
|
||||
inline void inclusionProcess() {
|
||||
inline void inclusionProcess()
|
||||
{
|
||||
#ifdef MY_INCLUSION_BUTTON_FEATURE
|
||||
if (!_inclusionMode && hwDigitalRead(MY_INCLUSION_MODE_BUTTON_PIN) == MY_INCLUSION_BUTTON_PRESSED) {
|
||||
// Start inclusion mode
|
||||
|
||||
@@ -25,20 +25,17 @@
|
||||
void setIndication( const indication_t ind )
|
||||
{
|
||||
#if defined(MY_DEFAULT_TX_LED_PIN)
|
||||
if ((INDICATION_TX == ind) || (INDICATION_GW_TX == ind))
|
||||
{
|
||||
if ((INDICATION_TX == ind) || (INDICATION_GW_TX == ind)) {
|
||||
ledsBlinkTx(1);
|
||||
} else
|
||||
#endif
|
||||
#if defined(MY_DEFAULT_RX_LED_PIN)
|
||||
if ((INDICATION_RX == ind) || (INDICATION_GW_RX == ind))
|
||||
{
|
||||
if ((INDICATION_RX == ind) || (INDICATION_GW_RX == ind)) {
|
||||
ledsBlinkRx(1);
|
||||
} else
|
||||
#endif
|
||||
#if defined(MY_DEFAULT_ERR_LED_PIN)
|
||||
if (ind > INDICATION_ERR_START)
|
||||
{
|
||||
if (ind > INDICATION_ERR_START) {
|
||||
// Number of blinks indicates which error occurred.
|
||||
ledsBlinkErr(ind-INDICATION_ERR_START);
|
||||
}
|
||||
|
||||
+12
-6
@@ -45,11 +45,13 @@ inline void ledsInit()
|
||||
#if defined(MY_DEFAULT_ERR_LED_PIN)
|
||||
hwPinMode(MY_DEFAULT_ERR_LED_PIN, OUTPUT);
|
||||
#endif
|
||||
prevTime = hwMillis() - LED_PROCESS_INTERVAL_MS; // Substract some, to make sure leds gets updated on first run.
|
||||
prevTime = hwMillis() -
|
||||
LED_PROCESS_INTERVAL_MS; // Substract some, to make sure leds gets updated on first run.
|
||||
ledsProcess();
|
||||
}
|
||||
|
||||
void ledsProcess() {
|
||||
void ledsProcess()
|
||||
{
|
||||
// Just return if it is not the time...
|
||||
if ((hwMillis() - prevTime) < LED_PROCESS_INTERVAL_MS) {
|
||||
return;
|
||||
@@ -85,27 +87,31 @@ void ledsProcess() {
|
||||
#endif
|
||||
}
|
||||
|
||||
void ledsBlinkRx(uint8_t cnt) {
|
||||
void ledsBlinkRx(uint8_t cnt)
|
||||
{
|
||||
if (!countRx) {
|
||||
countRx = cnt*LED_ON_OFF_RATIO;
|
||||
}
|
||||
ledsProcess();
|
||||
}
|
||||
|
||||
void ledsBlinkTx(uint8_t cnt) {
|
||||
void ledsBlinkTx(uint8_t cnt)
|
||||
{
|
||||
if(!countTx) {
|
||||
countTx = cnt*LED_ON_OFF_RATIO;
|
||||
}
|
||||
ledsProcess();
|
||||
}
|
||||
|
||||
void ledsBlinkErr(uint8_t cnt) {
|
||||
void ledsBlinkErr(uint8_t cnt)
|
||||
{
|
||||
if(!countErr) {
|
||||
countErr = cnt*LED_ON_OFF_RATIO;
|
||||
}
|
||||
ledsProcess();
|
||||
}
|
||||
|
||||
bool ledsBlinking() {
|
||||
bool ledsBlinking()
|
||||
{
|
||||
return countRx || countTx || countErr;
|
||||
}
|
||||
|
||||
@@ -21,7 +21,8 @@
|
||||
|
||||
extern "C" void __libc_init_array(void);
|
||||
|
||||
int main(void) {
|
||||
int main(void)
|
||||
{
|
||||
init();
|
||||
#if defined(USBCON)
|
||||
#if defined(ARDUINO_ARCH_SAMD)
|
||||
|
||||
+28
-17
@@ -38,7 +38,8 @@ extern "C" {
|
||||
struct rst_info resetInfo;
|
||||
|
||||
extern "C" {
|
||||
extern const uint32_t __attribute__((section(".ver_number"))) core_version = ARDUINO_ESP8266_GIT_VER;
|
||||
extern const uint32_t __attribute__((section(".ver_number"))) core_version =
|
||||
ARDUINO_ESP8266_GIT_VER;
|
||||
const char* core_release =
|
||||
#ifdef ARDUINO_ESP8266_RELEASE
|
||||
ARDUINO_ESP8266_RELEASE;
|
||||
@@ -47,18 +48,21 @@ extern "C" {
|
||||
#endif
|
||||
} // extern "C"
|
||||
|
||||
int atexit(void(*func)()) {
|
||||
int atexit(void(*func)())
|
||||
{
|
||||
(void)func;
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern "C" void ets_update_cpu_frequency(int freqmhz);
|
||||
void initVariant() __attribute__((weak));
|
||||
void initVariant() {
|
||||
void initVariant()
|
||||
{
|
||||
}
|
||||
|
||||
void preloop_update_frequency() __attribute__((weak));
|
||||
void preloop_update_frequency() {
|
||||
void preloop_update_frequency()
|
||||
{
|
||||
#if defined(F_CPU) && (F_CPU == 160000000L)
|
||||
REG_SET_BIT(0x3ff00014, BIT(0));
|
||||
ets_update_cpu_frequency(160);
|
||||
@@ -73,37 +77,40 @@ static os_event_t g_loop_queue[LOOP_QUEUE_SIZE];
|
||||
|
||||
static uint32_t g_micros_at_task_start;
|
||||
|
||||
extern "C" void esp_yield() {
|
||||
extern "C" void esp_yield()
|
||||
{
|
||||
if (cont_can_yield(&g_cont)) {
|
||||
cont_yield(&g_cont);
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void esp_schedule() {
|
||||
extern "C" void esp_schedule()
|
||||
{
|
||||
ets_post(LOOP_TASK_PRIORITY, 0, 0);
|
||||
}
|
||||
|
||||
extern "C" void __yield() {
|
||||
extern "C" void __yield()
|
||||
{
|
||||
if (cont_can_yield(&g_cont)) {
|
||||
esp_schedule();
|
||||
esp_yield();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
panic();
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void yield(void) __attribute__((weak, alias("__yield")));
|
||||
|
||||
extern "C" void optimistic_yield(uint32_t interval_us) {
|
||||
if (cont_can_yield(&g_cont) &&
|
||||
(system_get_time() - g_micros_at_task_start) > interval_us)
|
||||
extern "C" void optimistic_yield(uint32_t interval_us)
|
||||
{
|
||||
if (cont_can_yield(&g_cont) &&
|
||||
(system_get_time() - g_micros_at_task_start) > interval_us) {
|
||||
yield();
|
||||
}
|
||||
}
|
||||
|
||||
static void loop_wrapper() {
|
||||
static void loop_wrapper()
|
||||
{
|
||||
static bool setup_done = false;
|
||||
preloop_update_frequency();
|
||||
if (!setup_done) {
|
||||
@@ -116,7 +123,8 @@ static void loop_wrapper() {
|
||||
esp_schedule();
|
||||
}
|
||||
|
||||
static void loop_task(os_event_t *events) {
|
||||
static void loop_task(os_event_t *events)
|
||||
{
|
||||
(void)events;
|
||||
g_micros_at_task_start = system_get_time();
|
||||
cont_run(&g_cont, &loop_wrapper);
|
||||
@@ -125,7 +133,8 @@ static void loop_task(os_event_t *events) {
|
||||
}
|
||||
}
|
||||
|
||||
static void do_global_ctors(void) {
|
||||
static void do_global_ctors(void)
|
||||
{
|
||||
void(**p)(void) = &__init_array_end;
|
||||
while (p != &__init_array_start) {
|
||||
(*--p)();
|
||||
@@ -138,7 +147,8 @@ extern "C" void gdb_init(void) __attribute__((weak, alias("__gdb_init")));
|
||||
extern "C" void __gdb_do_break() {}
|
||||
extern "C" void gdb_do_break(void) __attribute__((weak, alias("__gdb_do_break")));
|
||||
|
||||
void init_done() {
|
||||
void init_done()
|
||||
{
|
||||
system_set_os_print(1);
|
||||
gdb_init();
|
||||
do_global_ctors();
|
||||
@@ -146,7 +156,8 @@ void init_done() {
|
||||
}
|
||||
|
||||
|
||||
extern "C" void user_init(void) {
|
||||
extern "C" void user_init(void)
|
||||
{
|
||||
struct rst_info *rtc_info_ptr = system_get_rst_info();
|
||||
memcpy((void *)&resetInfo, (void *)rtc_info_ptr, sizeof(resetInfo));
|
||||
|
||||
|
||||
+21
-12
@@ -137,7 +137,9 @@ void print_soft_sign_hmac_key(uint8_t *key_ptr = NULL)
|
||||
printf("#define MY_SOFT_HMAC_KEY ");
|
||||
for (int i=0; i<32; i++) {
|
||||
printf("%#02X", key_ptr[i]);
|
||||
if (i < 31) printf(",");
|
||||
if (i < 31) {
|
||||
printf(",");
|
||||
}
|
||||
}
|
||||
printf("\n\n");
|
||||
}
|
||||
@@ -172,12 +174,13 @@ void set_soft_sign_hmac_key(char *key_str)
|
||||
} else {
|
||||
for (int i = 0; i < 64; ++i) {
|
||||
char c = key_str[i];
|
||||
if (c <= '9')
|
||||
if (c <= '9') {
|
||||
n = c - '0';
|
||||
else if (c >= 'a')
|
||||
} else if (c >= 'a') {
|
||||
n = c - 'a' + 10;
|
||||
else
|
||||
} else {
|
||||
n = c - 'A' + 10;
|
||||
}
|
||||
|
||||
if ((i & 0x1) == 0) {
|
||||
key[i/2] = n * 16;
|
||||
@@ -209,7 +212,9 @@ void print_soft_sign_serial_key(uint8_t *key_ptr = NULL)
|
||||
printf("#define MY_SOFT_SERIAL ");
|
||||
for (int i=0; i<9; i++) {
|
||||
printf("%#02X", key_ptr[i]);
|
||||
if (i < 8) printf(",");
|
||||
if (i < 8) {
|
||||
printf(",");
|
||||
}
|
||||
}
|
||||
printf("\n\n");
|
||||
}
|
||||
@@ -244,12 +249,13 @@ void set_soft_sign_serial_key(char *key_str)
|
||||
} else {
|
||||
for (int i = 0; i < 18; ++i) {
|
||||
char c = key_str[i];
|
||||
if (c <= '9')
|
||||
if (c <= '9') {
|
||||
n = c - '0';
|
||||
else if (c >= 'a')
|
||||
} else if (c >= 'a') {
|
||||
n = c - 'a' + 10;
|
||||
else
|
||||
} else {
|
||||
n = c - 'A' + 10;
|
||||
}
|
||||
|
||||
if ((i & 0x1) == 0) {
|
||||
key[i/2] = n * 16;
|
||||
@@ -281,7 +287,9 @@ void print_aes_key(uint8_t *key_ptr = NULL)
|
||||
printf("#define MY_AES_KEY ");
|
||||
for (int i=0; i<16; i++) {
|
||||
printf("%#02X", key_ptr[i]);
|
||||
if (i < 15) printf(",");
|
||||
if (i < 15) {
|
||||
printf(",");
|
||||
}
|
||||
}
|
||||
printf("\n\n");
|
||||
}
|
||||
@@ -316,12 +324,13 @@ void set_aes_key(char *key_str)
|
||||
} else {
|
||||
for (int i = 0; i < 32; ++i) {
|
||||
char c = key_str[i];
|
||||
if (c <= '9')
|
||||
if (c <= '9') {
|
||||
n = c - '0';
|
||||
else if (c >= 'a')
|
||||
} else if (c >= 'a') {
|
||||
n = c - 'a' + 10;
|
||||
else
|
||||
} else {
|
||||
n = c - 'A' + 10;
|
||||
}
|
||||
|
||||
if ((i & 0x1) == 0) {
|
||||
key[i/2] = n * 16;
|
||||
|
||||
+55
-30
@@ -50,20 +50,24 @@ void MyMessage::clear()
|
||||
miSetVersion(PROTOCOL_VERSION);
|
||||
}
|
||||
|
||||
bool MyMessage::isAck() const {
|
||||
bool MyMessage::isAck() const
|
||||
{
|
||||
return miGetAck();
|
||||
}
|
||||
|
||||
uint8_t MyMessage::getCommand() const {
|
||||
uint8_t MyMessage::getCommand() const
|
||||
{
|
||||
return miGetCommand();
|
||||
}
|
||||
|
||||
/* Getters for payload converted to desired form */
|
||||
void* MyMessage::getCustom() const {
|
||||
void* MyMessage::getCustom() const
|
||||
{
|
||||
return (void *)data;
|
||||
}
|
||||
|
||||
const char* MyMessage::getString() const {
|
||||
const char* MyMessage::getString() const
|
||||
{
|
||||
uint8_t payloadType = miGetPayloadType();
|
||||
if (payloadType == P_STRING) {
|
||||
return data;
|
||||
@@ -73,19 +77,19 @@ const char* MyMessage::getString() const {
|
||||
}
|
||||
|
||||
// handles single character hex (0 - 15)
|
||||
char MyMessage::i2h(uint8_t i) const {
|
||||
char MyMessage::i2h(uint8_t i) const
|
||||
{
|
||||
uint8_t k = i & 0x0F;
|
||||
if (k <= 9) {
|
||||
return '0' + k;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return 'A' + k - 10;
|
||||
}
|
||||
}
|
||||
|
||||
char* MyMessage::getCustomString(char *buffer) const {
|
||||
for (uint8_t i = 0; i < miGetLength(); i++)
|
||||
char* MyMessage::getCustomString(char *buffer) const
|
||||
{
|
||||
for (uint8_t i = 0; i < miGetLength(); i++) {
|
||||
buffer[i * 2] = i2h(data[i] >> 4);
|
||||
buffer[(i * 2) + 1] = i2h(data[i]);
|
||||
}
|
||||
@@ -93,7 +97,8 @@ char* MyMessage::getCustomString(char *buffer) const {
|
||||
return buffer;
|
||||
}
|
||||
|
||||
char* MyMessage::getStream(char *buffer) const {
|
||||
char* MyMessage::getStream(char *buffer) const
|
||||
{
|
||||
uint8_t cmd = miGetCommand();
|
||||
if ((cmd == C_STREAM) && (buffer != NULL)) {
|
||||
return getCustomString(buffer);
|
||||
@@ -102,7 +107,8 @@ char* MyMessage::getStream(char *buffer) const {
|
||||
}
|
||||
}
|
||||
|
||||
char* MyMessage::getString(char *buffer) const {
|
||||
char* MyMessage::getString(char *buffer) const
|
||||
{
|
||||
uint8_t payloadType = miGetPayloadType();
|
||||
if (buffer != NULL) {
|
||||
if (payloadType == P_STRING) {
|
||||
@@ -129,11 +135,13 @@ char* MyMessage::getString(char *buffer) const {
|
||||
}
|
||||
}
|
||||
|
||||
bool MyMessage::getBool() const {
|
||||
bool MyMessage::getBool() const
|
||||
{
|
||||
return getByte();
|
||||
}
|
||||
|
||||
uint8_t MyMessage::getByte() const {
|
||||
uint8_t MyMessage::getByte() const
|
||||
{
|
||||
if (miGetPayloadType() == P_BYTE) {
|
||||
return data[0];
|
||||
} else if (miGetPayloadType() == P_STRING) {
|
||||
@@ -144,7 +152,8 @@ uint8_t MyMessage::getByte() const {
|
||||
}
|
||||
|
||||
|
||||
float MyMessage::getFloat() const {
|
||||
float MyMessage::getFloat() const
|
||||
{
|
||||
if (miGetPayloadType() == P_FLOAT32) {
|
||||
return fValue;
|
||||
} else if (miGetPayloadType() == P_STRING) {
|
||||
@@ -154,7 +163,8 @@ float MyMessage::getFloat() const {
|
||||
}
|
||||
}
|
||||
|
||||
int32_t MyMessage::getLong() const {
|
||||
int32_t MyMessage::getLong() const
|
||||
{
|
||||
if (miGetPayloadType() == P_LONG32) {
|
||||
return lValue;
|
||||
} else if (miGetPayloadType() == P_STRING) {
|
||||
@@ -164,7 +174,8 @@ int32_t MyMessage::getLong() const {
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t MyMessage::getULong() const {
|
||||
uint32_t MyMessage::getULong() const
|
||||
{
|
||||
if (miGetPayloadType() == P_ULONG32) {
|
||||
return ulValue;
|
||||
} else if (miGetPayloadType() == P_STRING) {
|
||||
@@ -174,7 +185,8 @@ uint32_t MyMessage::getULong() const {
|
||||
}
|
||||
}
|
||||
|
||||
int16_t MyMessage::getInt() const {
|
||||
int16_t MyMessage::getInt() const
|
||||
{
|
||||
if (miGetPayloadType() == P_INT16) {
|
||||
return iValue;
|
||||
} else if (miGetPayloadType() == P_STRING) {
|
||||
@@ -184,7 +196,8 @@ int16_t MyMessage::getInt() const {
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t MyMessage::getUInt() const {
|
||||
uint16_t MyMessage::getUInt() const
|
||||
{
|
||||
if (miGetPayloadType() == P_UINT16) {
|
||||
return uiValue;
|
||||
} else if (miGetPayloadType() == P_STRING) {
|
||||
@@ -195,23 +208,27 @@ uint16_t MyMessage::getUInt() const {
|
||||
|
||||
}
|
||||
|
||||
MyMessage& MyMessage::setType(uint8_t _type) {
|
||||
MyMessage& MyMessage::setType(uint8_t _type)
|
||||
{
|
||||
type = _type;
|
||||
return *this;
|
||||
}
|
||||
|
||||
MyMessage& MyMessage::setSensor(uint8_t _sensor) {
|
||||
MyMessage& MyMessage::setSensor(uint8_t _sensor)
|
||||
{
|
||||
sensor = _sensor;
|
||||
return *this;
|
||||
}
|
||||
|
||||
MyMessage& MyMessage::setDestination(uint8_t _destination) {
|
||||
MyMessage& MyMessage::setDestination(uint8_t _destination)
|
||||
{
|
||||
destination = _destination;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Set payload
|
||||
MyMessage& MyMessage::set(void* value, uint8_t length) {
|
||||
MyMessage& MyMessage::set(void* value, uint8_t length)
|
||||
{
|
||||
uint8_t payloadLength = value == NULL ? 0 : min(length, (uint8_t)MAX_PAYLOAD);
|
||||
miSetLength(payloadLength);
|
||||
miSetPayloadType(P_CUSTOM);
|
||||
@@ -219,7 +236,8 @@ MyMessage& MyMessage::set(void* value, uint8_t length) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
MyMessage& MyMessage::set(const char* value) {
|
||||
MyMessage& MyMessage::set(const char* value)
|
||||
{
|
||||
uint8_t length = value == NULL ? 0 : min(strlen(value), (size_t)MAX_PAYLOAD);
|
||||
miSetLength(length);
|
||||
miSetPayloadType(P_STRING);
|
||||
@@ -231,21 +249,24 @@ MyMessage& MyMessage::set(const char* value) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
MyMessage& MyMessage::set(bool value) {
|
||||
MyMessage& MyMessage::set(bool value)
|
||||
{
|
||||
miSetLength(1);
|
||||
miSetPayloadType(P_BYTE);
|
||||
data[0] = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
MyMessage& MyMessage::set(uint8_t value) {
|
||||
MyMessage& MyMessage::set(uint8_t value)
|
||||
{
|
||||
miSetLength(1);
|
||||
miSetPayloadType(P_BYTE);
|
||||
data[0] = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
MyMessage& MyMessage::set(float value, uint8_t decimals) {
|
||||
MyMessage& MyMessage::set(float value, uint8_t decimals)
|
||||
{
|
||||
miSetLength(5); // 32 bit float + persi
|
||||
miSetPayloadType(P_FLOAT32);
|
||||
fValue=value;
|
||||
@@ -253,28 +274,32 @@ MyMessage& MyMessage::set(float value, uint8_t decimals) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
MyMessage& MyMessage::set(uint32_t value) {
|
||||
MyMessage& MyMessage::set(uint32_t value)
|
||||
{
|
||||
miSetPayloadType(P_ULONG32);
|
||||
miSetLength(4);
|
||||
ulValue = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
MyMessage& MyMessage::set(int32_t value) {
|
||||
MyMessage& MyMessage::set(int32_t value)
|
||||
{
|
||||
miSetPayloadType(P_LONG32);
|
||||
miSetLength(4);
|
||||
lValue = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
MyMessage& MyMessage::set(uint16_t value) {
|
||||
MyMessage& MyMessage::set(uint16_t value)
|
||||
{
|
||||
miSetPayloadType(P_UINT16);
|
||||
miSetLength(2);
|
||||
uiValue = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
MyMessage& MyMessage::set(int16_t value) {
|
||||
MyMessage& MyMessage::set(int16_t value)
|
||||
{
|
||||
miSetPayloadType(P_INT16);
|
||||
miSetLength(2);
|
||||
iValue = value;
|
||||
|
||||
+1
-2
@@ -331,8 +331,7 @@ public:
|
||||
#else
|
||||
|
||||
typedef union {
|
||||
struct
|
||||
{
|
||||
struct {
|
||||
|
||||
#endif
|
||||
uint8_t last; // 8 bit - Id of last node this message passed
|
||||
|
||||
@@ -33,7 +33,8 @@ uint8_t _firmwareRetry;
|
||||
|
||||
void readFirmwareSettings(void)
|
||||
{
|
||||
hwReadConfigBlock((void*)&_nodeFirmwareConfig, (void*)EEPROM_FIRMWARE_TYPE_ADDRESS, sizeof(nodeFirmwareConfig_t));
|
||||
hwReadConfigBlock((void*)&_nodeFirmwareConfig, (void*)EEPROM_FIRMWARE_TYPE_ADDRESS,
|
||||
sizeof(nodeFirmwareConfig_t));
|
||||
}
|
||||
|
||||
void firmwareOTAUpdateRequest(void)
|
||||
@@ -54,8 +55,10 @@ void firmwareOTAUpdateRequest(void)
|
||||
firmwareRequest.type = _nodeFirmwareConfig.type;
|
||||
firmwareRequest.version = _nodeFirmwareConfig.version;
|
||||
firmwareRequest.block = (_firmwareBlock - 1);
|
||||
OTA_DEBUG(PSTR("OTA:FRQ:FW REQ,T=%04X,V=%04X,B=%04X\n"), _nodeFirmwareConfig.type, _nodeFirmwareConfig.version, _firmwareBlock - 1); // request FW update block
|
||||
(void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_STREAM, ST_FIRMWARE_REQUEST, false).set(&firmwareRequest, sizeof(requestFirmwareBlock_t)));
|
||||
OTA_DEBUG(PSTR("OTA:FRQ:FW REQ,T=%04X,V=%04X,B=%04X\n"), _nodeFirmwareConfig.type,
|
||||
_nodeFirmwareConfig.version, _firmwareBlock - 1); // request FW update block
|
||||
(void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_STREAM, ST_FIRMWARE_REQUEST,
|
||||
false).set(&firmwareRequest, sizeof(requestFirmwareBlock_t)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,7 +99,8 @@ bool firmwareOTAUpdateProcess(void)
|
||||
// extract FW block
|
||||
replyFirmwareBlock_t *firmwareResponse = (replyFirmwareBlock_t *)_msg.data;
|
||||
// write to flash
|
||||
_flash.writeBytes( ((_firmwareBlock - 1) * FIRMWARE_BLOCK_SIZE) + FIRMWARE_START_OFFSET, firmwareResponse->data, FIRMWARE_BLOCK_SIZE);
|
||||
_flash.writeBytes( ((_firmwareBlock - 1) * FIRMWARE_BLOCK_SIZE) + FIRMWARE_START_OFFSET,
|
||||
firmwareResponse->data, FIRMWARE_BLOCK_SIZE);
|
||||
// wait until flash written
|
||||
while (_flash.busy()) {}
|
||||
_firmwareBlock--;
|
||||
@@ -107,7 +111,8 @@ bool firmwareOTAUpdateProcess(void)
|
||||
if (transportIsValidFirmware()) {
|
||||
OTA_DEBUG(PSTR("OTA:FWP:CRC OK\n")); // FW checksum ok
|
||||
// Write the new firmware config to eeprom
|
||||
hwWriteConfigBlock((void*)&_nodeFirmwareConfig, (void*)EEPROM_FIRMWARE_TYPE_ADDRESS, sizeof(nodeFirmwareConfig_t));
|
||||
hwWriteConfigBlock((void*)&_nodeFirmwareConfig, (void*)EEPROM_FIRMWARE_TYPE_ADDRESS,
|
||||
sizeof(nodeFirmwareConfig_t));
|
||||
// All seems ok, write size and signature to flash (DualOptiboot will pick this up and flash it)
|
||||
const uint16_t firmwareSize = FIRMWARE_BLOCK_SIZE * _nodeFirmwareConfig.blocks;
|
||||
const uint8_t OTAbuffer[FIRMWARE_START_OFFSET] = {'F','L','X','I','M','G',':', (uint8_t)(firmwareSize >> 8), (uint8_t)(firmwareSize & 0xff),':'};
|
||||
@@ -142,7 +147,8 @@ void presentBootloaderInformation(void)
|
||||
// add bootloader information
|
||||
requestFirmwareConfig->BLVersion = MY_OTA_BOOTLOADER_VERSION;
|
||||
_firmwareUpdateOngoing = false;
|
||||
(void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_STREAM, ST_FIRMWARE_CONFIG_REQUEST, false));
|
||||
(void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_STREAM,
|
||||
ST_FIRMWARE_CONFIG_REQUEST, false));
|
||||
}
|
||||
bool isFirmwareUpdateOngoing(void)
|
||||
{
|
||||
@@ -158,8 +164,7 @@ bool transportIsValidFirmware(void)
|
||||
for (int8_t j = 0; j < 8; ++j) {
|
||||
if (crc & 1) {
|
||||
crc = (crc >> 1) ^ 0xA001;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
crc = (crc >> 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,8 @@ uint8_t protocolH2i(char c);
|
||||
char _fmtBuffer[MY_GATEWAY_MAX_SEND_LENGTH];
|
||||
char _convBuffer[MAX_PAYLOAD*2+1];
|
||||
|
||||
bool protocolParse(MyMessage &message, char *inputString) {
|
||||
bool protocolParse(MyMessage &message, char *inputString)
|
||||
{
|
||||
char *str, *p, *value=NULL;
|
||||
uint8_t bvalue[MAX_PAYLOAD];
|
||||
uint8_t blen = 0;
|
||||
@@ -91,30 +92,36 @@ bool protocolParse(MyMessage &message, char *inputString) {
|
||||
mSetAck(message, false);
|
||||
if (command == C_STREAM) {
|
||||
message.set(bvalue, blen);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
message.set(value);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
char * protocolFormat(MyMessage &message) {
|
||||
snprintf_P(_fmtBuffer, MY_GATEWAY_MAX_SEND_LENGTH, PSTR("%d;%d;%d;%d;%d;%s\n"), message.sender, message.sensor, (uint8_t)mGetCommand(message), (uint8_t)mGetAck(message), message.type, message.getString(_convBuffer));
|
||||
char * protocolFormat(MyMessage &message)
|
||||
{
|
||||
snprintf_P(_fmtBuffer, MY_GATEWAY_MAX_SEND_LENGTH, PSTR("%d;%d;%d;%d;%d;%s\n"), message.sender,
|
||||
message.sensor, (uint8_t)mGetCommand(message), (uint8_t)mGetAck(message), message.type,
|
||||
message.getString(_convBuffer));
|
||||
return _fmtBuffer;
|
||||
}
|
||||
|
||||
char * protocolFormatMQTTTopic(const char* prefix, MyMessage &message) {
|
||||
snprintf_P(_fmtBuffer, MY_GATEWAY_MAX_SEND_LENGTH, PSTR("%s/%d/%d/%d/%d/%d"), prefix, message.sender, message.sensor, mGetCommand(message), mGetAck(message), message.type);
|
||||
char * protocolFormatMQTTTopic(const char* prefix, MyMessage &message)
|
||||
{
|
||||
snprintf_P(_fmtBuffer, MY_GATEWAY_MAX_SEND_LENGTH, PSTR("%s/%d/%d/%d/%d/%d"), prefix,
|
||||
message.sender, message.sensor, mGetCommand(message), mGetAck(message), message.type);
|
||||
return _fmtBuffer;
|
||||
}
|
||||
|
||||
char * protocolFormatMQTTSubscribe(const char* prefix) {
|
||||
char * protocolFormatMQTTSubscribe(const char* prefix)
|
||||
{
|
||||
snprintf_P(_fmtBuffer, MY_GATEWAY_MAX_SEND_LENGTH, PSTR("%s/+/+/+/+/+"), prefix);
|
||||
return _fmtBuffer;
|
||||
}
|
||||
|
||||
#ifdef MY_GATEWAY_MQTT_CLIENT
|
||||
bool protocolMQTTParse(MyMessage &message, char* topic, uint8_t* payload, unsigned int length) {
|
||||
bool protocolMQTTParse(MyMessage &message, char* topic, uint8_t* payload, unsigned int length)
|
||||
{
|
||||
char *str, *p;
|
||||
uint8_t i = 0;
|
||||
uint8_t bvalue[MAX_PAYLOAD];
|
||||
@@ -188,15 +195,14 @@ bool protocolMQTTParse(MyMessage &message, char* topic, uint8_t* payload, unsign
|
||||
}
|
||||
#endif
|
||||
|
||||
uint8_t protocolH2i(char c) {
|
||||
uint8_t protocolH2i(char c)
|
||||
{
|
||||
uint8_t i = 0;
|
||||
if (c <= '9') {
|
||||
i += c - '0';
|
||||
}
|
||||
else if (c >= 'a') {
|
||||
} else if (c >= 'a') {
|
||||
i += c - 'a' + 10;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
i += c - 'A' + 10;
|
||||
}
|
||||
return i;
|
||||
|
||||
+115
-82
@@ -47,7 +47,8 @@ void _callbackTransportReady(void)
|
||||
}
|
||||
}
|
||||
|
||||
void _process(void) {
|
||||
void _process(void)
|
||||
{
|
||||
doYield();
|
||||
|
||||
#if defined(MY_INCLUSION_MODE_FEATURE)
|
||||
@@ -68,7 +69,8 @@ void _process(void) {
|
||||
#endif
|
||||
}
|
||||
|
||||
void _infiniteLoop(void) {
|
||||
void _infiniteLoop(void)
|
||||
{
|
||||
while(1) {
|
||||
doYield();
|
||||
#if defined(__linux__)
|
||||
@@ -77,7 +79,8 @@ void _infiniteLoop(void) {
|
||||
}
|
||||
}
|
||||
|
||||
void _begin(void) {
|
||||
void _begin(void)
|
||||
{
|
||||
// reset wdt
|
||||
hwWatchdogReset();
|
||||
|
||||
@@ -87,7 +90,8 @@ void _begin(void) {
|
||||
|
||||
hwInit();
|
||||
|
||||
CORE_DEBUG(PSTR("MCO:BGN:INIT " MY_NODE_TYPE ",CP=" MY_CAPABILITIES ",VER=" MYSENSORS_LIBRARY_VERSION "\n"));
|
||||
CORE_DEBUG(PSTR("MCO:BGN:INIT " MY_NODE_TYPE ",CP=" MY_CAPABILITIES ",VER="
|
||||
MYSENSORS_LIBRARY_VERSION "\n"));
|
||||
|
||||
// set defaults
|
||||
_coreConfig.presentationSent = false;
|
||||
@@ -106,7 +110,8 @@ void _begin(void) {
|
||||
|
||||
// Read latest received controller configuration from EEPROM
|
||||
// Note: _coreConfig.isMetric is bool, hence empty EEPROM (=0xFF) evaluates to true (default)
|
||||
hwReadConfigBlock((void*)&_coreConfig.controllerConfig, (void*)EEPROM_CONTROLLER_CONFIG_ADDRESS, sizeof(controllerConfig_t));
|
||||
hwReadConfigBlock((void*)&_coreConfig.controllerConfig, (void*)EEPROM_CONTROLLER_CONFIG_ADDRESS,
|
||||
sizeof(controllerConfig_t));
|
||||
|
||||
#if defined(MY_OTA_FIRMWARE_FEATURE)
|
||||
// Read firmware config from EEPROM, i.e. type, version, CRC, blocks
|
||||
@@ -164,7 +169,8 @@ void _registerNode(void)
|
||||
uint8_t counter = MY_REGISTRATION_RETRIES;
|
||||
// only proceed if register response received or retries exceeded
|
||||
do {
|
||||
(void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_REGISTRATION_REQUEST).set(MY_CORE_VERSION));
|
||||
(void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL,
|
||||
I_REGISTRATION_REQUEST).set(MY_CORE_VERSION));
|
||||
} while (!wait(2000, C_INTERNAL, I_REGISTRATION_RESPONSE) && counter--);
|
||||
#else
|
||||
_coreConfig.nodeRegistered = true;
|
||||
@@ -172,7 +178,8 @@ void _registerNode(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
void presentNode(void) {
|
||||
void presentNode(void)
|
||||
{
|
||||
setIndication(INDICATION_PRESENT);
|
||||
// Present node and request config
|
||||
#if defined(MY_GATEWAY_FEATURE)
|
||||
@@ -200,7 +207,8 @@ void presentNode(void) {
|
||||
|
||||
// Send a configuration exchange request to controller
|
||||
// Node sends parent node. Controller answers with latest node configuration
|
||||
(void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_CONFIG).set(getParentNodeId()));
|
||||
(void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL,
|
||||
I_CONFIG).set(getParentNodeId()));
|
||||
|
||||
// Wait configuration reply.
|
||||
(void)wait(2000, C_INTERNAL, I_CONFIG);
|
||||
@@ -240,12 +248,14 @@ uint8_t getDistanceGW(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
controllerConfig_t getConfig(void) {
|
||||
controllerConfig_t getConfig(void)
|
||||
{
|
||||
return _coreConfig.controllerConfig;
|
||||
}
|
||||
|
||||
|
||||
bool _sendRoute(MyMessage &message) {
|
||||
bool _sendRoute(MyMessage &message)
|
||||
{
|
||||
#if defined(MY_CORE_ONLY)
|
||||
(void)message;
|
||||
#endif
|
||||
@@ -263,7 +273,8 @@ bool _sendRoute(MyMessage &message) {
|
||||
#endif
|
||||
}
|
||||
|
||||
bool send(MyMessage &message, const bool enableAck) {
|
||||
bool send(MyMessage &message, const bool enableAck)
|
||||
{
|
||||
message.sender = getNodeId();
|
||||
mSetCommand(message, C_SET);
|
||||
mSetRequestAck(message, enableAck);
|
||||
@@ -271,8 +282,7 @@ bool send(MyMessage &message, const bool enableAck) {
|
||||
#if defined(MY_REGISTRATION_FEATURE) && !defined(MY_GATEWAY_FEATURE)
|
||||
if (_coreConfig.nodeRegistered) {
|
||||
return _sendRoute(message);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
CORE_DEBUG(PSTR("!MCO:SND:NODE NOT REG\n")); // node not registered
|
||||
return false;
|
||||
}
|
||||
@@ -281,45 +291,58 @@ bool send(MyMessage &message, const bool enableAck) {
|
||||
#endif
|
||||
}
|
||||
|
||||
bool sendBatteryLevel(const uint8_t value, const bool ack) {
|
||||
return _sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_BATTERY_LEVEL, ack).set(value));
|
||||
bool sendBatteryLevel(const uint8_t value, const bool ack)
|
||||
{
|
||||
return _sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_BATTERY_LEVEL,
|
||||
ack).set(value));
|
||||
}
|
||||
|
||||
bool sendHeartbeat(const bool ack) {
|
||||
bool sendHeartbeat(const bool ack)
|
||||
{
|
||||
#if defined(MY_SENSOR_NETWORK)
|
||||
const uint32_t heartbeat = transportGetHeartbeat();
|
||||
return _sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_HEARTBEAT_RESPONSE, ack).set(heartbeat));
|
||||
return _sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_HEARTBEAT_RESPONSE,
|
||||
ack).set(heartbeat));
|
||||
#else
|
||||
(void)ack;
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool present(const uint8_t childSensorId, const uint8_t sensorType, const char *description, const bool ack) {
|
||||
return _sendRoute(build(_msgTmp, GATEWAY_ADDRESS, childSensorId, C_PRESENTATION, sensorType, ack).set(childSensorId==NODE_SENSOR_ID?MYSENSORS_LIBRARY_VERSION:description));
|
||||
bool present(const uint8_t childSensorId, const uint8_t sensorType, const char *description,
|
||||
const bool ack)
|
||||
{
|
||||
return _sendRoute(build(_msgTmp, GATEWAY_ADDRESS, childSensorId, C_PRESENTATION, sensorType,
|
||||
ack).set(childSensorId==NODE_SENSOR_ID?MYSENSORS_LIBRARY_VERSION:description));
|
||||
}
|
||||
|
||||
bool sendSketchInfo(const char *name, const char *version, const bool ack) {
|
||||
bool sendSketchInfo(const char *name, const char *version, const bool ack)
|
||||
{
|
||||
bool result = true;
|
||||
if (name) {
|
||||
result &= _sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_SKETCH_NAME, ack).set(name));
|
||||
result &= _sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_SKETCH_NAME,
|
||||
ack).set(name));
|
||||
}
|
||||
if (version) {
|
||||
result &= _sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_SKETCH_VERSION, ack).set(version));
|
||||
result &= _sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_SKETCH_VERSION,
|
||||
ack).set(version));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool request(const uint8_t childSensorId, const uint8_t variableType, const uint8_t destination) {
|
||||
bool request(const uint8_t childSensorId, const uint8_t variableType, const uint8_t destination)
|
||||
{
|
||||
return _sendRoute(build(_msgTmp, destination, childSensorId, C_REQ, variableType).set(""));
|
||||
}
|
||||
|
||||
bool requestTime(const bool ack) {
|
||||
bool requestTime(const bool ack)
|
||||
{
|
||||
return _sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_TIME, ack).set(""));
|
||||
}
|
||||
|
||||
// Message delivered through _msg
|
||||
bool _processInternalMessages(void) {
|
||||
bool _processInternalMessages(void)
|
||||
{
|
||||
const uint8_t type = _msg.type;
|
||||
|
||||
if (_msg.sender == GATEWAY_ADDRESS) {
|
||||
@@ -329,33 +352,29 @@ bool _processInternalMessages(void) {
|
||||
setIndication(INDICATION_REBOOT);
|
||||
hwReboot();
|
||||
#endif
|
||||
}
|
||||
else if (type == I_REGISTRATION_RESPONSE) {
|
||||
} else if (type == I_REGISTRATION_RESPONSE) {
|
||||
#if defined (MY_REGISTRATION_FEATURE) && !defined(MY_GATEWAY_FEATURE)
|
||||
_coreConfig.nodeRegistered = _msg.getBool();
|
||||
setIndication(INDICATION_GOT_REGISTRATION);
|
||||
CORE_DEBUG(PSTR("MCO:PIM:NODE REG=%d\n"), _coreConfig.nodeRegistered); // node registration
|
||||
#endif
|
||||
}
|
||||
else if (type == I_CONFIG) {
|
||||
} else if (type == I_CONFIG) {
|
||||
// Pick up configuration from controller (currently only metric/imperial) and store it in eeprom if changed
|
||||
_coreConfig.controllerConfig.isMetric = _msg.data[0] == 0x00 || _msg.data[0] == 'M'; // metric if null terminated or M
|
||||
hwWriteConfigBlock((void*)&_coreConfig.controllerConfig, (void*)EEPROM_CONTROLLER_CONFIG_ADDRESS, sizeof(controllerConfig_t));
|
||||
}
|
||||
else if (type == I_PRESENTATION) {
|
||||
_coreConfig.controllerConfig.isMetric = _msg.data[0] == 0x00 ||
|
||||
_msg.data[0] == 'M'; // metric if null terminated or M
|
||||
hwWriteConfigBlock((void*)&_coreConfig.controllerConfig, (void*)EEPROM_CONTROLLER_CONFIG_ADDRESS,
|
||||
sizeof(controllerConfig_t));
|
||||
} else if (type == I_PRESENTATION) {
|
||||
// Re-send node presentation to controller
|
||||
presentNode();
|
||||
}
|
||||
else if (type == I_HEARTBEAT_REQUEST) {
|
||||
} else if (type == I_HEARTBEAT_REQUEST) {
|
||||
(void)sendHeartbeat();
|
||||
}
|
||||
else if (type == I_TIME) {
|
||||
} else if (type == I_TIME) {
|
||||
// Deliver time to callback
|
||||
if (receiveTime) {
|
||||
receiveTime(_msg.getULong());
|
||||
}
|
||||
}
|
||||
else if (type == I_CHILDREN) {
|
||||
} else if (type == I_CHILDREN) {
|
||||
#if defined(MY_REPEATER_FEATURE)
|
||||
if (_msg.data[0] == 'C') {
|
||||
// Clears child relay data for this node
|
||||
@@ -364,8 +383,7 @@ bool _processInternalMessages(void) {
|
||||
(void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_CHILDREN).set("OK"));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else if (type == I_DEBUG) {
|
||||
} else if (type == I_DEBUG) {
|
||||
#if defined(MY_DEBUG) || defined(MY_SPECIAL_DEBUG)
|
||||
const char debug_msg = _msg.data[0];
|
||||
if (debug_msg == 'R') { // routing table
|
||||
@@ -375,22 +393,22 @@ bool _processInternalMessages(void) {
|
||||
if (route != BROADCAST_ADDRESS) {
|
||||
CORE_DEBUG(PSTR("MCO:PIM:ROUTE N=%d,R=%d\n"), cnt, route);
|
||||
uint8_t outBuf[2] = { (uint8_t)cnt,route };
|
||||
(void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_DEBUG).set(outBuf, 2));
|
||||
(void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_DEBUG).set(outBuf,
|
||||
2));
|
||||
wait(200);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else if (debug_msg == 'V') { // CPU voltage
|
||||
(void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_DEBUG).set(hwCPUVoltage()));
|
||||
}
|
||||
else if (debug_msg == 'F') { // CPU frequency in 1/10Mhz
|
||||
(void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_DEBUG).set(hwCPUFrequency()));
|
||||
}
|
||||
else if (debug_msg == 'M') { // free memory
|
||||
(void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_DEBUG).set(hwFreeMem()));
|
||||
}
|
||||
else if (debug_msg == 'E') { // clear MySensors eeprom area and reboot
|
||||
} else if (debug_msg == 'V') { // CPU voltage
|
||||
(void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL,
|
||||
I_DEBUG).set(hwCPUVoltage()));
|
||||
} else if (debug_msg == 'F') { // CPU frequency in 1/10Mhz
|
||||
(void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL,
|
||||
I_DEBUG).set(hwCPUFrequency()));
|
||||
} else if (debug_msg == 'M') { // free memory
|
||||
(void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL,
|
||||
I_DEBUG).set(hwFreeMem()));
|
||||
} else if (debug_msg == 'E') { // clear MySensors eeprom area and reboot
|
||||
(void)_sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_DEBUG).set("OK"));
|
||||
for (int i = EEPROM_START; i<EEPROM_LOCAL_CONFIG_ADDRESS; i++) {
|
||||
hwWriteConfig(i, 0xFF);
|
||||
@@ -399,10 +417,10 @@ bool _processInternalMessages(void) {
|
||||
hwReboot();
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
else return false;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// sender is a node
|
||||
if (type == I_REGISTRATION_REQUEST) {
|
||||
#if defined(MY_GATEWAY_FEATURE)
|
||||
@@ -419,34 +437,40 @@ bool _processInternalMessages(void) {
|
||||
// delay for fast GW and slow nodes
|
||||
delay(5);
|
||||
#endif
|
||||
(void)_sendRoute(build(_msgTmp, _msg.sender, NODE_SENSOR_ID, C_INTERNAL, I_REGISTRATION_RESPONSE).set(approveRegistration));
|
||||
(void)_sendRoute(build(_msgTmp, _msg.sender, NODE_SENSOR_ID, C_INTERNAL,
|
||||
I_REGISTRATION_RESPONSE).set(approveRegistration));
|
||||
#else
|
||||
return false; // processing of this request via controller
|
||||
#endif
|
||||
#endif
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
else return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void saveState(const uint8_t pos, const uint8_t value) {
|
||||
void saveState(const uint8_t pos, const uint8_t value)
|
||||
{
|
||||
hwWriteConfig(EEPROM_LOCAL_CONFIG_ADDRESS+pos, value);
|
||||
}
|
||||
uint8_t loadState(const uint8_t pos) {
|
||||
uint8_t loadState(const uint8_t pos)
|
||||
{
|
||||
return hwReadConfig(EEPROM_LOCAL_CONFIG_ADDRESS+pos);
|
||||
}
|
||||
|
||||
|
||||
void wait(const uint32_t waitingMS) {
|
||||
void wait(const uint32_t waitingMS)
|
||||
{
|
||||
const uint32_t enteringMS = hwMillis();
|
||||
while (hwMillis() - enteringMS < waitingMS) {
|
||||
_process();
|
||||
}
|
||||
}
|
||||
|
||||
bool wait(const uint32_t waitingMS, const uint8_t cmd, const uint8_t msgType) {
|
||||
bool wait(const uint32_t waitingMS, const uint8_t cmd, const uint8_t msgType)
|
||||
{
|
||||
const uint32_t enteringMS = hwMillis();
|
||||
// invalidate msg type
|
||||
_msg.type = !msgType;
|
||||
@@ -458,7 +482,8 @@ bool wait(const uint32_t waitingMS, const uint8_t cmd, const uint8_t msgType) {
|
||||
return expectedResponse;
|
||||
}
|
||||
|
||||
void doYield(void) {
|
||||
void doYield(void)
|
||||
{
|
||||
hwWatchdogReset();
|
||||
|
||||
yield();
|
||||
@@ -468,8 +493,11 @@ void doYield(void) {
|
||||
#endif
|
||||
}
|
||||
|
||||
int8_t _sleep(const uint32_t sleepingMS, const bool smartSleep, const uint8_t interrupt1, const uint8_t mode1, const uint8_t interrupt2, const uint8_t mode2) {
|
||||
CORE_DEBUG(PSTR("MCO:SLP:MS=%lu,SMS=%d,I1=%d,M1=%d,I2=%d,M2=%d\n"), sleepingMS, smartSleep, interrupt1, mode1, interrupt2, mode2);
|
||||
int8_t _sleep(const uint32_t sleepingMS, const bool smartSleep, const uint8_t interrupt1,
|
||||
const uint8_t mode1, const uint8_t interrupt2, const uint8_t mode2)
|
||||
{
|
||||
CORE_DEBUG(PSTR("MCO:SLP:MS=%lu,SMS=%d,I1=%d,M1=%d,I2=%d,M2=%d\n"), sleepingMS, smartSleep,
|
||||
interrupt1, mode1, interrupt2, mode2);
|
||||
// OTA FW feature: do not sleep if FW update ongoing
|
||||
#if defined(MY_OTA_FIRMWARE_FEATURE)
|
||||
if (isFirmwareUpdateOngoing()) {
|
||||
@@ -497,7 +525,8 @@ int8_t _sleep(const uint32_t sleepingMS, const bool smartSleep, const uint8_t in
|
||||
CORE_DEBUG(PSTR("!MCO:SLP:TNR\n")); // sleeping not possible, transport not ready
|
||||
const uint32_t sleepEnterMS = hwMillis();
|
||||
uint32_t sleepDeltaMS = 0;
|
||||
while (!isTransportReady() && (sleepDeltaMS < sleepingTimeMS) && (sleepDeltaMS < MY_SLEEP_TRANSPORT_RECONNECT_TIMEOUT_MS)) {
|
||||
while (!isTransportReady() && (sleepDeltaMS < sleepingTimeMS) &&
|
||||
(sleepDeltaMS < MY_SLEEP_TRANSPORT_RECONNECT_TIMEOUT_MS)) {
|
||||
_process();
|
||||
sleepDeltaMS = hwMillis() - sleepEnterMS;
|
||||
}
|
||||
@@ -505,8 +534,7 @@ int8_t _sleep(const uint32_t sleepingMS, const bool smartSleep, const uint8_t in
|
||||
if (sleepDeltaMS < sleepingTimeMS) {
|
||||
sleepingTimeMS -= sleepDeltaMS; // calculate remaining sleeping time
|
||||
CORE_DEBUG(PSTR("MCO:SLP:MS=%lu\n"), sleepingTimeMS);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// no sleeping time left
|
||||
return MY_SLEEP_NOT_POSSIBLE;
|
||||
}
|
||||
@@ -538,12 +566,10 @@ int8_t _sleep(const uint32_t sleepingMS, const bool smartSleep, const uint8_t in
|
||||
if (interrupt1 != INTERRUPT_NOT_DEFINED && interrupt2 != INTERRUPT_NOT_DEFINED) {
|
||||
// both IRQs
|
||||
result = hwSleep(interrupt1, mode1, interrupt2, mode2, sleepingTimeMS);
|
||||
}
|
||||
else if (interrupt1 != INTERRUPT_NOT_DEFINED && interrupt2 == INTERRUPT_NOT_DEFINED) {
|
||||
} else if (interrupt1 != INTERRUPT_NOT_DEFINED && interrupt2 == INTERRUPT_NOT_DEFINED) {
|
||||
// one IRQ
|
||||
result = hwSleep(interrupt1, mode1, sleepingTimeMS);
|
||||
}
|
||||
else if (interrupt1 == INTERRUPT_NOT_DEFINED && interrupt2 == INTERRUPT_NOT_DEFINED) {
|
||||
} else if (interrupt1 == INTERRUPT_NOT_DEFINED && interrupt2 == INTERRUPT_NOT_DEFINED) {
|
||||
// no IRQ
|
||||
result = hwSleep(sleepingTimeMS);
|
||||
}
|
||||
@@ -555,30 +581,39 @@ int8_t _sleep(const uint32_t sleepingMS, const bool smartSleep, const uint8_t in
|
||||
}
|
||||
|
||||
// sleep functions
|
||||
int8_t sleep(const uint32_t sleepingMS, const bool smartSleep) {
|
||||
int8_t sleep(const uint32_t sleepingMS, const bool smartSleep)
|
||||
{
|
||||
return _sleep(sleepingMS, smartSleep);
|
||||
}
|
||||
|
||||
int8_t sleep(const uint8_t interrupt, const uint8_t mode, const uint32_t sleepingMS, const bool smartSleep) {
|
||||
int8_t sleep(const uint8_t interrupt, const uint8_t mode, const uint32_t sleepingMS,
|
||||
const bool smartSleep)
|
||||
{
|
||||
return _sleep(sleepingMS, smartSleep, interrupt, mode);
|
||||
}
|
||||
|
||||
int8_t sleep(const uint8_t interrupt1, const uint8_t mode1, const uint8_t interrupt2, const uint8_t mode2, const uint32_t sleepingMS, const bool smartSleep) {
|
||||
int8_t sleep(const uint8_t interrupt1, const uint8_t mode1, const uint8_t interrupt2,
|
||||
const uint8_t mode2, const uint32_t sleepingMS, const bool smartSleep)
|
||||
{
|
||||
return _sleep(sleepingMS, smartSleep, interrupt1, mode1, interrupt2, mode2);
|
||||
}
|
||||
|
||||
// deprecated smartSleep() functions
|
||||
int8_t smartSleep(const uint32_t sleepingMS) {
|
||||
int8_t smartSleep(const uint32_t sleepingMS)
|
||||
{
|
||||
// compatibility
|
||||
return _sleep(sleepingMS, true);
|
||||
}
|
||||
|
||||
int8_t smartSleep(const uint8_t interrupt, const uint8_t mode, const uint32_t sleepingMS) {
|
||||
int8_t smartSleep(const uint8_t interrupt, const uint8_t mode, const uint32_t sleepingMS)
|
||||
{
|
||||
// compatibility
|
||||
return _sleep(sleepingMS, true, interrupt, mode);
|
||||
}
|
||||
|
||||
int8_t smartSleep(const uint8_t interrupt1, const uint8_t mode1, const uint8_t interrupt2, const uint8_t mode2, const uint32_t sleepingMS) {
|
||||
int8_t smartSleep(const uint8_t interrupt1, const uint8_t mode1, const uint8_t interrupt2,
|
||||
const uint8_t mode2, const uint32_t sleepingMS)
|
||||
{
|
||||
// compatibility
|
||||
return _sleep(sleepingMS, true, interrupt1, mode1, interrupt2, mode2);
|
||||
}
|
||||
@@ -625,14 +660,12 @@ void _checkNodeLock(void)
|
||||
hwPinMode(MY_NODE_UNLOCK_PIN, INPUT);
|
||||
setIndication(INDICATION_ERR_LOCKED);
|
||||
CORE_DEBUG(PSTR("MCO:BGN:NODE UNLOCKED\n"));
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// Disable pullup
|
||||
hwPinMode(MY_NODE_UNLOCK_PIN, INPUT);
|
||||
_nodeLock("LDB"); //Locked during boot
|
||||
}
|
||||
}
|
||||
else if (hwReadConfig(EEPROM_NODE_LOCK_COUNTER) == 0xFF) {
|
||||
} else if (hwReadConfig(EEPROM_NODE_LOCK_COUNTER) == 0xFF) {
|
||||
// Reset walue
|
||||
hwWriteConfig(EEPROM_NODE_LOCK_COUNTER, MY_NODE_LOCK_COUNTER_MAX);
|
||||
}
|
||||
|
||||
+18
-8
@@ -143,7 +143,8 @@ void presentNode(void);
|
||||
* @param description A textual description of the sensor.
|
||||
* @return true Returns true if message reached the first stop on its way to destination.
|
||||
*/
|
||||
bool present(const uint8_t sensorId, const uint8_t sensorType, const char *description="", const bool ack = false);
|
||||
bool present(const uint8_t sensorId, const uint8_t sensorType, const char *description="",
|
||||
const bool ack = false);
|
||||
|
||||
/**
|
||||
* Sends sketch meta information to the gateway. Not mandatory but a nice thing to do.
|
||||
@@ -189,7 +190,8 @@ bool sendHeartbeat(const bool ack = false);
|
||||
* @param destination The nodeId of other node in radio network. Default is gateway
|
||||
* @return true Returns true if message reached the first stop on its way to destination.
|
||||
*/
|
||||
bool request(const uint8_t childSensorId, const uint8_t variableType, const uint8_t destination = GATEWAY_ADDRESS);
|
||||
bool request(const uint8_t childSensorId, const uint8_t variableType,
|
||||
const uint8_t destination = GATEWAY_ADDRESS);
|
||||
|
||||
/**
|
||||
* Requests time from controller. Answer will be delivered to receiveTime function in sketch.
|
||||
@@ -269,7 +271,8 @@ int8_t sleep(const uint32_t sleepingMS, const bool smartSleep = false);
|
||||
* @param smartSleep Set True if sending heartbeat and process incoming messages before going to sleep
|
||||
* @return Interrupt number if wake up was triggered by pin change, @ref MY_WAKE_UP_BY_TIMER if wake up was triggered by timer, @ref MY_SLEEP_NOT_POSSIBLE if sleep was not possible (e.g. ongoing FW update)
|
||||
*/
|
||||
int8_t sleep(const uint8_t interrupt, const uint8_t mode, const uint32_t sleepingMS = 0, const bool smartSleep = false);
|
||||
int8_t sleep(const uint8_t interrupt, const uint8_t mode, const uint32_t sleepingMS = 0,
|
||||
const bool smartSleep = false);
|
||||
|
||||
/**
|
||||
* Sleep (PowerDownMode) the MCU and radio. Wake up on timer or pin change for two separate interrupts.
|
||||
@@ -283,7 +286,8 @@ int8_t sleep(const uint8_t interrupt, const uint8_t mode, const uint32_t sleepin
|
||||
* @param smartSleep Set True if sending heartbeat and process incoming messages before going to sleep.
|
||||
* @return Interrupt number if wake up was triggered by pin change, @ref MY_WAKE_UP_BY_TIMER if wake up was triggered by timer, @ref MY_SLEEP_NOT_POSSIBLE if sleep was not possible (e.g. ongoing FW update)
|
||||
*/
|
||||
int8_t sleep(const uint8_t interrupt1, const uint8_t mode1, const uint8_t interrupt2, const uint8_t mode2, const uint32_t sleepingMS = 0, const bool smartSleep = false);
|
||||
int8_t sleep(const uint8_t interrupt1, const uint8_t mode1, const uint8_t interrupt2,
|
||||
const uint8_t mode2, const uint32_t sleepingMS = 0, const bool smartSleep = false);
|
||||
|
||||
/**
|
||||
* \deprecated Use sleep(ms, true) instead
|
||||
@@ -316,7 +320,8 @@ int8_t smartSleep(const uint8_t interrupt, const uint8_t mode, const uint32_t sl
|
||||
* @param sleepingMS Number of milliseconds to sleep or 0 to sleep forever
|
||||
* @return Interrupt number if wake up was triggered by pin change, @ref MY_WAKE_UP_BY_TIMER if wake up was triggered by timer, @ref MY_SLEEP_NOT_POSSIBLE if sleep was not possible (e.g. ongoing FW update)
|
||||
*/
|
||||
int8_t smartSleep(const uint8_t interrupt1, const uint8_t mode1, const uint8_t interrupt2, const uint8_t mode2, const uint32_t sleepingMS = 0);
|
||||
int8_t smartSleep(const uint8_t interrupt1, const uint8_t mode1, const uint8_t interrupt2,
|
||||
const uint8_t mode2, const uint32_t sleepingMS = 0);
|
||||
|
||||
/**
|
||||
* Sleep (PowerDownMode) the MCU and radio. Wake up on timer or pin change for two separate interrupts.
|
||||
@@ -330,7 +335,9 @@ int8_t smartSleep(const uint8_t interrupt1, const uint8_t mode1, const uint8_t i
|
||||
* @param smartSleep (optional) Set True if sending heartbeat and process incoming messages before going to sleep.
|
||||
* @return Interrupt number if wake up was triggered by pin change, @ref MY_WAKE_UP_BY_TIMER if wake up was triggered by timer, @ref MY_SLEEP_NOT_POSSIBLE if sleep was not possible (e.g. ongoing FW update)
|
||||
*/
|
||||
int8_t _sleep(const uint32_t sleepingMS, const bool smartSleep = false, const uint8_t interrupt1 = INTERRUPT_NOT_DEFINED, const uint8_t mode1 = MODE_NOT_DEFINED, const uint8_t interrupt2 = INTERRUPT_NOT_DEFINED, const uint8_t mode2 = MODE_NOT_DEFINED);
|
||||
int8_t _sleep(const uint32_t sleepingMS, const bool smartSleep = false,
|
||||
const uint8_t interrupt1 = INTERRUPT_NOT_DEFINED, const uint8_t mode1 = MODE_NOT_DEFINED,
|
||||
const uint8_t interrupt2 = INTERRUPT_NOT_DEFINED, const uint8_t mode2 = MODE_NOT_DEFINED);
|
||||
|
||||
|
||||
/**
|
||||
@@ -412,7 +419,9 @@ void loop(void) __attribute__((weak));
|
||||
|
||||
|
||||
// Inline function and macros
|
||||
static inline MyMessage& build(MyMessage &msg, const uint8_t destination, const uint8_t sensor, const uint8_t command, const uint8_t type, const bool ack = false) {
|
||||
static inline MyMessage& build(MyMessage &msg, const uint8_t destination, const uint8_t sensor,
|
||||
const uint8_t command, const uint8_t type, const bool ack = false)
|
||||
{
|
||||
msg.sender = getNodeId();
|
||||
msg.destination = destination;
|
||||
msg.sensor = sensor;
|
||||
@@ -423,7 +432,8 @@ static inline MyMessage& build(MyMessage &msg, const uint8_t destination, const
|
||||
return msg;
|
||||
}
|
||||
|
||||
static inline MyMessage& buildGw(MyMessage &msg, const uint8_t type) {
|
||||
static inline MyMessage& buildGw(MyMessage &msg, const uint8_t type)
|
||||
{
|
||||
msg.sender = GATEWAY_ADDRESS;
|
||||
msg.destination = GATEWAY_ADDRESS;
|
||||
msg.sensor = NODE_SENSOR_ID;
|
||||
|
||||
+23
-13
@@ -82,12 +82,14 @@ extern bool signerAtsha204SignMsg(MyMessage &msg);
|
||||
#endif
|
||||
|
||||
// Helper function to centralize signing/verification exceptions
|
||||
static bool skipSign(MyMessage &msg) {
|
||||
static bool skipSign(MyMessage &msg)
|
||||
{
|
||||
if mGetAck(msg) {
|
||||
SIGN_DEBUG(PSTR("Skipping security for ACK on command %d type %d\n"), mGetCommand(msg), msg.type);
|
||||
return true;
|
||||
} else if (mGetCommand(msg) == C_INTERNAL &&
|
||||
(msg.type == I_NONCE_REQUEST || msg.type == I_NONCE_RESPONSE || msg.type == I_SIGNING_PRESENTATION ||
|
||||
(msg.type == I_NONCE_REQUEST || msg.type == I_NONCE_RESPONSE ||
|
||||
msg.type == I_SIGNING_PRESENTATION ||
|
||||
msg.type == I_ID_REQUEST || msg.type == I_ID_RESPONSE ||
|
||||
msg.type == I_FIND_PARENT_REQUEST || msg.type == I_FIND_PARENT_RESPONSE ||
|
||||
msg.type == I_HEARTBEAT_REQUEST || msg.type == I_HEARTBEAT_RESPONSE ||
|
||||
@@ -107,7 +109,8 @@ static bool skipSign(MyMessage &msg) {
|
||||
#endif // MY_SIGNING_FEATURE
|
||||
|
||||
// Helper to prepare a signing presentation message
|
||||
static void prepareSigningPresentation(MyMessage &msg, uint8_t destination) {
|
||||
static void prepareSigningPresentation(MyMessage &msg, uint8_t destination)
|
||||
{
|
||||
// Only supports version 1 for now
|
||||
(void)build(msg, destination, NODE_SENSOR_ID, C_INTERNAL, I_SIGNING_PRESENTATION).set("");
|
||||
mSetLength(msg, 2);
|
||||
@@ -116,7 +119,8 @@ static void prepareSigningPresentation(MyMessage &msg, uint8_t destination) {
|
||||
msg.data[1] = 0;
|
||||
}
|
||||
|
||||
void signerInit(void) {
|
||||
void signerInit(void)
|
||||
{
|
||||
#if defined(MY_SIGNING_FEATURE)
|
||||
// Read out the signing requirements from EEPROM
|
||||
hwReadConfigBlock((void*)_doSign, (void*)EEPROM_SIGNING_REQUIREMENT_TABLE_ADDRESS,
|
||||
@@ -135,7 +139,8 @@ void signerInit(void) {
|
||||
#endif
|
||||
}
|
||||
|
||||
void signerPresentation(MyMessage &msg, uint8_t destination) {
|
||||
void signerPresentation(MyMessage &msg, uint8_t destination)
|
||||
{
|
||||
prepareSigningPresentation(msg, destination);
|
||||
|
||||
#if defined(MY_SIGNING_REQUEST_SIGNATURES)
|
||||
@@ -157,7 +162,8 @@ void signerPresentation(MyMessage &msg, uint8_t destination) {
|
||||
}
|
||||
}
|
||||
|
||||
bool signerProcessInternal(MyMessage &msg) {
|
||||
bool signerProcessInternal(MyMessage &msg)
|
||||
{
|
||||
uint8_t sender = msg.sender;
|
||||
(void)sender;
|
||||
#if !defined(MY_SIGNING_FEATURE)
|
||||
@@ -166,7 +172,8 @@ bool signerProcessInternal(MyMessage &msg) {
|
||||
// If we act as gateway and do not have the signing feature and receive a signing request we still
|
||||
// need to do make sure the requester does not believe the gateway still require signatures
|
||||
prepareSigningPresentation(msg, sender);
|
||||
SIGN_DEBUG(PSTR("Informing node %d that we do not require signatures because we do not support it\n"),
|
||||
SIGN_DEBUG(
|
||||
PSTR("Informing node %d that we do not require signatures because we do not support it\n"),
|
||||
sender);
|
||||
if (!_sendRoute(msg)) {
|
||||
SIGN_DEBUG(PSTR("Failed to transmit signing presentation!\n"));
|
||||
@@ -183,7 +190,8 @@ bool signerProcessInternal(MyMessage &msg) {
|
||||
if (msg.type == I_NONCE_REQUEST) {
|
||||
#if defined(MY_NODE_LOCK_FEATURE)
|
||||
nof_nonce_requests++;
|
||||
SIGN_DEBUG(PSTR("Nonce requests left until lockdown: %d\n"), MY_NODE_LOCK_COUNTER_MAX-nof_nonce_requests);
|
||||
SIGN_DEBUG(PSTR("Nonce requests left until lockdown: %d\n"),
|
||||
MY_NODE_LOCK_COUNTER_MAX-nof_nonce_requests);
|
||||
if (nof_nonce_requests >= MY_NODE_LOCK_COUNTER_MAX) {
|
||||
_nodeLock("TMNR"); //Too many nonces requested
|
||||
}
|
||||
@@ -323,7 +331,8 @@ bool signerSignMsg(MyMessage &msg) {
|
||||
} else {
|
||||
// Send nonce-request
|
||||
_signingNonceStatus=SIGN_WAITING_FOR_NONCE;
|
||||
if (!_sendRoute(build(_msgSign, msg.destination, msg.sensor, C_INTERNAL, I_NONCE_REQUEST).set(""))) {
|
||||
if (!_sendRoute(build(_msgSign, msg.destination, msg.sensor, C_INTERNAL,
|
||||
I_NONCE_REQUEST).set(""))) {
|
||||
SIGN_DEBUG(PSTR("Failed to transmit nonce request!\n"));
|
||||
return false;
|
||||
}
|
||||
@@ -332,7 +341,8 @@ bool signerSignMsg(MyMessage &msg) {
|
||||
// Other messages could come in-between. We trust _process() takes care of them
|
||||
unsigned long enter = hwMillis();
|
||||
_msgSign = msg; // Copy the message to sign since message buffer might be touched in _process()
|
||||
while (hwMillis() - enter < MY_VERIFICATION_TIMEOUT_MS && _signingNonceStatus==SIGN_WAITING_FOR_NONCE) {
|
||||
while (hwMillis() - enter < MY_VERIFICATION_TIMEOUT_MS &&
|
||||
_signingNonceStatus==SIGN_WAITING_FOR_NONCE) {
|
||||
_process();
|
||||
}
|
||||
if (hwMillis() - enter > MY_VERIFICATION_TIMEOUT_MS) {
|
||||
@@ -375,8 +385,7 @@ bool signerVerifyMsg(MyMessage &msg) {
|
||||
// Internal messages of certain types are not verified
|
||||
if (skipSign(msg)) {
|
||||
verificationResult = true;
|
||||
}
|
||||
else if (!mGetSigned(msg)) {
|
||||
} else if (!mGetSigned(msg)) {
|
||||
// Got unsigned message that should have been signed
|
||||
SIGN_DEBUG(PSTR("Message is not signed, but it should have been!\n"));
|
||||
verificationResult = false;
|
||||
@@ -397,7 +406,8 @@ bool signerVerifyMsg(MyMessage &msg) {
|
||||
nof_failed_verifications = 0;
|
||||
} else {
|
||||
nof_failed_verifications++;
|
||||
SIGN_DEBUG(PSTR("Failed verification attempts left until lockdown: %d\n"), MY_NODE_LOCK_COUNTER_MAX-nof_failed_verifications);
|
||||
SIGN_DEBUG(PSTR("Failed verification attempts left until lockdown: %d\n"),
|
||||
MY_NODE_LOCK_COUNTER_MAX-nof_failed_verifications);
|
||||
if (nof_failed_verifications >= MY_NODE_LOCK_COUNTER_MAX) {
|
||||
_nodeLock("TMFV"); //Too many failed verifications
|
||||
}
|
||||
|
||||
+51
-30
@@ -54,21 +54,20 @@ static char i2h(uint8_t i)
|
||||
uint8_t k = i & 0x0F;
|
||||
if (k <= 9) {
|
||||
return '0' + k;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return 'A' + k - 10;
|
||||
}
|
||||
}
|
||||
|
||||
static void DEBUG_SIGNING_PRINTBUF(const __FlashStringHelper* str, uint8_t* buf, uint8_t sz) {
|
||||
static void DEBUG_SIGNING_PRINTBUF(const __FlashStringHelper* str, uint8_t* buf, uint8_t sz)
|
||||
{
|
||||
static char printBuffer[300];
|
||||
#ifdef MY_GATEWAY_FEATURE
|
||||
// prepend debug message to be handled correctly by controller (C_INTERNAL, I_LOG_MESSAGE)
|
||||
snprintf_P(printBuffer, 299, PSTR("0;255;%d;0;%d;"), C_INTERNAL, I_LOG_MESSAGE);
|
||||
MY_SERIALDEVICE.print(printBuffer);
|
||||
#endif
|
||||
for (int i=0; i<sz; i++)
|
||||
{
|
||||
for (int i=0; i<sz; i++) {
|
||||
printBuffer[i * 2] = i2h(buf[i] >> 4);
|
||||
printBuffer[(i * 2) + 1] = i2h(buf[i]);
|
||||
}
|
||||
@@ -78,8 +77,7 @@ static void DEBUG_SIGNING_PRINTBUF(const __FlashStringHelper* str, uint8_t* buf,
|
||||
printBuffer[MY_GATEWAY_MAX_SEND_LENGTH-1-strlen_P((const char*)str)] = '\0';
|
||||
#endif
|
||||
MY_SERIALDEVICE.print(str);
|
||||
if (sz > 0)
|
||||
{
|
||||
if (sz > 0) {
|
||||
MY_SERIALDEVICE.print(printBuffer);
|
||||
}
|
||||
MY_SERIALDEVICE.println("");
|
||||
@@ -88,13 +86,16 @@ static void DEBUG_SIGNING_PRINTBUF(const __FlashStringHelper* str, uint8_t* buf,
|
||||
#define DEBUG_SIGNING_PRINTBUF(str, buf, sz)
|
||||
#endif
|
||||
|
||||
void signerAtsha204Init(void) {
|
||||
void signerAtsha204Init(void)
|
||||
{
|
||||
atsha204_init(MY_SIGNING_ATSHA204_PIN);
|
||||
}
|
||||
|
||||
bool signerAtsha204CheckTimer(void) {
|
||||
bool signerAtsha204CheckTimer(void)
|
||||
{
|
||||
if (_signing_verification_ongoing) {
|
||||
if (hwMillis() < _signing_timestamp || hwMillis() > _signing_timestamp + MY_VERIFICATION_TIMEOUT_MS) {
|
||||
if (hwMillis() < _signing_timestamp ||
|
||||
hwMillis() > _signing_timestamp + MY_VERIFICATION_TIMEOUT_MS) {
|
||||
DEBUG_SIGNING_PRINTBUF(F("Verification timeout"), NULL, 0);
|
||||
// Purge nonce
|
||||
memset(_signing_signing_nonce, 0x00, NONCE_NUMIN_SIZE_PASSTHROUGH);
|
||||
@@ -106,7 +107,8 @@ bool signerAtsha204CheckTimer(void) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool signerAtsha204GetNonce(MyMessage &msg) {
|
||||
bool signerAtsha204GetNonce(MyMessage &msg)
|
||||
{
|
||||
DEBUG_SIGNING_PRINTBUF(F("Signing backend: ATSHA204"), NULL, 0);
|
||||
// Generate random number for use as nonce
|
||||
// We used a basic whitening technique that XORs each byte in a 32byte random value with current hwMillis() counter
|
||||
@@ -140,7 +142,8 @@ bool signerAtsha204GetNonce(MyMessage &msg) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void signerAtsha204PutNonce(MyMessage &msg) {
|
||||
void signerAtsha204PutNonce(MyMessage &msg)
|
||||
{
|
||||
DEBUG_SIGNING_PRINTBUF(F("Signing backend: ATSHA204"), NULL, 0);
|
||||
|
||||
memcpy(_signing_signing_nonce, (uint8_t*)msg.getCustom(), MAX_PAYLOAD);
|
||||
@@ -148,7 +151,8 @@ void signerAtsha204PutNonce(MyMessage &msg) {
|
||||
memset(&_signing_signing_nonce[MAX_PAYLOAD], 0xAA, sizeof(_signing_signing_nonce)-MAX_PAYLOAD);
|
||||
}
|
||||
|
||||
bool signerAtsha204SignMsg(MyMessage &msg) {
|
||||
bool signerAtsha204SignMsg(MyMessage &msg)
|
||||
{
|
||||
// If we cannot fit any signature in the message, refuse to sign it
|
||||
if (mGetLength(msg) > MAX_PAYLOAD-2) {
|
||||
DEBUG_SIGNING_PRINTBUF(F("Message too large"), NULL, 0);
|
||||
@@ -161,10 +165,12 @@ bool signerAtsha204SignMsg(MyMessage &msg) {
|
||||
|
||||
if (DO_WHITELIST(msg.destination)) {
|
||||
// Salt the signature with the senders nodeId and the unique serial of the ATSHA device
|
||||
memcpy(_signing_signing_nonce, &_signing_rx_buffer[SHA204_BUFFER_POS_DATA], 32); // We can reuse the nonce buffer now since it is no longer needed
|
||||
memcpy(_signing_signing_nonce, &_signing_rx_buffer[SHA204_BUFFER_POS_DATA],
|
||||
32); // We can reuse the nonce buffer now since it is no longer needed
|
||||
_signing_signing_nonce[32] = msg.sender;
|
||||
atsha204_getSerialNumber(&_signing_signing_nonce[33]);
|
||||
(void)signerSha256(_signing_signing_nonce, 32+1+SHA204_SERIAL_SZ); // we can 'void' sha256 because the hash is already put in the correct place
|
||||
(void)signerSha256(_signing_signing_nonce,
|
||||
32+1+SHA204_SERIAL_SZ); // we can 'void' sha256 because the hash is already put in the correct place
|
||||
DEBUG_SIGNING_PRINTBUF(F("Signature salted with serial"), NULL, 0);
|
||||
}
|
||||
|
||||
@@ -175,13 +181,16 @@ bool signerAtsha204SignMsg(MyMessage &msg) {
|
||||
_signing_rx_buffer[SHA204_BUFFER_POS_DATA] = SIGNING_IDENTIFIER;
|
||||
|
||||
// Transfer as much signature data as the remaining space in the message permits
|
||||
memcpy(&msg.data[mGetLength(msg)], &_signing_rx_buffer[SHA204_BUFFER_POS_DATA], MAX_PAYLOAD-mGetLength(msg));
|
||||
DEBUG_SIGNING_PRINTBUF(F("Signature in message: "), (uint8_t*)&msg.data[mGetLength(msg)], MAX_PAYLOAD-mGetLength(msg));
|
||||
memcpy(&msg.data[mGetLength(msg)], &_signing_rx_buffer[SHA204_BUFFER_POS_DATA],
|
||||
MAX_PAYLOAD-mGetLength(msg));
|
||||
DEBUG_SIGNING_PRINTBUF(F("Signature in message: "), (uint8_t*)&msg.data[mGetLength(msg)],
|
||||
MAX_PAYLOAD-mGetLength(msg));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool signerAtsha204VerifyMsg(MyMessage &msg) {
|
||||
bool signerAtsha204VerifyMsg(MyMessage &msg)
|
||||
{
|
||||
if (!_signing_verification_ongoing) {
|
||||
DEBUG_SIGNING_PRINTBUF(F("No active verification session"), NULL, 0);
|
||||
return false;
|
||||
@@ -198,7 +207,8 @@ bool signerAtsha204VerifyMsg(MyMessage &msg) {
|
||||
return false;
|
||||
}
|
||||
|
||||
DEBUG_SIGNING_PRINTBUF(F("Signature in message: "), (uint8_t*)&msg.data[mGetLength(msg)], MAX_PAYLOAD-mGetLength(msg));
|
||||
DEBUG_SIGNING_PRINTBUF(F("Signature in message: "), (uint8_t*)&msg.data[mGetLength(msg)],
|
||||
MAX_PAYLOAD-mGetLength(msg));
|
||||
signerCalculateSignature(msg, false); // Get signature of message
|
||||
|
||||
#ifdef MY_SIGNING_NODE_WHITELISTING
|
||||
@@ -207,10 +217,12 @@ bool signerAtsha204VerifyMsg(MyMessage &msg) {
|
||||
for (j=0; j < NUM_OF(_signing_whitelist); j++) {
|
||||
if (_signing_whitelist[j].nodeId == msg.sender) {
|
||||
DEBUG_SIGNING_PRINTBUF(F("Sender found in whitelist"), NULL, 0);
|
||||
memcpy(_signing_verifying_nonce, &_signing_rx_buffer[SHA204_BUFFER_POS_DATA], 32); // We can reuse the nonce buffer now since it is no longer needed
|
||||
memcpy(_signing_verifying_nonce, &_signing_rx_buffer[SHA204_BUFFER_POS_DATA],
|
||||
32); // We can reuse the nonce buffer now since it is no longer needed
|
||||
_signing_verifying_nonce[32] = msg.sender;
|
||||
memcpy(&_signing_verifying_nonce[33], _signing_whitelist[j].serial, SHA204_SERIAL_SZ);
|
||||
(void)signerSha256(_signing_verifying_nonce, 32+1+SHA204_SERIAL_SZ); // we can 'void' sha256 because the hash is already put in the correct place
|
||||
(void)signerSha256(_signing_verifying_nonce,
|
||||
32+1+SHA204_SERIAL_SZ); // we can 'void' sha256 because the hash is already put in the correct place
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -229,8 +241,10 @@ bool signerAtsha204VerifyMsg(MyMessage &msg) {
|
||||
_signing_rx_buffer[SHA204_BUFFER_POS_DATA] = SIGNING_IDENTIFIER;
|
||||
|
||||
// Compare the caluclated signature with the provided signature
|
||||
if (signerMemcmp(&msg.data[mGetLength(msg)], &_signing_rx_buffer[SHA204_BUFFER_POS_DATA], MAX_PAYLOAD-mGetLength(msg))) {
|
||||
DEBUG_SIGNING_PRINTBUF(F("Signature bad: "), &_signing_rx_buffer[SHA204_BUFFER_POS_DATA], MAX_PAYLOAD-mGetLength(msg));
|
||||
if (signerMemcmp(&msg.data[mGetLength(msg)], &_signing_rx_buffer[SHA204_BUFFER_POS_DATA],
|
||||
MAX_PAYLOAD-mGetLength(msg))) {
|
||||
DEBUG_SIGNING_PRINTBUF(F("Signature bad: "), &_signing_rx_buffer[SHA204_BUFFER_POS_DATA],
|
||||
MAX_PAYLOAD-mGetLength(msg));
|
||||
#ifdef MY_SIGNING_NODE_WHITELISTING
|
||||
DEBUG_SIGNING_PRINTBUF(F("Is the sender whitelisted and serial correct?"), NULL, 0);
|
||||
#endif
|
||||
@@ -243,15 +257,20 @@ bool signerAtsha204VerifyMsg(MyMessage &msg) {
|
||||
}
|
||||
|
||||
// Helper to calculate signature of msg (returned in _signing_rx_buffer[SHA204_BUFFER_POS_DATA])
|
||||
static void signerCalculateSignature(MyMessage &msg, bool signing) {
|
||||
static void signerCalculateSignature(MyMessage &msg, bool signing)
|
||||
{
|
||||
(void)atsha204_wakeup(_signing_temp_message);
|
||||
memset(_signing_temp_message, 0, 32);
|
||||
memcpy(_signing_temp_message, (uint8_t*)&msg.data[1-HEADER_SIZE], MAX_MESSAGE_LENGTH-1-(MAX_PAYLOAD-mGetLength(msg)));
|
||||
memcpy(_signing_temp_message, (uint8_t*)&msg.data[1-HEADER_SIZE],
|
||||
MAX_MESSAGE_LENGTH-1-(MAX_PAYLOAD-mGetLength(msg)));
|
||||
|
||||
// Program the data to sign into the ATSHA204
|
||||
DEBUG_SIGNING_PRINTBUF(F("Message to process: "), (uint8_t*)&msg.data[1-HEADER_SIZE], MAX_MESSAGE_LENGTH-1-(MAX_PAYLOAD-mGetLength(msg)));
|
||||
DEBUG_SIGNING_PRINTBUF(F("Current nonce: "), signing ? _signing_signing_nonce : _signing_verifying_nonce, 32);
|
||||
(void)atsha204_execute(SHA204_WRITE, SHA204_ZONE_DATA | SHA204_ZONE_COUNT_FLAG, 8 << 3, 32, _signing_temp_message,
|
||||
DEBUG_SIGNING_PRINTBUF(F("Message to process: "), (uint8_t*)&msg.data[1-HEADER_SIZE],
|
||||
MAX_MESSAGE_LENGTH-1-(MAX_PAYLOAD-mGetLength(msg)));
|
||||
DEBUG_SIGNING_PRINTBUF(F("Current nonce: "),
|
||||
signing ? _signing_signing_nonce : _signing_verifying_nonce, 32);
|
||||
(void)atsha204_execute(SHA204_WRITE, SHA204_ZONE_DATA | SHA204_ZONE_COUNT_FLAG, 8 << 3, 32,
|
||||
_signing_temp_message,
|
||||
WRITE_COUNT_LONG, _signing_tx_buffer, WRITE_RSP_SIZE, _signing_rx_buffer);
|
||||
|
||||
// Program the nonce to use for the signature (has to be done just before GENDIG due to chip limitations)
|
||||
@@ -260,7 +279,8 @@ static void signerCalculateSignature(MyMessage &msg, bool signing) {
|
||||
NONCE_COUNT_LONG, _signing_tx_buffer, NONCE_RSP_SIZE_SHORT, _signing_rx_buffer);
|
||||
|
||||
// Purge nonce when used
|
||||
memset(signing ? _signing_signing_nonce : _signing_verifying_nonce, 0x00, NONCE_NUMIN_SIZE_PASSTHROUGH);
|
||||
memset(signing ? _signing_signing_nonce : _signing_verifying_nonce, 0x00,
|
||||
NONCE_NUMIN_SIZE_PASSTHROUGH);
|
||||
|
||||
// Generate digest of data and nonce
|
||||
(void)atsha204_execute(SHA204_GENDIG, GENDIG_ZONE_DATA, 8, 0, NULL,
|
||||
@@ -275,7 +295,8 @@ static void signerCalculateSignature(MyMessage &msg, bool signing) {
|
||||
|
||||
// Helper to calculate a generic SHA256 digest of provided buffer (only supports one block)
|
||||
// The pointer to the hash is returned, but the hash is also stored in _signing_rx_buffer[SHA204_BUFFER_POS_DATA])
|
||||
static uint8_t* signerSha256(const uint8_t* data, size_t sz) {
|
||||
static uint8_t* signerSha256(const uint8_t* data, size_t sz)
|
||||
{
|
||||
// Initiate SHA256 calculator
|
||||
(void)atsha204_execute(SHA204_SHA, SHA_INIT, 0, 0, NULL,
|
||||
SHA_COUNT_SHORT, _signing_tx_buffer, SHA_RSP_SIZE_SHORT, _signing_rx_buffer);
|
||||
|
||||
@@ -58,38 +58,36 @@ static char i2h(uint8_t i)
|
||||
uint8_t k = i & 0x0F;
|
||||
if (k <= 9) {
|
||||
return '0' + k;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return 'A' + k - 10;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __linux__
|
||||
static void DEBUG_SIGNING_PRINTBUF(const char *str, uint8_t* buf, uint8_t sz) {
|
||||
static void DEBUG_SIGNING_PRINTBUF(const char *str, uint8_t* buf, uint8_t sz)
|
||||
{
|
||||
static char printBuffer[300];
|
||||
|
||||
for (int i=0; i<sz; i++)
|
||||
{
|
||||
for (int i=0; i<sz; i++) {
|
||||
printBuffer[i * 2] = i2h(buf[i] >> 4);
|
||||
printBuffer[(i * 2) + 1] = i2h(buf[i]);
|
||||
}
|
||||
printBuffer[sz * 2] = '\0';
|
||||
debug(str);
|
||||
if (sz > 0)
|
||||
{
|
||||
if (sz > 0) {
|
||||
debug(printBuffer);
|
||||
}
|
||||
}
|
||||
#else
|
||||
static void DEBUG_SIGNING_PRINTBUF(const __FlashStringHelper* str, uint8_t* buf, uint8_t sz) {
|
||||
static void DEBUG_SIGNING_PRINTBUF(const __FlashStringHelper* str, uint8_t* buf, uint8_t sz)
|
||||
{
|
||||
static char printBuffer[300];
|
||||
#ifdef MY_GATEWAY_FEATURE
|
||||
// prepend debug message to be handled correctly by controller (C_INTERNAL, I_LOG_MESSAGE)
|
||||
snprintf_P(printBuffer, 299, PSTR("0;255;%d;0;%d;"), C_INTERNAL, I_LOG_MESSAGE);
|
||||
MY_SERIALDEVICE.print(printBuffer);
|
||||
#endif
|
||||
for (int i=0; i<sz; i++)
|
||||
{
|
||||
for (int i=0; i<sz; i++) {
|
||||
printBuffer[i * 2] = i2h(buf[i] >> 4);
|
||||
printBuffer[(i * 2) + 1] = i2h(buf[i]);
|
||||
}
|
||||
@@ -99,8 +97,7 @@ static void DEBUG_SIGNING_PRINTBUF(const __FlashStringHelper* str, uint8_t* buf,
|
||||
printBuffer[MY_GATEWAY_MAX_SEND_LENGTH-1-strlen_P((const char*)str)] = '\0';
|
||||
#endif
|
||||
MY_SERIALDEVICE.print(str);
|
||||
if (sz > 0)
|
||||
{
|
||||
if (sz > 0) {
|
||||
MY_SERIALDEVICE.print(printBuffer);
|
||||
}
|
||||
MY_SERIALDEVICE.println("");
|
||||
@@ -110,7 +107,8 @@ static void DEBUG_SIGNING_PRINTBUF(const __FlashStringHelper* str, uint8_t* buf,
|
||||
#define DEBUG_SIGNING_PRINTBUF(str, buf, sz)
|
||||
#endif
|
||||
|
||||
void signerAtsha204SoftInit(void) {
|
||||
void signerAtsha204SoftInit(void)
|
||||
{
|
||||
// initialize pseudo-RNG
|
||||
hwRandomNumberInit();
|
||||
// Set secrets
|
||||
@@ -118,9 +116,11 @@ void signerAtsha204SoftInit(void) {
|
||||
hwReadConfigBlock((void*)_signing_node_serial_info, (void*)EEPROM_SIGNING_SOFT_SERIAL_ADDRESS, 9);
|
||||
}
|
||||
|
||||
bool signerAtsha204SoftCheckTimer(void) {
|
||||
bool signerAtsha204SoftCheckTimer(void)
|
||||
{
|
||||
if (_signing_verification_ongoing) {
|
||||
if (hwMillis() < _signing_timestamp || hwMillis() > _signing_timestamp + MY_VERIFICATION_TIMEOUT_MS) {
|
||||
if (hwMillis() < _signing_timestamp ||
|
||||
hwMillis() > _signing_timestamp + MY_VERIFICATION_TIMEOUT_MS) {
|
||||
DEBUG_SIGNING_PRINTBUF(F("Verification timeout"), NULL, 0);
|
||||
// Purge nonce
|
||||
memset(_signing_signing_nonce, 0xAA, 32);
|
||||
@@ -132,7 +132,8 @@ bool signerAtsha204SoftCheckTimer(void) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool signerAtsha204SoftGetNonce(MyMessage &msg) {
|
||||
bool signerAtsha204SoftGetNonce(MyMessage &msg)
|
||||
{
|
||||
DEBUG_SIGNING_PRINTBUF(F("Signing backend: ATSHA204Soft"), NULL, 0);
|
||||
|
||||
// We used a basic whitening technique that XORs a random byte with the current hwMillis() counter and then the byte is
|
||||
@@ -160,7 +161,8 @@ bool signerAtsha204SoftGetNonce(MyMessage &msg) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void signerAtsha204SoftPutNonce(MyMessage &msg) {
|
||||
void signerAtsha204SoftPutNonce(MyMessage &msg)
|
||||
{
|
||||
DEBUG_SIGNING_PRINTBUF(F("Signing backend: ATSHA204Soft"), NULL, 0);
|
||||
|
||||
memcpy(_signing_signing_nonce, (uint8_t*)msg.getCustom(), MAX_PAYLOAD);
|
||||
@@ -168,7 +170,8 @@ void signerAtsha204SoftPutNonce(MyMessage &msg) {
|
||||
memset(&_signing_signing_nonce[MAX_PAYLOAD], 0xAA, sizeof(_signing_signing_nonce)-MAX_PAYLOAD);
|
||||
}
|
||||
|
||||
bool signerAtsha204SoftSignMsg(MyMessage &msg) {
|
||||
bool signerAtsha204SoftSignMsg(MyMessage &msg)
|
||||
{
|
||||
// If we cannot fit any signature in the message, refuse to sign it
|
||||
if (mGetLength(msg) > MAX_PAYLOAD-2) {
|
||||
DEBUG_SIGNING_PRINTBUF(F("Message too large"), NULL, 0);
|
||||
@@ -199,12 +202,14 @@ bool signerAtsha204SoftSignMsg(MyMessage &msg) {
|
||||
|
||||
// Transfer as much signature data as the remaining space in the message permits
|
||||
memcpy(&msg.data[mGetLength(msg)], _signing_hmac, MAX_PAYLOAD-mGetLength(msg));
|
||||
DEBUG_SIGNING_PRINTBUF(F("Signature in message: "), (uint8_t*)&msg.data[mGetLength(msg)], MAX_PAYLOAD-mGetLength(msg));
|
||||
DEBUG_SIGNING_PRINTBUF(F("Signature in message: "), (uint8_t*)&msg.data[mGetLength(msg)],
|
||||
MAX_PAYLOAD-mGetLength(msg));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool signerAtsha204SoftVerifyMsg(MyMessage &msg) {
|
||||
bool signerAtsha204SoftVerifyMsg(MyMessage &msg)
|
||||
{
|
||||
if (!_signing_verification_ongoing) {
|
||||
DEBUG_SIGNING_PRINTBUF(F("No active verification session"), NULL, 0);
|
||||
return false;
|
||||
@@ -222,7 +227,8 @@ bool signerAtsha204SoftVerifyMsg(MyMessage &msg) {
|
||||
}
|
||||
|
||||
// Get signature of message
|
||||
DEBUG_SIGNING_PRINTBUF(F("Signature in message: "), (uint8_t*)&msg.data[mGetLength(msg)], MAX_PAYLOAD-mGetLength(msg));
|
||||
DEBUG_SIGNING_PRINTBUF(F("Signature in message: "), (uint8_t*)&msg.data[mGetLength(msg)],
|
||||
MAX_PAYLOAD-mGetLength(msg));
|
||||
signerCalculateSignature(msg, false);
|
||||
|
||||
#ifdef MY_SIGNING_NODE_WHITELISTING
|
||||
@@ -268,11 +274,15 @@ bool signerAtsha204SoftVerifyMsg(MyMessage &msg) {
|
||||
}
|
||||
|
||||
// Helper to calculate signature of msg (returned in hmac)
|
||||
static void signerCalculateSignature(MyMessage &msg, bool signing) {
|
||||
static void signerCalculateSignature(MyMessage &msg, bool signing)
|
||||
{
|
||||
memset(_signing_temp_message, 0, 32);
|
||||
memcpy(_signing_temp_message, (uint8_t*)&msg.data[1-HEADER_SIZE], MAX_MESSAGE_LENGTH-1-(MAX_PAYLOAD-mGetLength(msg)));
|
||||
DEBUG_SIGNING_PRINTBUF(F("Message to process: "), (uint8_t*)&msg.data[1-HEADER_SIZE], MAX_MESSAGE_LENGTH-1-(MAX_PAYLOAD-mGetLength(msg)));
|
||||
DEBUG_SIGNING_PRINTBUF(F("Current nonce: "), signing ? _signing_signing_nonce : _signing_verifying_nonce, 32);
|
||||
memcpy(_signing_temp_message, (uint8_t*)&msg.data[1-HEADER_SIZE],
|
||||
MAX_MESSAGE_LENGTH-1-(MAX_PAYLOAD-mGetLength(msg)));
|
||||
DEBUG_SIGNING_PRINTBUF(F("Message to process: "), (uint8_t*)&msg.data[1-HEADER_SIZE],
|
||||
MAX_MESSAGE_LENGTH-1-(MAX_PAYLOAD-mGetLength(msg)));
|
||||
DEBUG_SIGNING_PRINTBUF(F("Current nonce: "),
|
||||
signing ? _signing_signing_nonce : _signing_verifying_nonce, 32);
|
||||
|
||||
// ATSHA204 calculates the HMAC with a PSK and a SHA256 digest of the following data:
|
||||
// 32 bytes zeroes
|
||||
|
||||
+155
-115
@@ -57,7 +57,8 @@ extern MyMessage _msgTmp; // outgoing message
|
||||
#endif
|
||||
|
||||
// stInit: initialise transport HW
|
||||
void stInitTransition(void) {
|
||||
void stInitTransition(void)
|
||||
{
|
||||
TRANSPORT_DEBUG(PSTR("TSM:INIT\n"));
|
||||
// initialise status variables
|
||||
_transportSM.pingActive = false;
|
||||
@@ -75,17 +76,18 @@ void stInitTransition(void) {
|
||||
#endif
|
||||
|
||||
// Read node settings (ID, parent ID, GW distance) from EEPROM
|
||||
hwReadConfigBlock((void*)&_transportConfig, (void*)EEPROM_NODE_ID_ADDRESS, sizeof(transportConfig_t));
|
||||
hwReadConfigBlock((void*)&_transportConfig, (void*)EEPROM_NODE_ID_ADDRESS,
|
||||
sizeof(transportConfig_t));
|
||||
}
|
||||
|
||||
void stInitUpdate(void) {
|
||||
void stInitUpdate(void)
|
||||
{
|
||||
// initialise radio
|
||||
if (!transportInit()) {
|
||||
TRANSPORT_DEBUG(PSTR("!TSM:INIT:TSP FAIL\n"));
|
||||
setIndication(INDICATION_ERR_INIT_TRANSPORT);
|
||||
transportSwitchSM(stFailure);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
TRANSPORT_DEBUG(PSTR("TSM:INIT:TSP OK\n"));
|
||||
_transportSM.transportActive = true;
|
||||
#if defined(MY_GATEWAY_FEATURE)
|
||||
@@ -109,8 +111,7 @@ void stInitUpdate(void) {
|
||||
if (_transportConfig.nodeId == AUTO || transportAssignNodeID(_transportConfig.nodeId)) {
|
||||
// if node ID valid (>0 and <255), proceed to next state
|
||||
transportSwitchSM(stParent);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// ID invalid (0 or 255)
|
||||
transportSwitchSM(stFailure);
|
||||
}
|
||||
@@ -119,7 +120,8 @@ void stInitUpdate(void) {
|
||||
}
|
||||
|
||||
// stParent: find parent
|
||||
void stParentTransition(void) {
|
||||
void stParentTransition(void)
|
||||
{
|
||||
TRANSPORT_DEBUG(PSTR("TSM:FPAR\n")); // find parent
|
||||
setIndication(INDICATION_FIND_PARENT);
|
||||
_transportSM.uplinkOk = false;
|
||||
@@ -136,12 +138,14 @@ void stParentTransition(void) {
|
||||
_transportConfig.distanceGW = DISTANCE_INVALID; // Set distance to max and invalidate parent node ID
|
||||
_transportConfig.parentNodeId = AUTO;
|
||||
// Broadcast find parent request
|
||||
(void)transportRouteMessage(build(_msgTmp, BROADCAST_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_FIND_PARENT_REQUEST).set(""));
|
||||
(void)transportRouteMessage(build(_msgTmp, BROADCAST_ADDRESS, NODE_SENSOR_ID, C_INTERNAL,
|
||||
I_FIND_PARENT_REQUEST).set(""));
|
||||
#endif
|
||||
}
|
||||
|
||||
// stParentUpdate
|
||||
void stParentUpdate(void) {
|
||||
void stParentUpdate(void)
|
||||
{
|
||||
#if defined(MY_PARENT_NODE_IS_STATIC)
|
||||
// skipping find parent
|
||||
setIndication(INDICATION_GOT_PARENT);
|
||||
@@ -156,16 +160,14 @@ void stParentUpdate(void) {
|
||||
setIndication(INDICATION_GOT_PARENT);
|
||||
// go to next state
|
||||
transportSwitchSM(stID);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// timeout w/o reply or valid parent
|
||||
if (_transportSM.stateRetries < MY_TRANSPORT_STATE_RETRIES) {
|
||||
// retries left
|
||||
TRANSPORT_DEBUG(PSTR("!TSM:FPAR:NO REPLY\n")); // find parent, no reply
|
||||
// reenter state
|
||||
transportSwitchSM(stParent);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// no retries left, finding parent failed
|
||||
TRANSPORT_DEBUG(PSTR("!TSM:FPAR:FAIL\n"));
|
||||
setIndication(INDICATION_ERR_FIND_PARENT);
|
||||
@@ -177,31 +179,32 @@ void stParentUpdate(void) {
|
||||
}
|
||||
|
||||
// stID: verify and request ID if necessary
|
||||
void stIDTransition(void) {
|
||||
void stIDTransition(void)
|
||||
{
|
||||
TRANSPORT_DEBUG(PSTR("TSM:ID\n")); // verify/request node ID
|
||||
if (_transportConfig.nodeId == AUTO) {
|
||||
// send ID request
|
||||
setIndication(INDICATION_REQ_NODEID);
|
||||
TRANSPORT_DEBUG(PSTR("TSM:ID:REQ\n")); // request node ID
|
||||
(void)transportRouteMessage(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_ID_REQUEST).set(""));
|
||||
(void)transportRouteMessage(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL,
|
||||
I_ID_REQUEST).set(""));
|
||||
}
|
||||
}
|
||||
|
||||
void stIDUpdate(void) {
|
||||
void stIDUpdate(void)
|
||||
{
|
||||
if (_transportConfig.nodeId != AUTO) {
|
||||
// current node ID is valid
|
||||
TRANSPORT_DEBUG(PSTR("TSM:ID:OK\n"));
|
||||
setIndication(INDICATION_GOT_NODEID);
|
||||
// proceed to next state
|
||||
transportSwitchSM(stUplink);
|
||||
}
|
||||
else if (transportTimeInState() > MY_TRANSPORT_STATE_TIMEOUT_MS) {
|
||||
} else if (transportTimeInState() > MY_TRANSPORT_STATE_TIMEOUT_MS) {
|
||||
// timeout
|
||||
if (_transportSM.stateRetries < MY_TRANSPORT_STATE_RETRIES) {
|
||||
// retries left: reenter state
|
||||
transportSwitchSM(stID);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// no retries left
|
||||
TRANSPORT_DEBUG(PSTR("!TSM:ID:FAIL\n"));
|
||||
setIndication(INDICATION_ERR_GET_NODEID);
|
||||
@@ -210,35 +213,37 @@ void stIDUpdate(void) {
|
||||
}
|
||||
}
|
||||
|
||||
void stUplinkTransition(void) {
|
||||
void stUplinkTransition(void)
|
||||
{
|
||||
#if !defined(MY_TRANSPORT_UPLINK_CHECK_DISABLED)
|
||||
TRANSPORT_DEBUG(PSTR("TSM:UPL\n"));
|
||||
setIndication(INDICATION_CHECK_UPLINK);
|
||||
_transportSM.pingResponse = INVALID_HOPS;
|
||||
_transportSM.pingActive = true;
|
||||
(void)transportRouteMessage(build(_msgTmp,GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_PING).set((uint8_t)0x01));
|
||||
(void)transportRouteMessage(build(_msgTmp,GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL,
|
||||
I_PING).set((uint8_t)0x01));
|
||||
#endif
|
||||
}
|
||||
|
||||
void stUplinkUpdate(void) {
|
||||
void stUplinkUpdate(void)
|
||||
{
|
||||
#if !defined(MY_TRANSPORT_UPLINK_CHECK_DISABLED)
|
||||
if (_transportSM.pingResponse != INVALID_HOPS) {
|
||||
_transportSM.lastUplinkCheck = hwMillis();
|
||||
// uplink ok, i.e. GW replied
|
||||
TRANSPORT_DEBUG(PSTR("TSM:UPL:OK\n")); // uplink ok
|
||||
if (_transportSM.pingResponse != _transportConfig.distanceGW) {
|
||||
TRANSPORT_DEBUG(PSTR("TSM:UPL:DGWC,O=%d,N=%d\n"), _transportConfig.distanceGW, _transportSM.pingResponse); // distance to GW changed
|
||||
TRANSPORT_DEBUG(PSTR("TSM:UPL:DGWC,O=%d,N=%d\n"), _transportConfig.distanceGW,
|
||||
_transportSM.pingResponse); // distance to GW changed
|
||||
_transportConfig.distanceGW = _transportSM.pingResponse;
|
||||
}
|
||||
transportSwitchSM(stReady); // proceed to next state
|
||||
}
|
||||
else if (transportTimeInState() > MY_TRANSPORT_STATE_TIMEOUT_MS) {
|
||||
} else if (transportTimeInState() > MY_TRANSPORT_STATE_TIMEOUT_MS) {
|
||||
// timeout
|
||||
if (_transportSM.stateRetries < MY_TRANSPORT_STATE_RETRIES) {
|
||||
// retries left: reenter state
|
||||
transportSwitchSM(stUplink);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// no retries left
|
||||
TRANSPORT_DEBUG(PSTR("!TSM:UPL:FAIL\n")); // uplink check failed
|
||||
_transportSM.pingActive = false;
|
||||
@@ -252,9 +257,11 @@ void stUplinkUpdate(void) {
|
||||
#endif
|
||||
}
|
||||
|
||||
void stReadyTransition(void) {
|
||||
void stReadyTransition(void)
|
||||
{
|
||||
// transport is ready and fully operational
|
||||
TRANSPORT_DEBUG(PSTR("TSM:READY:ID=%d,PAR=%d,DIS=%d\n"), _transportConfig.nodeId, _transportConfig.parentNodeId, _transportConfig.distanceGW);
|
||||
TRANSPORT_DEBUG(PSTR("TSM:READY:ID=%d,PAR=%d,DIS=%d\n"), _transportConfig.nodeId,
|
||||
_transportConfig.parentNodeId, _transportConfig.distanceGW);
|
||||
_transportSM.uplinkOk = true;
|
||||
_transportSM.failureCounter = 0u; // reset failure counter
|
||||
_transportSM.failedUplinkTransmissions = 0u; // reset failed uplink TX counter
|
||||
@@ -265,12 +272,14 @@ void stReadyTransition(void) {
|
||||
}
|
||||
|
||||
// stReadyUpdate: monitors link
|
||||
void stReadyUpdate(void) {
|
||||
void stReadyUpdate(void)
|
||||
{
|
||||
#if defined(MY_GATEWAY_FEATURE)
|
||||
if (hwMillis() - _lastNetworkDiscovery > MY_TRANSPORT_DISCOVERY_INTERVAL_MS) {
|
||||
_lastNetworkDiscovery = hwMillis();
|
||||
TRANSPORT_DEBUG(PSTR("TSM:READY:NWD REQ\n")); // send transport network discovery
|
||||
(void)transportRouteMessage(build(_msgTmp, BROADCAST_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_DISCOVER_REQUEST).set(""));
|
||||
(void)transportRouteMessage(build(_msgTmp, BROADCAST_ADDRESS, NODE_SENSOR_ID, C_INTERNAL,
|
||||
I_DISCOVER_REQUEST).set(""));
|
||||
}
|
||||
#else
|
||||
if (_transportSM.failedUplinkTransmissions > MY_TRANSPORT_MAX_TX_FAILURES) {
|
||||
@@ -295,7 +304,8 @@ void stReadyUpdate(void) {
|
||||
}
|
||||
|
||||
// stFailure: entered upon HW init failure or max retries exceeded
|
||||
void stFailureTransition(void) {
|
||||
void stFailureTransition(void)
|
||||
{
|
||||
if (_transportSM.failureCounter < MY_TRANSPORT_MAX_TSM_FAILURES) {
|
||||
_transportSM.failureCounter++; // increment consecutive TSM failure counter
|
||||
}
|
||||
@@ -309,19 +319,21 @@ void stFailureTransition(void) {
|
||||
#endif
|
||||
}
|
||||
|
||||
void stFailureUpdate(void) {
|
||||
if (transportTimeInState() > ( isTransportExtendedFailure()? MY_TRANSPORT_TIMEOUT_EXT_FAILURE_STATE: MY_TRANSPORT_TIMEOUT_FAILURE_STATE) ) {
|
||||
void stFailureUpdate(void)
|
||||
{
|
||||
if (transportTimeInState() > ( isTransportExtendedFailure()? MY_TRANSPORT_TIMEOUT_EXT_FAILURE_STATE:
|
||||
MY_TRANSPORT_TIMEOUT_FAILURE_STATE) ) {
|
||||
TRANSPORT_DEBUG(PSTR("TSM:FAIL:RE-INIT\n")); // attempt to re-initialise transport
|
||||
transportSwitchSM(stInit);
|
||||
}
|
||||
}
|
||||
|
||||
void transportSwitchSM(transportState_t& newState) {
|
||||
void transportSwitchSM(transportState_t& newState)
|
||||
{
|
||||
if (_transportSM.currentState != &newState) {
|
||||
_transportSM.stateRetries = 0u; // state change, reset retry counter
|
||||
_transportSM.currentState = &newState; // change state
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
_transportSM.stateRetries++; // increment retries
|
||||
}
|
||||
if (_transportSM.currentState->Transition) {
|
||||
@@ -330,38 +342,46 @@ void transportSwitchSM(transportState_t& newState) {
|
||||
_transportSM.stateEnter = hwMillis(); // save time
|
||||
}
|
||||
|
||||
uint32_t transportTimeInState(void) {
|
||||
uint32_t transportTimeInState(void)
|
||||
{
|
||||
return hwMillis() - _transportSM.stateEnter;
|
||||
}
|
||||
|
||||
void transportUpdateSM(void) {
|
||||
void transportUpdateSM(void)
|
||||
{
|
||||
if (_transportSM.currentState->Update) {
|
||||
_transportSM.currentState->Update();
|
||||
}
|
||||
}
|
||||
|
||||
bool isTransportReady(void) {
|
||||
bool isTransportReady(void)
|
||||
{
|
||||
return _transportSM.uplinkOk;
|
||||
}
|
||||
|
||||
bool isTransportExtendedFailure(void) {
|
||||
bool isTransportExtendedFailure(void)
|
||||
{
|
||||
return _transportSM.failureCounter == MY_TRANSPORT_MAX_TSM_FAILURES;
|
||||
}
|
||||
|
||||
bool isTransportSearchingParent(void) {
|
||||
bool isTransportSearchingParent(void)
|
||||
{
|
||||
return _transportSM.findingParentNode;
|
||||
}
|
||||
|
||||
bool isMessageReceived(void) {
|
||||
bool isMessageReceived(void)
|
||||
{
|
||||
return _transportSM.msgReceived;
|
||||
}
|
||||
|
||||
void resetMessageReceived(void) {
|
||||
void resetMessageReceived(void)
|
||||
{
|
||||
_transportSM.msgReceived = false;
|
||||
}
|
||||
|
||||
|
||||
void transportInitialise(void) {
|
||||
void transportInitialise(void)
|
||||
{
|
||||
_transportSM.failureCounter = 0u; // reset failure counter
|
||||
transportLoadRoutingTable(); // load routing table to RAM (if feature enabled)
|
||||
// intial state
|
||||
@@ -369,7 +389,8 @@ void transportInitialise(void) {
|
||||
transportSwitchSM(stInit);
|
||||
}
|
||||
|
||||
bool transportWaitUntilReady(const uint32_t waitingMS) {
|
||||
bool transportWaitUntilReady(const uint32_t waitingMS)
|
||||
{
|
||||
// check if transport ready
|
||||
TRANSPORT_DEBUG(PSTR("TSF:WUR:MS=%lu\n"), waitingMS); // timeout
|
||||
uint32_t enterMS = hwMillis();
|
||||
@@ -383,7 +404,8 @@ bool transportWaitUntilReady(const uint32_t waitingMS) {
|
||||
}
|
||||
|
||||
// update TSM and process incoming messages
|
||||
void transportProcess(void) {
|
||||
void transportProcess(void)
|
||||
{
|
||||
// update state machine
|
||||
transportUpdateSM();
|
||||
// process transport FIFO
|
||||
@@ -391,7 +413,8 @@ void transportProcess(void) {
|
||||
}
|
||||
|
||||
|
||||
bool transportCheckUplink(const bool force) {
|
||||
bool transportCheckUplink(const bool force)
|
||||
{
|
||||
if (!force && (hwMillis() - _transportSM.lastUplinkCheck) < MY_TRANSPORT_CHKUPL_INTERVAL_MS) {
|
||||
TRANSPORT_DEBUG(PSTR("TSF:CKU:OK,FCTRL\n")); // flood control
|
||||
return true;
|
||||
@@ -405,18 +428,19 @@ bool transportCheckUplink(const bool force) {
|
||||
TRANSPORT_DEBUG(PSTR("TSF:CKU:OK\n"));
|
||||
// did distance to GW change upstream, eg. re-routing of uplink nodes
|
||||
if (hopsCount != _transportConfig.distanceGW) {
|
||||
TRANSPORT_DEBUG(PSTR("TSF:CKU:DGWC,O=%d,N=%d\n"), _transportConfig.distanceGW, hopsCount); // distance to GW changed
|
||||
TRANSPORT_DEBUG(PSTR("TSF:CKU:DGWC,O=%d,N=%d\n"), _transportConfig.distanceGW,
|
||||
hopsCount); // distance to GW changed
|
||||
_transportConfig.distanceGW = hopsCount;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
TRANSPORT_DEBUG(PSTR("TSF:CKU:FAIL\n"));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool transportAssignNodeID(const uint8_t newNodeId) {
|
||||
bool transportAssignNodeID(const uint8_t newNodeId)
|
||||
{
|
||||
// verify if ID valid
|
||||
if (newNodeId != GATEWAY_ADDRESS && newNodeId != AUTO) {
|
||||
_transportConfig.nodeId = newNodeId;
|
||||
@@ -425,8 +449,7 @@ bool transportAssignNodeID(const uint8_t newNodeId) {
|
||||
hwWriteConfig(EEPROM_NODE_ID_ADDRESS, newNodeId);
|
||||
TRANSPORT_DEBUG(PSTR("TSF:SID:OK,ID=%d\n"),newNodeId); // Node ID assigned
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
TRANSPORT_DEBUG(PSTR("!TSF:SID:FAIL,ID=%d\n"),newNodeId); // ID is invalid, cannot assign ID
|
||||
setIndication(INDICATION_ERR_NET_FULL);
|
||||
_transportConfig.nodeId = AUTO;
|
||||
@@ -434,7 +457,8 @@ bool transportAssignNodeID(const uint8_t newNodeId) {
|
||||
}
|
||||
}
|
||||
|
||||
bool transportRouteMessage(MyMessage &message) {
|
||||
bool transportRouteMessage(MyMessage &message)
|
||||
{
|
||||
const uint8_t destination = message.destination;
|
||||
uint8_t route = _transportConfig.parentNodeId; // by default, all traffic is routed via parent node
|
||||
|
||||
@@ -446,11 +470,9 @@ bool transportRouteMessage(MyMessage &message) {
|
||||
|
||||
if (destination == GATEWAY_ADDRESS) {
|
||||
route = _transportConfig.parentNodeId; // message to GW always routes via parent
|
||||
}
|
||||
else if (destination == BROADCAST_ADDRESS) {
|
||||
} else if (destination == BROADCAST_ADDRESS) {
|
||||
route = BROADCAST_ADDRESS; // message to BC does not require routing
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
#if defined(MY_REPEATER_FEATURE)
|
||||
// destination not GW & not BC, get route
|
||||
route = transportGetRoute(destination);
|
||||
@@ -460,8 +482,7 @@ bool transportRouteMessage(MyMessage &message) {
|
||||
if (message.last != _transportConfig.parentNodeId) {
|
||||
// message not from parent, i.e. child node - route it to parent
|
||||
route = _transportConfig.parentNodeId;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// route unknown and msg received from parent, send it to destination assuming in rx radius
|
||||
route = destination;
|
||||
}
|
||||
@@ -482,8 +503,9 @@ bool transportRouteMessage(MyMessage &message) {
|
||||
if (!result) {
|
||||
setIndication(INDICATION_ERR_TX);
|
||||
_transportSM.failedUplinkTransmissions++;
|
||||
} else {
|
||||
_transportSM.failedUplinkTransmissions = 0u;
|
||||
}
|
||||
else _transportSM.failedUplinkTransmissions = 0u;
|
||||
}
|
||||
#else
|
||||
if(!result) {
|
||||
@@ -494,12 +516,12 @@ bool transportRouteMessage(MyMessage &message) {
|
||||
return result;
|
||||
}
|
||||
|
||||
bool transportSendRoute(MyMessage &message) {
|
||||
bool transportSendRoute(MyMessage &message)
|
||||
{
|
||||
bool result = false;
|
||||
if (isTransportReady()) {
|
||||
result = transportRouteMessage(message);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// TNR: transport not ready
|
||||
TRANSPORT_DEBUG(PSTR("!TSF:SND:TNR\n"));
|
||||
}
|
||||
@@ -507,7 +529,8 @@ bool transportSendRoute(MyMessage &message) {
|
||||
}
|
||||
|
||||
// only be used inside transport
|
||||
bool transportWait(const uint32_t waitingMS, const uint8_t cmd, const uint8_t msgType){
|
||||
bool transportWait(const uint32_t waitingMS, const uint8_t cmd, const uint8_t msgType)
|
||||
{
|
||||
const uint32_t enterMS = hwMillis();
|
||||
// invalidate msg type
|
||||
_msg.type = !msgType;
|
||||
@@ -521,35 +544,37 @@ bool transportWait(const uint32_t waitingMS, const uint8_t cmd, const uint8_t ms
|
||||
return expectedResponse;
|
||||
}
|
||||
|
||||
uint8_t transportPingNode(const uint8_t targetId) {
|
||||
uint8_t transportPingNode(const uint8_t targetId)
|
||||
{
|
||||
if(!_transportSM.pingActive) {
|
||||
TRANSPORT_DEBUG(PSTR("TSF:PNG:SEND,TO=%d\n"), targetId);
|
||||
if(targetId == _transportConfig.nodeId) {
|
||||
// pinging self
|
||||
_transportSM.pingResponse = 0u;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
_transportSM.pingActive = true;
|
||||
_transportSM.pingResponse = INVALID_HOPS;
|
||||
(void)transportRouteMessage(build(_msgTmp, targetId, NODE_SENSOR_ID, C_INTERNAL, I_PING).set((uint8_t)0x01));
|
||||
(void)transportRouteMessage(build(_msgTmp, targetId, NODE_SENSOR_ID, C_INTERNAL,
|
||||
I_PING).set((uint8_t)0x01));
|
||||
// Wait for ping reply or timeout
|
||||
(void)transportWait(2000, C_INTERNAL, I_PONG);
|
||||
}
|
||||
// make sure missing I_PONG msg does not block pinging function by leaving pignActive=true
|
||||
_transportSM.pingActive = false;
|
||||
return _transportSM.pingResponse;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
TRANSPORT_DEBUG(PSTR("!TSF:PNG:ACTIVE\n")); // ping active, cannot start new ping
|
||||
return INVALID_HOPS;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t transportGetHeartbeat(void) {
|
||||
uint32_t transportGetHeartbeat(void)
|
||||
{
|
||||
return transportTimeInState();
|
||||
}
|
||||
|
||||
void transportProcessMessage(void) {
|
||||
void transportProcessMessage(void)
|
||||
{
|
||||
// Manage signing timeout
|
||||
(void)signerCheckTimer();
|
||||
// receive message
|
||||
@@ -571,19 +596,22 @@ void transportProcessMessage(void) {
|
||||
const uint8_t destination = _msg.destination;
|
||||
|
||||
TRANSPORT_DEBUG(PSTR("TSF:MSG:READ,%d-%d-%d,s=%d,c=%d,t=%d,pt=%d,l=%d,sg=%d:%s\n"),
|
||||
sender, last, destination, _msg.sensor, command, type, mGetPayloadType(_msg), msgLength, mGetSigned(_msg), _msg.getString(_convBuf));
|
||||
sender, last, destination, _msg.sensor, command, type, mGetPayloadType(_msg), msgLength,
|
||||
mGetSigned(_msg), _msg.getString(_convBuf));
|
||||
|
||||
// Reject payloads with incorrect length
|
||||
if (payloadLength != expectedMessageLength) {
|
||||
setIndication(INDICATION_ERR_LENGTH);
|
||||
TRANSPORT_DEBUG(PSTR("!TSF:MSG:LEN,%d!=%d\n"), payloadLength, expectedMessageLength); // invalid payload length
|
||||
TRANSPORT_DEBUG(PSTR("!TSF:MSG:LEN,%d!=%d\n"), payloadLength,
|
||||
expectedMessageLength); // invalid payload length
|
||||
return;
|
||||
}
|
||||
|
||||
// Reject messages with incorrect protocol version
|
||||
if (mGetVersion(_msg) != PROTOCOL_VERSION) {
|
||||
setIndication(INDICATION_ERR_VERSION);
|
||||
TRANSPORT_DEBUG(PSTR("!TSF:MSG:PVER,%d=%d\n"), mGetVersion(_msg), PROTOCOL_VERSION); // protocol version mismatch
|
||||
TRANSPORT_DEBUG(PSTR("!TSF:MSG:PVER,%d=%d\n"), mGetVersion(_msg),
|
||||
PROTOCOL_VERSION); // protocol version mismatch
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -597,14 +625,14 @@ void transportProcessMessage(void) {
|
||||
// update routing table if msg not from parent
|
||||
#if defined(MY_REPEATER_FEATURE)
|
||||
#if !defined(MY_GATEWAY_FEATURE)
|
||||
if (last != getParentNodeId())
|
||||
{
|
||||
if (last != getParentNodeId()) {
|
||||
#else
|
||||
// GW doesn't have parent
|
||||
{
|
||||
#endif
|
||||
// Message is from one of the child nodes and not sent from this node. Add it to routing table.
|
||||
if (sender != getNodeId()) {
|
||||
if (sender != getNodeId())
|
||||
{
|
||||
transportSetRoute(sender, last);
|
||||
}
|
||||
}
|
||||
@@ -623,7 +651,8 @@ void transportProcessMessage(void) {
|
||||
if (mGetRequestAck(_msg)) {
|
||||
TRANSPORT_DEBUG(PSTR("TSF:MSG:ACK REQ\n")); // ACK requested
|
||||
_msgTmp = _msg; // Copy message
|
||||
mSetRequestAck(_msgTmp, false); // Reply without ack flag (otherwise we would end up in an eternal loop)
|
||||
mSetRequestAck(_msgTmp,
|
||||
false); // Reply without ack flag (otherwise we would end up in an eternal loop)
|
||||
mSetAck(_msgTmp, true); // set ACK flag
|
||||
_msgTmp.sender = _transportConfig.nodeId;
|
||||
_msgTmp.destination = sender;
|
||||
@@ -653,7 +682,8 @@ void transportProcessMessage(void) {
|
||||
if (isValidDistance(distance)) {
|
||||
distance++; // Distance to gateway is one more for us w.r.t. parent
|
||||
// update settings if distance shorter or preferred parent found
|
||||
if (((isValidDistance(distance) && distance < _transportConfig.distanceGW) || (!_autoFindParent && sender == (uint8_t)MY_PARENT_NODE_ID)) && !_transportSM.preferredParentFound) {
|
||||
if (((isValidDistance(distance) && distance < _transportConfig.distanceGW) || (!_autoFindParent &&
|
||||
sender == (uint8_t)MY_PARENT_NODE_ID)) && !_transportSM.preferredParentFound) {
|
||||
// Found a neighbor closer to GW than previously found
|
||||
if (!_autoFindParent && sender == (uint8_t)MY_PARENT_NODE_ID) {
|
||||
_transportSM.preferredParentFound = true;
|
||||
@@ -661,11 +691,11 @@ void transportProcessMessage(void) {
|
||||
}
|
||||
_transportConfig.distanceGW = distance;
|
||||
_transportConfig.parentNodeId = sender;
|
||||
TRANSPORT_DEBUG(PSTR("TSF:MSG:FPAR OK,ID=%d,D=%d\n"), _transportConfig.parentNodeId, _transportConfig.distanceGW);
|
||||
TRANSPORT_DEBUG(PSTR("TSF:MSG:FPAR OK,ID=%d,D=%d\n"), _transportConfig.parentNodeId,
|
||||
_transportConfig.distanceGW);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
TRANSPORT_DEBUG(PSTR("!TSF:MSG:FPAR INACTIVE\n")); // find parent response received, but inactive
|
||||
}
|
||||
return;
|
||||
@@ -679,7 +709,8 @@ void transportProcessMessage(void) {
|
||||
// delay for fast GW and slow nodes
|
||||
delay(5);
|
||||
#endif
|
||||
(void)transportRouteMessage(build(_msgTmp, sender, NODE_SENSOR_ID, C_INTERNAL, I_PONG).set((uint8_t)1));
|
||||
(void)transportRouteMessage(build(_msgTmp, sender, NODE_SENSOR_ID, C_INTERNAL,
|
||||
I_PONG).set((uint8_t)1));
|
||||
return; // no further processing required
|
||||
}
|
||||
if (type == I_PONG) {
|
||||
@@ -687,8 +718,7 @@ void transportProcessMessage(void) {
|
||||
_transportSM.pingActive = false;
|
||||
_transportSM.pingResponse = _msg.getByte();
|
||||
TRANSPORT_DEBUG(PSTR("TSF:MSG:PONG RECV,HP=%d\n"), _transportSM.pingResponse); // pong received
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
TRANSPORT_DEBUG(PSTR("!TSF:MSG:PONG RECV,INACTIVE\n")); // pong received, but !pingActive
|
||||
}
|
||||
return; // no further processing required
|
||||
@@ -703,9 +733,9 @@ void transportProcessMessage(void) {
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else {
|
||||
TRANSPORT_DEBUG(PSTR("TSF:MSG:ACK\n")); // received message is ACK, no internal processing, handover to msg callback
|
||||
} else {
|
||||
TRANSPORT_DEBUG(
|
||||
PSTR("TSF:MSG:ACK\n")); // received message is ACK, no internal processing, handover to msg callback
|
||||
}
|
||||
#if defined(MY_GATEWAY_FEATURE)
|
||||
// Hand over message to controller
|
||||
@@ -715,8 +745,7 @@ void transportProcessMessage(void) {
|
||||
if (receive) {
|
||||
receive(_msg);
|
||||
}
|
||||
}
|
||||
else if (destination == BROADCAST_ADDRESS) {
|
||||
} else if (destination == BROADCAST_ADDRESS) {
|
||||
TRANSPORT_DEBUG(PSTR("TSF:MSG:BC\n")); // broadcast msg
|
||||
if (command == C_INTERNAL) {
|
||||
if (isTransportReady()) {
|
||||
@@ -732,9 +761,9 @@ void transportProcessMessage(void) {
|
||||
TRANSPORT_DEBUG(PSTR("TSF:MSG:GWL OK\n")); // GW uplink ok
|
||||
// random delay minimizes collisions
|
||||
delay(hwMillis() & 0x3ff);
|
||||
(void)transportRouteMessage(build(_msgTmp, sender, NODE_SENSOR_ID, C_INTERNAL, I_FIND_PARENT_RESPONSE).set(_transportConfig.distanceGW));
|
||||
}
|
||||
else {
|
||||
(void)transportRouteMessage(build(_msgTmp, sender, NODE_SENSOR_ID, C_INTERNAL,
|
||||
I_FIND_PARENT_RESPONSE).set(_transportConfig.distanceGW));
|
||||
} else {
|
||||
TRANSPORT_DEBUG(PSTR("!TSF:MSG:GWL FAIL\n")); // GW uplink fail, do not respond to parent request
|
||||
}
|
||||
}
|
||||
@@ -750,7 +779,8 @@ void transportProcessMessage(void) {
|
||||
if (last == _transportConfig.parentNodeId) {
|
||||
// random wait to minimize collisions
|
||||
delay(hwMillis() & 0x3ff);
|
||||
(void)transportRouteMessage(build(_msgTmp, sender, NODE_SENSOR_ID, C_INTERNAL, I_DISCOVER_RESPONSE).set(_transportConfig.parentNodeId));
|
||||
(void)transportRouteMessage(build(_msgTmp, sender, NODE_SENSOR_ID, C_INTERNAL,
|
||||
I_DISCOVER_RESPONSE).set(_transportConfig.parentNodeId));
|
||||
// no return here (for fwd if repeater)
|
||||
}
|
||||
}
|
||||
@@ -759,7 +789,8 @@ void transportProcessMessage(void) {
|
||||
// controlled BC relay
|
||||
#if defined(MY_REPEATER_FEATURE)
|
||||
// controlled BC repeating: forward only if message received from parent and sender not self to prevent circular fwds
|
||||
if(last == _transportConfig.parentNodeId && sender != _transportConfig.nodeId && isTransportReady()){
|
||||
if(last == _transportConfig.parentNodeId && sender != _transportConfig.nodeId &&
|
||||
isTransportReady()) {
|
||||
TRANSPORT_DEBUG(PSTR("TSF:MSG:FWD BC MSG\n")); // controlled broadcast msg forwarding
|
||||
(void)transportRouteMessage(_msg);
|
||||
}
|
||||
@@ -782,8 +813,7 @@ void transportProcessMessage(void) {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// msg not to us and not BC, relay msg
|
||||
#if defined(MY_REPEATER_FEATURE)
|
||||
if (isTransportReady()) {
|
||||
@@ -807,17 +837,18 @@ void transportProcessMessage(void) {
|
||||
}
|
||||
}
|
||||
|
||||
void transportInvokeSanityCheck(void) {
|
||||
void transportInvokeSanityCheck(void)
|
||||
{
|
||||
if (!transportSanityCheck()) {
|
||||
TRANSPORT_DEBUG(PSTR("!TSF:SNK:FAIL\n")); // sanity check fail
|
||||
transportSwitchSM(stFailure);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
TRANSPORT_DEBUG(PSTR("TSF:SNK:OK\n")); // sanity check ok
|
||||
}
|
||||
}
|
||||
|
||||
void transportProcessFIFO(void) {
|
||||
void transportProcessFIFO(void)
|
||||
{
|
||||
if (!_transportSM.transportActive) {
|
||||
// transport not active, no further processing required
|
||||
return;
|
||||
@@ -843,7 +874,8 @@ void transportProcessFIFO(void) {
|
||||
#endif
|
||||
}
|
||||
|
||||
bool transportSendWrite(const uint8_t to, MyMessage &message) {
|
||||
bool transportSendWrite(const uint8_t to, MyMessage &message)
|
||||
{
|
||||
message.last = _transportConfig.nodeId; // Update last
|
||||
// sign message if required
|
||||
if (!signerSignMsg(message)) {
|
||||
@@ -853,7 +885,8 @@ bool transportSendWrite(const uint8_t to, MyMessage &message) {
|
||||
}
|
||||
|
||||
// msg length changes if signed
|
||||
const uint8_t totalMsgLength = HEADER_SIZE + ( mGetSigned(message) ? MAX_PAYLOAD : mGetLength(message) );
|
||||
const uint8_t totalMsgLength = HEADER_SIZE + ( mGetSigned(message) ? MAX_PAYLOAD : mGetLength(
|
||||
message) );
|
||||
|
||||
// send
|
||||
setIndication(INDICATION_TX);
|
||||
@@ -862,8 +895,10 @@ bool transportSendWrite(const uint8_t to, MyMessage &message) {
|
||||
result |= (to == BROADCAST_ADDRESS);
|
||||
|
||||
TRANSPORT_DEBUG(PSTR("%sTSF:MSG:SEND,%d-%d-%d-%d,s=%d,c=%d,t=%d,pt=%d,l=%d,sg=%d,ft=%d,st=%s:%s\n"),
|
||||
(result ? "" : "!"), message.sender, message.last, to, message.destination, message.sensor, mGetCommand(message), message.type,
|
||||
mGetPayloadType(message), mGetLength(message), mGetSigned(message), _transportSM.failedUplinkTransmissions, (result ? "OK" : "NACK"), message.getString(_convBuf));
|
||||
(result ? "" : "!"), message.sender, message.last, to, message.destination, message.sensor,
|
||||
mGetCommand(message), message.type,
|
||||
mGetPayloadType(message), mGetLength(message), mGetSigned(message),
|
||||
_transportSM.failedUplinkTransmissions, (result ? "OK" : "NACK"), message.getString(_convBuf));
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -887,7 +922,8 @@ uint8_t transportGetDistanceGW(void)
|
||||
}
|
||||
|
||||
|
||||
void transportClearRoutingTable(void) {
|
||||
void transportClearRoutingTable(void)
|
||||
{
|
||||
for (uint16_t i = 0; i < SIZE_ROUTES; i++) {
|
||||
transportSetRoute((uint8_t)i, BROADCAST_ADDRESS);
|
||||
}
|
||||
@@ -895,21 +931,24 @@ void transportClearRoutingTable(void) {
|
||||
TRANSPORT_DEBUG(PSTR("TSF:CRT:OK\n")); // clear routing table
|
||||
}
|
||||
|
||||
void transportLoadRoutingTable(void) {
|
||||
void transportLoadRoutingTable(void)
|
||||
{
|
||||
#if defined(MY_RAM_ROUTING_TABLE_ENABLED)
|
||||
hwReadConfigBlock((void*)&_transportRoutingTable.route, (void*)EEPROM_ROUTES_ADDRESS, SIZE_ROUTES);
|
||||
TRANSPORT_DEBUG(PSTR("TSF:LRT:OK\n")); // load routing table
|
||||
#endif
|
||||
}
|
||||
|
||||
void transportSaveRoutingTable(void) {
|
||||
void transportSaveRoutingTable(void)
|
||||
{
|
||||
#if defined(MY_RAM_ROUTING_TABLE_ENABLED)
|
||||
hwWriteConfigBlock((void*)&_transportRoutingTable.route, (void*)EEPROM_ROUTES_ADDRESS, SIZE_ROUTES);
|
||||
TRANSPORT_DEBUG(PSTR("TSF:SRT:OK\n")); // save routing table
|
||||
#endif
|
||||
}
|
||||
|
||||
void transportSetRoute(const uint8_t node, const uint8_t route) {
|
||||
void transportSetRoute(const uint8_t node, const uint8_t route)
|
||||
{
|
||||
#if defined(MY_RAM_ROUTING_TABLE_ENABLED)
|
||||
_transportRoutingTable.route[node] = route;
|
||||
#else
|
||||
@@ -917,7 +956,8 @@ void transportSetRoute(const uint8_t node, const uint8_t route) {
|
||||
#endif
|
||||
}
|
||||
|
||||
uint8_t transportGetRoute(const uint8_t node) {
|
||||
uint8_t transportGetRoute(const uint8_t node)
|
||||
{
|
||||
uint8_t result;
|
||||
#if defined(MY_RAM_ROUTING_TABLE_ENABLED)
|
||||
result = _transportRoutingTable.route[node];
|
||||
|
||||
@@ -37,7 +37,8 @@ typedef struct _transportQueuedMessage {
|
||||
/** Buffer to store queued messages in. */
|
||||
static transportQueuedMessage transportRxQueueStorage[MY_RX_MESSAGE_BUFFER_SIZE];
|
||||
/** Circular buffer, which uses the transportRxQueueStorage and administers stored messages. */
|
||||
static CircularBuffer<transportQueuedMessage> transportRxQueue(transportRxQueueStorage, MY_RX_MESSAGE_BUFFER_SIZE);
|
||||
static CircularBuffer<transportQueuedMessage> transportRxQueue(transportRxQueueStorage,
|
||||
MY_RX_MESSAGE_BUFFER_SIZE);
|
||||
|
||||
static volatile uint8_t transportLostMessageCount = 0;
|
||||
|
||||
|
||||
@@ -26,7 +26,8 @@ RFM69 _radio(MY_RF69_SPI_CS, MY_RF69_IRQ_PIN, MY_RFM69HW, MY_RF69_IRQ_NUM);
|
||||
uint8_t _address;
|
||||
|
||||
|
||||
bool transportInit() {
|
||||
bool transportInit()
|
||||
{
|
||||
// Start up the radio library (_address will be set later by the MySensors library)
|
||||
if (_radio.initialize(MY_RFM69_FREQUENCY, _address, MY_RFM69_NETWORKID)) {
|
||||
#ifdef MY_RFM69_ENABLE_ENCRYPTION
|
||||
@@ -40,29 +41,35 @@ bool transportInit() {
|
||||
return false;
|
||||
}
|
||||
|
||||
void transportSetAddress(uint8_t address) {
|
||||
void transportSetAddress(uint8_t address)
|
||||
{
|
||||
_address = address;
|
||||
_radio.setAddress(address);
|
||||
}
|
||||
|
||||
uint8_t transportGetAddress() {
|
||||
uint8_t transportGetAddress()
|
||||
{
|
||||
return _address;
|
||||
}
|
||||
|
||||
bool transportSend(uint8_t to, const void* data, uint8_t len) {
|
||||
bool transportSend(uint8_t to, const void* data, uint8_t len)
|
||||
{
|
||||
return _radio.sendWithRetry(to,data,len);
|
||||
}
|
||||
|
||||
bool transportAvailable() {
|
||||
bool transportAvailable()
|
||||
{
|
||||
return _radio.receiveDone();
|
||||
}
|
||||
|
||||
bool transportSanityCheck() {
|
||||
bool transportSanityCheck()
|
||||
{
|
||||
// not implemented yet
|
||||
return true;
|
||||
}
|
||||
|
||||
uint8_t transportReceive(void* data) {
|
||||
uint8_t transportReceive(void* data)
|
||||
{
|
||||
memcpy(data,(const void *)_radio.DATA, _radio.DATALEN);
|
||||
// save payload length
|
||||
const uint8_t dataLen = _radio.DATALEN;
|
||||
@@ -73,6 +80,7 @@ uint8_t transportReceive(void* data) {
|
||||
return dataLen;
|
||||
}
|
||||
|
||||
void transportPowerDown() {
|
||||
void transportPowerDown()
|
||||
{
|
||||
_radio.sleep();
|
||||
}
|
||||
|
||||
@@ -22,7 +22,8 @@
|
||||
#include "MyTransport.h"
|
||||
#include "drivers/RFM95/RFM95.h"
|
||||
|
||||
bool transportInit(void) {
|
||||
bool transportInit(void)
|
||||
{
|
||||
const bool result = RFM95_initialise(MY_RFM95_FREQUENCY);
|
||||
#if !defined(MY_GATEWAY_FEATURE) && !defined(MY_RFM95_ATC_MODE_DISABLED)
|
||||
// only enable ATC mode nodes
|
||||
@@ -31,34 +32,42 @@ bool transportInit(void) {
|
||||
return result;
|
||||
}
|
||||
|
||||
void transportSetAddress(uint8_t address) {
|
||||
void transportSetAddress(uint8_t address)
|
||||
{
|
||||
RFM95_setAddress(address);
|
||||
}
|
||||
|
||||
uint8_t transportGetAddress(void) {
|
||||
uint8_t transportGetAddress(void)
|
||||
{
|
||||
return RFM95_getAddress();
|
||||
}
|
||||
|
||||
bool transportSend(uint8_t to, const void* data, uint8_t len) {
|
||||
bool transportSend(uint8_t to, const void* data, uint8_t len)
|
||||
{
|
||||
return RFM95_sendWithRetry(to, data, len);
|
||||
}
|
||||
|
||||
bool transportAvailable(void) {
|
||||
bool transportAvailable(void)
|
||||
{
|
||||
return RFM95_available();
|
||||
}
|
||||
|
||||
bool transportSanityCheck(void) {
|
||||
bool transportSanityCheck(void)
|
||||
{
|
||||
return RFM95_sanityCheck();
|
||||
}
|
||||
|
||||
uint8_t transportReceive(void* data) {
|
||||
uint8_t transportReceive(void* data)
|
||||
{
|
||||
return RFM95_recv((uint8_t*)data);
|
||||
}
|
||||
|
||||
void transportPowerDown(void) {
|
||||
void transportPowerDown(void)
|
||||
{
|
||||
(void)RFM95_sleep();
|
||||
}
|
||||
|
||||
int16_t transportGetSignalStrength(void) {
|
||||
int16_t transportGetSignalStrength(void)
|
||||
{
|
||||
return RFM95_getRSSI();
|
||||
}
|
||||
|
||||
+17
-10
@@ -114,7 +114,8 @@ bool _packet_received;
|
||||
|
||||
|
||||
//Reset the state machine and release the data pointer
|
||||
void _serialReset(){
|
||||
void _serialReset()
|
||||
{
|
||||
_recPhase = 0;
|
||||
_recPos = 0;
|
||||
_recLen = 0;
|
||||
@@ -318,7 +319,8 @@ bool transportSend(uint8_t to, const void* data, uint8_t len)
|
||||
|
||||
|
||||
|
||||
bool transportInit() {
|
||||
bool transportInit()
|
||||
{
|
||||
// Reset the state machine
|
||||
_dev.begin(MY_RS485_BAUD_RATE);
|
||||
_serialReset();
|
||||
@@ -329,36 +331,41 @@ bool transportInit() {
|
||||
return true;
|
||||
}
|
||||
|
||||
void transportSetAddress(uint8_t address) {
|
||||
void transportSetAddress(uint8_t address)
|
||||
{
|
||||
_nodeId = address;
|
||||
}
|
||||
|
||||
uint8_t transportGetAddress() {
|
||||
uint8_t transportGetAddress()
|
||||
{
|
||||
return _nodeId;
|
||||
}
|
||||
|
||||
|
||||
bool transportAvailable() {
|
||||
bool transportAvailable()
|
||||
{
|
||||
_serialProcess();
|
||||
return _packet_received;
|
||||
}
|
||||
|
||||
bool transportSanityCheck() {
|
||||
bool transportSanityCheck()
|
||||
{
|
||||
// not implemented yet
|
||||
return true;
|
||||
}
|
||||
|
||||
uint8_t transportReceive(void* data) {
|
||||
uint8_t transportReceive(void* data)
|
||||
{
|
||||
if (_packet_received) {
|
||||
memcpy(data,_data,_packet_len);
|
||||
_packet_received = false;
|
||||
return _packet_len;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
void transportPowerDown() {
|
||||
void transportPowerDown()
|
||||
{
|
||||
// Nothing to shut down here
|
||||
}
|
||||
|
||||
+102
-82
@@ -65,8 +65,7 @@
|
||||
#define WPOLY 0x011B
|
||||
#define DPOLY 0x008D
|
||||
|
||||
const static byte s_fwd [0x100] PROGMEM =
|
||||
{
|
||||
const static byte s_fwd [0x100] PROGMEM = {
|
||||
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,
|
||||
@@ -85,8 +84,7 @@ const static byte s_fwd [0x100] PROGMEM =
|
||||
0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16,
|
||||
} ;
|
||||
|
||||
const static byte s_inv [0x100] PROGMEM =
|
||||
{
|
||||
const static byte s_inv [0x100] PROGMEM = {
|
||||
0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
|
||||
0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
|
||||
0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
|
||||
@@ -125,8 +123,7 @@ static byte is_box (byte x)
|
||||
|
||||
static void xor_block (byte * d, byte * s)
|
||||
{
|
||||
for (byte i = 0 ; i < N_BLOCK ; i += 4)
|
||||
{
|
||||
for (byte i = 0 ; i < N_BLOCK ; i += 4) {
|
||||
*d++ ^= *s++ ; // some unrolling
|
||||
*d++ ^= *s++ ;
|
||||
*d++ ^= *s++ ;
|
||||
@@ -136,8 +133,7 @@ static void xor_block (byte * d, byte * s)
|
||||
|
||||
static void copy_and_key (byte * d, byte * s, byte * k)
|
||||
{
|
||||
for (byte i = 0 ; i < N_BLOCK ; i += 4)
|
||||
{
|
||||
for (byte i = 0 ; i < N_BLOCK ; i += 4) {
|
||||
*d++ = *s++ ^ *k++ ; // some unrolling
|
||||
*d++ = *s++ ^ *k++ ;
|
||||
*d++ = *s++ ^ *k++ ;
|
||||
@@ -151,36 +147,56 @@ static void copy_and_key (byte * d, byte * s, byte * k)
|
||||
|
||||
static void shift_sub_rows (byte st [N_BLOCK])
|
||||
{
|
||||
st [0] = s_box (st [0]) ; st [4] = s_box (st [4]) ;
|
||||
st [8] = s_box (st [8]) ; st [12] = s_box (st [12]) ;
|
||||
st [0] = s_box (st [0]) ;
|
||||
st [4] = s_box (st [4]) ;
|
||||
st [8] = s_box (st [8]) ;
|
||||
st [12] = s_box (st [12]) ;
|
||||
|
||||
byte tt = st [1] ;
|
||||
st [1] = s_box (st [5]) ; st [5] = s_box (st [9]) ;
|
||||
st [9] = s_box (st [13]) ; st [13] = s_box (tt) ;
|
||||
st [1] = s_box (st [5]) ;
|
||||
st [5] = s_box (st [9]) ;
|
||||
st [9] = s_box (st [13]) ;
|
||||
st [13] = s_box (tt) ;
|
||||
|
||||
tt = st[2] ; st [2] = s_box (st [10]) ; st [10] = s_box (tt) ;
|
||||
tt = st[6] ; st [6] = s_box (st [14]) ; st [14] = s_box (tt) ;
|
||||
tt = st[2] ;
|
||||
st [2] = s_box (st [10]) ;
|
||||
st [10] = s_box (tt) ;
|
||||
tt = st[6] ;
|
||||
st [6] = s_box (st [14]) ;
|
||||
st [14] = s_box (tt) ;
|
||||
|
||||
tt = st[15] ;
|
||||
st [15] = s_box (st [11]) ; st [11] = s_box (st [7]) ;
|
||||
st [7] = s_box (st [3]) ; st [3] = s_box (tt) ;
|
||||
st [15] = s_box (st [11]) ;
|
||||
st [11] = s_box (st [7]) ;
|
||||
st [7] = s_box (st [3]) ;
|
||||
st [3] = s_box (tt) ;
|
||||
}
|
||||
|
||||
static void inv_shift_sub_rows (byte st[N_BLOCK])
|
||||
{
|
||||
st [0] = is_box (st[0]) ; st [4] = is_box (st [4]);
|
||||
st [8] = is_box (st[8]) ; st [12] = is_box (st [12]);
|
||||
st [0] = is_box (st[0]) ;
|
||||
st [4] = is_box (st [4]);
|
||||
st [8] = is_box (st[8]) ;
|
||||
st [12] = is_box (st [12]);
|
||||
|
||||
byte tt = st[13] ;
|
||||
st [13] = is_box (st [9]) ; st [9] = is_box (st [5]) ;
|
||||
st [5] = is_box (st [1]) ; st [1] = is_box (tt) ;
|
||||
st [13] = is_box (st [9]) ;
|
||||
st [9] = is_box (st [5]) ;
|
||||
st [5] = is_box (st [1]) ;
|
||||
st [1] = is_box (tt) ;
|
||||
|
||||
tt = st [2] ; st [2] = is_box (st [10]) ; st [10] = is_box (tt) ;
|
||||
tt = st [6] ; st [6] = is_box (st [14]) ; st [14] = is_box (tt) ;
|
||||
tt = st [2] ;
|
||||
st [2] = is_box (st [10]) ;
|
||||
st [10] = is_box (tt) ;
|
||||
tt = st [6] ;
|
||||
st [6] = is_box (st [14]) ;
|
||||
st [14] = is_box (tt) ;
|
||||
|
||||
tt = st [3] ;
|
||||
st [3] = is_box (st [7]) ; st [7] = is_box (st [11]) ;
|
||||
st [11] = is_box (st [15]) ; st [15] = is_box (tt) ;
|
||||
st [3] = is_box (st [7]) ;
|
||||
st [7] = is_box (st [11]) ;
|
||||
st [11] = is_box (st [15]) ;
|
||||
st [15] = is_box (tt) ;
|
||||
}
|
||||
|
||||
/* SUB COLUMNS PHASE */
|
||||
@@ -190,12 +206,14 @@ static void mix_sub_columns (byte dt[N_BLOCK], byte st[N_BLOCK])
|
||||
byte j = 5 ;
|
||||
byte k = 10 ;
|
||||
byte l = 15 ;
|
||||
for (byte i = 0 ; i < N_BLOCK ; i += N_COL)
|
||||
{
|
||||
for (byte i = 0 ; i < N_BLOCK ; i += N_COL) {
|
||||
byte a = st [i] ;
|
||||
byte b = st [j] ; j = (j+N_COL) & 15 ;
|
||||
byte c = st [k] ; k = (k+N_COL) & 15 ;
|
||||
byte d = st [l] ; l = (l+N_COL) & 15 ;
|
||||
byte b = st [j] ;
|
||||
j = (j+N_COL) & 15 ;
|
||||
byte c = st [k] ;
|
||||
k = (k+N_COL) & 15 ;
|
||||
byte d = st [l] ;
|
||||
l = (l+N_COL) & 15 ;
|
||||
byte a1 = s_box (a), b1 = s_box (b), c1 = s_box (c), d1 = s_box (d) ;
|
||||
byte a2 = f2(a1), b2 = f2(b1), c2 = f2(c1), d2 = f2(d1) ;
|
||||
dt[i] = a2 ^ b2^b1 ^ c1 ^ d1 ;
|
||||
@@ -207,8 +225,7 @@ static void mix_sub_columns (byte dt[N_BLOCK], byte st[N_BLOCK])
|
||||
|
||||
static void inv_mix_sub_columns (byte dt[N_BLOCK], byte st[N_BLOCK])
|
||||
{
|
||||
for (byte i = 0 ; i < N_BLOCK ; i += N_COL)
|
||||
{
|
||||
for (byte i = 0 ; i < N_BLOCK ; i += N_COL) {
|
||||
byte a1 = st [i] ;
|
||||
byte b1 = st [i+1] ;
|
||||
byte c1 = st [i+2] ;
|
||||
@@ -228,7 +245,8 @@ static void inv_mix_sub_columns (byte dt[N_BLOCK], byte st[N_BLOCK])
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
AES::AES(){
|
||||
AES::AES()
|
||||
{
|
||||
byte ar_iv[8] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01 };
|
||||
memcpy(iv,ar_iv,8);
|
||||
memcpy(iv+8,ar_iv,8);
|
||||
@@ -254,8 +272,7 @@ AES::AES(){
|
||||
byte AES::set_key (byte key [], int keylen)
|
||||
{
|
||||
byte hi ;
|
||||
switch (keylen)
|
||||
{
|
||||
switch (keylen) {
|
||||
case 16:
|
||||
case 128:
|
||||
keylen = 16; // 10 rounds
|
||||
@@ -279,13 +296,11 @@ byte AES::set_key (byte key [], int keylen)
|
||||
copy_n_bytes (key_sched, key, keylen) ;
|
||||
byte t[4] ;
|
||||
byte next = keylen ;
|
||||
for (byte cc = keylen, rc = 1 ; cc < hi ; cc += N_COL)
|
||||
{
|
||||
for (byte cc = keylen, rc = 1 ; cc < hi ; cc += N_COL) {
|
||||
for (byte i = 0 ; i < N_COL ; i++) {
|
||||
t[i] = key_sched [cc-4+i] ;
|
||||
}
|
||||
if (cc == next)
|
||||
{
|
||||
if (cc == next) {
|
||||
next += keylen ;
|
||||
byte ttt = t[0] ;
|
||||
t[0] = s_box (t[1]) ^ rc ;
|
||||
@@ -293,9 +308,7 @@ byte AES::set_key (byte key [], int keylen)
|
||||
t[2] = s_box (t[3]) ;
|
||||
t[3] = s_box (ttt) ;
|
||||
rc = f2 (rc) ;
|
||||
}
|
||||
else if (keylen == 32 && (cc & 31) == 16)
|
||||
{
|
||||
} else if (keylen == 32 && (cc & 31) == 16) {
|
||||
for (byte i = 0 ; i < 4 ; i++) {
|
||||
t[i] = s_box (t[i]) ;
|
||||
}
|
||||
@@ -322,38 +335,36 @@ void AES::clean ()
|
||||
|
||||
void AES::copy_n_bytes (byte * d, byte * s, byte nn)
|
||||
{
|
||||
while (nn >= 4)
|
||||
{
|
||||
while (nn >= 4) {
|
||||
*d++ = *s++ ; // some unrolling
|
||||
*d++ = *s++ ;
|
||||
*d++ = *s++ ;
|
||||
*d++ = *s++ ;
|
||||
nn -= 4 ;
|
||||
}
|
||||
while (nn--)
|
||||
while (nn--) {
|
||||
*d++ = *s++ ;
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
byte AES::encrypt (byte plain [N_BLOCK], byte cipher [N_BLOCK])
|
||||
{
|
||||
if (round)
|
||||
{
|
||||
if (round) {
|
||||
byte s1 [N_BLOCK], r ;
|
||||
copy_and_key (s1, plain, (byte*) (key_sched)) ;
|
||||
|
||||
for (r = 1 ; r < round ; r++)
|
||||
{
|
||||
for (r = 1 ; r < round ; r++) {
|
||||
byte s2 [N_BLOCK] ;
|
||||
mix_sub_columns (s2, s1) ;
|
||||
copy_and_key (s1, s2, (byte*) (key_sched + r * N_BLOCK)) ;
|
||||
}
|
||||
shift_sub_rows (s1) ;
|
||||
copy_and_key (cipher, s1, (byte*) (key_sched + r * N_BLOCK)) ;
|
||||
}
|
||||
else
|
||||
} else {
|
||||
return AES_FAILURE ;
|
||||
}
|
||||
return AES_SUCCESS ;
|
||||
}
|
||||
|
||||
@@ -361,8 +372,7 @@ byte AES::encrypt (byte plain [N_BLOCK], byte cipher [N_BLOCK])
|
||||
|
||||
byte AES::cbc_encrypt (byte * plain, byte * cipher, int n_block, byte iv [N_BLOCK])
|
||||
{
|
||||
while (n_block--)
|
||||
{
|
||||
while (n_block--) {
|
||||
xor_block (iv, plain) ;
|
||||
if (encrypt (iv, iv) != AES_SUCCESS) {
|
||||
return AES_FAILURE ;
|
||||
@@ -378,8 +388,7 @@ byte AES::cbc_encrypt (byte * plain, byte * cipher, int n_block, byte iv [N_BLOC
|
||||
|
||||
byte AES::cbc_encrypt (byte * plain, byte * cipher, int n_block)
|
||||
{
|
||||
while (n_block--)
|
||||
{
|
||||
while (n_block--) {
|
||||
xor_block (iv, plain) ;
|
||||
if (encrypt (iv, iv) != AES_SUCCESS) {
|
||||
return AES_FAILURE ;
|
||||
@@ -395,22 +404,20 @@ byte AES::cbc_encrypt (byte * plain, byte * cipher, int n_block)
|
||||
|
||||
byte AES::decrypt (byte plain [N_BLOCK], byte cipher [N_BLOCK])
|
||||
{
|
||||
if (round)
|
||||
{
|
||||
if (round) {
|
||||
byte s1 [N_BLOCK] ;
|
||||
copy_and_key (s1, plain, (byte*) (key_sched + round * N_BLOCK)) ;
|
||||
inv_shift_sub_rows (s1) ;
|
||||
|
||||
for (byte r = round ; --r ; )
|
||||
{
|
||||
for (byte r = round ; --r ; ) {
|
||||
byte s2 [N_BLOCK] ;
|
||||
copy_and_key (s2, s1, (byte*) (key_sched + r * N_BLOCK)) ;
|
||||
inv_mix_sub_columns (s1, s2) ;
|
||||
}
|
||||
copy_and_key (cipher, s1, (byte*) (key_sched)) ;
|
||||
}
|
||||
else
|
||||
} else {
|
||||
return AES_FAILURE ;
|
||||
}
|
||||
return AES_SUCCESS ;
|
||||
}
|
||||
|
||||
@@ -418,8 +425,7 @@ byte AES::decrypt (byte plain [N_BLOCK], byte cipher [N_BLOCK])
|
||||
|
||||
byte AES::cbc_decrypt (byte * cipher, byte * plain, int n_block, byte iv [N_BLOCK])
|
||||
{
|
||||
while (n_block--)
|
||||
{
|
||||
while (n_block--) {
|
||||
byte tmp [N_BLOCK] ;
|
||||
copy_n_bytes (tmp, cipher, N_BLOCK) ;
|
||||
if (decrypt (cipher, plain) != AES_SUCCESS) {
|
||||
@@ -437,8 +443,7 @@ byte AES::cbc_decrypt (byte * cipher, byte * plain, int n_block, byte iv [N_BLOC
|
||||
|
||||
byte AES::cbc_decrypt (byte * cipher, byte * plain, int n_block)
|
||||
{
|
||||
while (n_block--)
|
||||
{
|
||||
while (n_block--) {
|
||||
byte tmp [N_BLOCK] ;
|
||||
copy_n_bytes (tmp, cipher, N_BLOCK) ;
|
||||
if (decrypt (cipher, plain) != AES_SUCCESS) {
|
||||
@@ -454,7 +459,8 @@ byte AES::cbc_decrypt (byte * cipher, byte * plain, int n_block)
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void AES::set_IV(unsigned long long int IVCl){
|
||||
void AES::set_IV(unsigned long long int IVCl)
|
||||
{
|
||||
memcpy(iv,&IVCl,8);
|
||||
memcpy(iv+8,&IVCl,8);
|
||||
IVC = IVCl;
|
||||
@@ -462,7 +468,8 @@ void AES::set_IV(unsigned long long int IVCl){
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
void AES::iv_inc(){
|
||||
void AES::iv_inc()
|
||||
{
|
||||
IVC += 1;
|
||||
memcpy(iv,&IVC,8);
|
||||
memcpy(iv+8,&IVC,8);
|
||||
@@ -470,27 +477,31 @@ void AES::iv_inc(){
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
int AES::get_size(){
|
||||
int AES::get_size()
|
||||
{
|
||||
return size;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
void AES::set_size(int sizel){
|
||||
void AES::set_size(int sizel)
|
||||
{
|
||||
size = sizel;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
void AES::get_IV(byte *out){
|
||||
void AES::get_IV(byte *out)
|
||||
{
|
||||
memcpy(out,&IVC,8);
|
||||
memcpy(out+8,&IVC,8);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
void AES::calc_size_n_pad(int p_size){
|
||||
void AES::calc_size_n_pad(int p_size)
|
||||
{
|
||||
int s_of_p = p_size - 1;
|
||||
if ( s_of_p % N_BLOCK == 0) {
|
||||
size = s_of_p;
|
||||
@@ -505,14 +516,16 @@ void AES::calc_size_n_pad(int p_size){
|
||||
void AES::padPlaintext(void* in,byte* out)
|
||||
{
|
||||
memcpy(out,in,size);
|
||||
for (int i = size-pad; i < size; i++){;
|
||||
for (int i = size-pad; i < size; i++) {
|
||||
;
|
||||
out[i] = arr_pad[pad - 1];
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
bool AES::CheckPad(byte* in,int lsize){
|
||||
bool AES::CheckPad(byte* in,int lsize)
|
||||
{
|
||||
if (in[lsize-1] <= 0x0f) {
|
||||
int lpad = (int)in[lsize-1];
|
||||
for (int i = lsize - 1; i >= lsize-lpad; i--) {
|
||||
@@ -534,9 +547,10 @@ uint8_t i,j;
|
||||
uint8_t loops = size/N_BLOCK;
|
||||
uint8_t outp = N_BLOCK;
|
||||
for (j = 0; j < loops; j += 1) {
|
||||
if (p_pad && (j == (loops - 1)) ) { outp = N_BLOCK - pad; }
|
||||
for (i = 0; i < outp; i++)
|
||||
{
|
||||
if (p_pad && (j == (loops - 1)) ) {
|
||||
outp = N_BLOCK - pad;
|
||||
}
|
||||
for (i = 0; i < outp; i++) {
|
||||
printf_P(PSTR("%c"),output[j*N_BLOCK + i]);
|
||||
}
|
||||
}
|
||||
@@ -547,8 +561,7 @@ for (j = 0; j < loops; j += 1){
|
||||
|
||||
void AES::printArray(byte output[],int sizel)
|
||||
{
|
||||
for (int i = 0; i < sizel; i++)
|
||||
{
|
||||
for (int i = 0; i < sizel; i++) {
|
||||
printf_P(PSTR("%x"),output[i]);
|
||||
}
|
||||
printf_P(PSTR("\n"));
|
||||
@@ -557,7 +570,9 @@ void AES::printArray(byte output[],int sizel)
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
void AES::do_aes_encrypt(byte *plain,int size_p,byte *cipher,byte *key, int bits, byte ivl [N_BLOCK]){
|
||||
void AES::do_aes_encrypt(byte *plain,int size_p,byte *cipher,byte *key, int bits,
|
||||
byte ivl [N_BLOCK])
|
||||
{
|
||||
calc_size_n_pad(size_p);
|
||||
byte plain_p[get_size()];
|
||||
padPlaintext(plain,plain_p);
|
||||
@@ -568,7 +583,8 @@ void AES::do_aes_encrypt(byte *plain,int size_p,byte *cipher,byte *key, int bits
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
void AES::do_aes_encrypt(byte *plain,int size_p,byte *cipher,byte *key, int bits){
|
||||
void AES::do_aes_encrypt(byte *plain,int size_p,byte *cipher,byte *key, int bits)
|
||||
{
|
||||
calc_size_n_pad(size_p);
|
||||
byte plain_p[get_size()];
|
||||
padPlaintext(plain,plain_p);
|
||||
@@ -579,7 +595,9 @@ void AES::do_aes_encrypt(byte *plain,int size_p,byte *cipher,byte *key, int bits
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
void AES::do_aes_decrypt(byte *cipher,int size_c,byte *plain,byte *key, int bits, byte ivl [N_BLOCK]){
|
||||
void AES::do_aes_decrypt(byte *cipher,int size_c,byte *plain,byte *key, int bits,
|
||||
byte ivl [N_BLOCK])
|
||||
{
|
||||
set_size(size_c);
|
||||
int blocks = size_c / N_BLOCK;
|
||||
set_key (key, bits);
|
||||
@@ -588,7 +606,8 @@ void AES::do_aes_decrypt(byte *cipher,int size_c,byte *plain,byte *key, int bits
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
void AES::do_aes_decrypt(byte *cipher,int size_c,byte *plain,byte *key, int bits){
|
||||
void AES::do_aes_decrypt(byte *cipher,int size_c,byte *plain,byte *key, int bits)
|
||||
{
|
||||
set_size(size_c);
|
||||
int blocks = size_c / N_BLOCK;
|
||||
set_key (key, bits);
|
||||
@@ -599,7 +618,8 @@ void AES::do_aes_decrypt(byte *cipher,int size_c,byte *plain,byte *key, int bits
|
||||
/******************************************************************************/
|
||||
|
||||
#if defined(AES_LINUX)
|
||||
double AES::millis(){
|
||||
double AES::millis()
|
||||
{
|
||||
gettimeofday(&tv, NULL);
|
||||
return (tv.tv_sec + 0.000001 * tv.tv_usec);
|
||||
}
|
||||
|
||||
+2
-1
@@ -295,7 +295,8 @@ class AES
|
||||
#endif
|
||||
private:
|
||||
int round ;/**< holds the number of rounds to be used. */
|
||||
byte key_sched [KEY_SCHEDULE_BYTES] ;/**< holds the pre-computed key for the encryption/decrpytion. */
|
||||
byte key_sched [KEY_SCHEDULE_BYTES]
|
||||
;/**< holds the pre-computed key for the encryption/decrpytion. */
|
||||
unsigned long long int IVC;/**< holds the initialization vector counter in numerical format. */
|
||||
byte iv[16];/**< holds the initialization vector that will be used in the cipher. */
|
||||
int pad;/**< holds the size of the padding. */
|
||||
|
||||
@@ -22,8 +22,7 @@ int main(int argc, char** argv)
|
||||
|
||||
monte_carlo (128) ;
|
||||
|
||||
for (int keysize = 128 ; keysize <= 256 ; keysize += 64)
|
||||
{
|
||||
for (int keysize = 128 ; keysize <= 256 ; keysize += 64) {
|
||||
prekey_test_var_plaintext (keysize) ;
|
||||
prekey_test_var_key (keysize) ;
|
||||
}
|
||||
@@ -37,12 +36,12 @@ void prekey_test_var_plaintext (int bits)
|
||||
byte succ ;
|
||||
set_bits (bits, key, 0) ; // all zero key
|
||||
succ = aes.set_key (key, bits) ;
|
||||
if (succ != SUCCESS)
|
||||
if (succ != SUCCESS) {
|
||||
printf("Failure set_key\n") ;
|
||||
}
|
||||
|
||||
|
||||
for (int bitcount = 1 ; bitcount <= 128 ; bitcount++)
|
||||
{
|
||||
for (int bitcount = 1 ; bitcount <= 128 ; bitcount++) {
|
||||
printf ("COUNT = %i \n",bitcount-1);
|
||||
print_value ("KEY = ", key, bits) ;
|
||||
set_bits (128, plain, bitcount) ;
|
||||
@@ -50,14 +49,16 @@ void prekey_test_var_plaintext (int bits)
|
||||
print_value ("PLAINTEXT = ", plain, 128) ;
|
||||
|
||||
succ = aes.encrypt (plain, cipher) ;
|
||||
if (succ != SUCCESS)
|
||||
if (succ != SUCCESS) {
|
||||
printf ("Failure encrypt\n") ;
|
||||
}
|
||||
|
||||
print_value ("CIPHERTEXT = ", cipher, 128) ;
|
||||
|
||||
succ = aes.decrypt (cipher, check) ;
|
||||
if (succ != SUCCESS)
|
||||
if (succ != SUCCESS) {
|
||||
printf ("Failure decrypt\n") ;
|
||||
}
|
||||
|
||||
//print_value ("CHECK = ", check, 128) ;
|
||||
check_same (plain, check, 128) ;
|
||||
@@ -73,26 +74,28 @@ void prekey_test_var_key (int bits)
|
||||
byte succ ;
|
||||
set_bits (128, plain, 0) ;
|
||||
|
||||
for (int bitcount = 1 ; bitcount <= bits ; bitcount++)
|
||||
{
|
||||
for (int bitcount = 1 ; bitcount <= bits ; bitcount++) {
|
||||
set_bits (bits, key, bitcount) ; // all zero key
|
||||
succ = aes.set_key (key, bits) ;
|
||||
if (succ != SUCCESS)
|
||||
if (succ != SUCCESS) {
|
||||
printf ("Failure set_key\n") ;
|
||||
}
|
||||
printf ("COUNT = %i\n",bitcount-1);
|
||||
print_value ("KEY = ", key, bits) ;
|
||||
|
||||
print_value ("PLAINTEXT = ", plain, 128) ;
|
||||
|
||||
succ = aes.encrypt (plain, cipher) ;
|
||||
if (succ != SUCCESS)
|
||||
if (succ != SUCCESS) {
|
||||
printf ("Failure encrypt\n") ;
|
||||
}
|
||||
|
||||
print_value ("CIPHERTEXT = ", cipher, 128) ;
|
||||
|
||||
succ = aes.decrypt (cipher, check) ;
|
||||
if (succ != SUCCESS)
|
||||
if (succ != SUCCESS) {
|
||||
printf ("Failure decrypt\n") ;
|
||||
}
|
||||
|
||||
check_same (plain, check, 128) ;
|
||||
printf("\n");
|
||||
@@ -103,20 +106,22 @@ void set_bits (int bits, byte * a, int count)
|
||||
{
|
||||
bits >>= 3 ;
|
||||
byte bcount = count >> 3 ;
|
||||
for (byte i = 0 ; i < bcount ; i++)
|
||||
for (byte i = 0 ; i < bcount ; i++) {
|
||||
a [i] = 0xFF ;
|
||||
if ((count & 7) != 0)
|
||||
}
|
||||
if ((count & 7) != 0) {
|
||||
a [bcount++] = 0xFF & (0xFF00 >> (count & 7)) ;
|
||||
for (byte i = bcount ; i < bits ; i++)
|
||||
}
|
||||
for (byte i = bcount ; i < bits ; i++) {
|
||||
a [i] = 0x00 ;
|
||||
}
|
||||
}
|
||||
|
||||
void check_same (byte * a, byte * b, int bits)
|
||||
{
|
||||
bits >>= 3 ;
|
||||
for (byte i = 0 ; i < bits ; i++)
|
||||
if (a[i] != b[i])
|
||||
{
|
||||
if (a[i] != b[i]) {
|
||||
printf ("Failure plain != check\n") ;
|
||||
return ;
|
||||
}
|
||||
@@ -129,8 +134,7 @@ void print_value (const char * str, byte * a, int bits)
|
||||
{
|
||||
printf ("%s",str) ;
|
||||
bits >>= 3 ;
|
||||
for (int i = 0 ; i < bits ; i++)
|
||||
{
|
||||
for (int i = 0 ; i < bits ; i++) {
|
||||
byte b = a[i] ;
|
||||
printf("%c%c",hex[b >> 4],hex [b & 15]);
|
||||
//Serial.print (hex [b >> 4]) ;
|
||||
@@ -139,45 +143,40 @@ void print_value (const char * str, byte * a, int bits)
|
||||
printf("\n") ;
|
||||
}
|
||||
|
||||
byte monteplain [] =
|
||||
{ 0xb9, 0x14, 0x5a, 0x76, 0x8b, 0x7d, 0xc4, 0x89,
|
||||
0xa0, 0x96, 0xb5, 0x46, 0xf4, 0x3b, 0x23, 0x1f } ;
|
||||
byte montekey [] =
|
||||
{ 0x13, 0x9a, 0x35, 0x42, 0x2f, 0x1d, 0x61, 0xde,
|
||||
0x3c, 0x91, 0x78, 0x7f, 0xe0, 0x50, 0x7a, 0xfd } ;
|
||||
byte monteplain [] = {
|
||||
0xb9, 0x14, 0x5a, 0x76, 0x8b, 0x7d, 0xc4, 0x89,
|
||||
0xa0, 0x96, 0xb5, 0x46, 0xf4, 0x3b, 0x23, 0x1f
|
||||
} ;
|
||||
byte montekey [] = {
|
||||
0x13, 0x9a, 0x35, 0x42, 0x2f, 0x1d, 0x61, 0xde,
|
||||
0x3c, 0x91, 0x78, 0x7f, 0xe0, 0x50, 0x7a, 0xfd
|
||||
} ;
|
||||
|
||||
void monte_carlo (int bits)
|
||||
{
|
||||
printf ("\nMonte Carlo %i bits\n",bits);
|
||||
byte succ;
|
||||
for (int i = 0 ; i < 16 ; i++)
|
||||
{
|
||||
for (int i = 0 ; i < 16 ; i++) {
|
||||
plain [i] = monteplain [i] ;
|
||||
key [i] = montekey [i] ;
|
||||
}
|
||||
for (int i = 0 ; i < 100 ; i++)
|
||||
{
|
||||
for (int i = 0 ; i < 100 ; i++) {
|
||||
printf ("COUNT = %i\n",i);
|
||||
print_value ("KEY = ", key, bits) ;
|
||||
print_value ("PLAINTEXT = ", plain, 128) ;
|
||||
succ = aes.set_key (key, bits) ;
|
||||
for (int j = 0 ; j < 1000 ; j++)
|
||||
{
|
||||
for (int j = 0 ; j < 1000 ; j++) {
|
||||
succ = aes.encrypt (plain, cipher) ;
|
||||
aes.copy_n_bytes (plain, cipher, 16) ;
|
||||
}
|
||||
print_value ("CIPHERTEXT = ", cipher, 128) ;
|
||||
printf("\n");
|
||||
if (bits == 128)
|
||||
{
|
||||
for (byte k = 0 ; k < 16 ; k++)
|
||||
if (bits == 128) {
|
||||
for (byte k = 0 ; k < 16 ; k++) {
|
||||
key [k] ^= cipher [k] ;
|
||||
}
|
||||
else if (bits == 192)
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
} else if (bits == 192) {
|
||||
} else {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,8 @@ static uint8_t swi_send_byte(uint8_t value);
|
||||
static uint8_t sha204p_receive_response(uint8_t size, uint8_t *response);
|
||||
static uint8_t sha204m_read(uint8_t *tx_buffer, uint8_t *rx_buffer, uint8_t zone, uint16_t address);
|
||||
static uint8_t sha204c_resync(uint8_t size, uint8_t *response);
|
||||
static uint8_t sha204c_send_and_receive(uint8_t *tx_buffer, uint8_t rx_size, uint8_t *rx_buffer, uint8_t execution_delay, uint8_t execution_timeout);
|
||||
static uint8_t sha204c_send_and_receive(uint8_t *tx_buffer, uint8_t rx_size, uint8_t *rx_buffer,
|
||||
uint8_t execution_delay, uint8_t execution_timeout);
|
||||
|
||||
/* SWI bit bang functions */
|
||||
|
||||
@@ -26,8 +27,7 @@ static void swi_set_signal_pin(uint8_t is_high)
|
||||
|
||||
if (is_high) {
|
||||
SHA204_POUT_HIGH();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
SHA204_POUT_LOW();
|
||||
}
|
||||
}
|
||||
@@ -47,19 +47,14 @@ static uint8_t swi_send_bytes(uint8_t count, uint8_t *buffer)
|
||||
// Wait turn around time.
|
||||
delayMicroseconds(RX_TX_DELAY); //RX_TX_DELAY;
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
for (bit_mask = 1; bit_mask > 0; bit_mask <<= 1)
|
||||
{
|
||||
if (bit_mask & buffer[i])
|
||||
{
|
||||
for (i = 0; i < count; i++) {
|
||||
for (bit_mask = 1; bit_mask > 0; bit_mask <<= 1) {
|
||||
if (bit_mask & buffer[i]) {
|
||||
SHA204_POUT_LOW(); //*device_port_OUT &= ~device_pin;
|
||||
delayMicroseconds(BIT_DELAY); //BIT_DELAY_1;
|
||||
SHA204_POUT_HIGH(); //*device_port_OUT |= device_pin;
|
||||
delayMicroseconds(7*BIT_DELAY); //BIT_DELAY_7;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
// Send a zero bit.
|
||||
SHA204_POUT_LOW(); //*device_port_OUT &= ~device_pin;
|
||||
delayMicroseconds(BIT_DELAY); //BIT_DELAY_1;
|
||||
@@ -96,10 +91,8 @@ static uint8_t swi_receive_bytes(uint8_t count, uint8_t *buffer)
|
||||
SHA204_SET_INPUT();
|
||||
|
||||
// Receive bits and store in buffer.
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
for (bit_mask = 1; bit_mask > 0; bit_mask <<= 1)
|
||||
{
|
||||
for (i = 0; i < count; i++) {
|
||||
for (bit_mask = 1; bit_mask > 0; bit_mask <<= 1) {
|
||||
pulse_count = 0;
|
||||
|
||||
// Make sure that the variable below is big enough.
|
||||
@@ -108,33 +101,28 @@ static uint8_t swi_receive_bytes(uint8_t count, uint8_t *buffer)
|
||||
timeout_count = START_PULSE_TIME_OUT;
|
||||
|
||||
// Detect start bit.
|
||||
while (--timeout_count > 0)
|
||||
{
|
||||
while (--timeout_count > 0) {
|
||||
// Wait for falling edge.
|
||||
if (SHA204_PIN_READ() == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (timeout_count == 0)
|
||||
{
|
||||
if (timeout_count == 0) {
|
||||
status = SWI_FUNCTION_RETCODE_TIMEOUT;
|
||||
break;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
do {
|
||||
// Wait for rising edge.
|
||||
if (SHA204_PIN_READ() != 0)
|
||||
{
|
||||
if (SHA204_PIN_READ() != 0) {
|
||||
// For an Atmel microcontroller this might be faster than "pulse_count++".
|
||||
pulse_count = 1;
|
||||
break;
|
||||
}
|
||||
} while (--timeout_count > 0);
|
||||
|
||||
if (pulse_count == 0)
|
||||
{
|
||||
if (pulse_count == 0) {
|
||||
status = SWI_FUNCTION_RETCODE_TIMEOUT;
|
||||
break;
|
||||
}
|
||||
@@ -146,10 +134,8 @@ static uint8_t swi_receive_bytes(uint8_t count, uint8_t *buffer)
|
||||
timeout_count = ZERO_PULSE_TIME_OUT;
|
||||
|
||||
// Detect possible edge indicating zero bit.
|
||||
do
|
||||
{
|
||||
if (SHA204_PIN_READ() == 0)
|
||||
{
|
||||
do {
|
||||
if (SHA204_PIN_READ() == 0) {
|
||||
// For an Atmel microcontroller this might be faster than "pulse_count++".
|
||||
pulse_count = 2;
|
||||
break;
|
||||
@@ -158,10 +144,8 @@ static uint8_t swi_receive_bytes(uint8_t count, uint8_t *buffer)
|
||||
|
||||
// Wait for rising edge of zero pulse before returning. Otherwise we might interpret
|
||||
// its rising edge as the next start pulse.
|
||||
if (pulse_count == 2)
|
||||
{
|
||||
do
|
||||
{
|
||||
if (pulse_count == 2) {
|
||||
do {
|
||||
if (SHA204_PIN_READ() != 0) {
|
||||
break;
|
||||
}
|
||||
@@ -169,9 +153,10 @@ static uint8_t swi_receive_bytes(uint8_t count, uint8_t *buffer)
|
||||
}
|
||||
|
||||
// Update byte at current buffer index.
|
||||
else
|
||||
else {
|
||||
buffer[i] |= bit_mask; // received "one" bit
|
||||
}
|
||||
}
|
||||
|
||||
if (status != SWI_FUNCTION_RETCODE_SUCCESS) {
|
||||
break;
|
||||
@@ -179,8 +164,7 @@ static uint8_t swi_receive_bytes(uint8_t count, uint8_t *buffer)
|
||||
}
|
||||
interrupts(); //swi_enable_interrupts();
|
||||
|
||||
if (status == SWI_FUNCTION_RETCODE_TIMEOUT)
|
||||
{
|
||||
if (status == SWI_FUNCTION_RETCODE_TIMEOUT) {
|
||||
if (i > 0) {
|
||||
// Indicate that we timed out after having received at least one byte.
|
||||
status = SWI_FUNCTION_RETCODE_RX_FAIL;
|
||||
@@ -204,8 +188,7 @@ static uint8_t sha204p_receive_response(uint8_t size, uint8_t *response)
|
||||
(void) swi_send_byte(SHA204_SWI_FLAG_TX);
|
||||
|
||||
ret_code = swi_receive_bytes(size, response);
|
||||
if (ret_code == SWI_FUNCTION_RETCODE_SUCCESS || ret_code == SWI_FUNCTION_RETCODE_RX_FAIL)
|
||||
{
|
||||
if (ret_code == SWI_FUNCTION_RETCODE_SUCCESS || ret_code == SWI_FUNCTION_RETCODE_RX_FAIL) {
|
||||
count_byte = response[SHA204_BUFFER_POS_COUNT];
|
||||
if ((count_byte < SHA204_RSP_SIZE_MIN) || (count_byte > size)) {
|
||||
return SHA204_INVALID_SIZE;
|
||||
@@ -219,8 +202,7 @@ static uint8_t sha204p_receive_response(uint8_t size, uint8_t *response)
|
||||
// device being busy executing a command.
|
||||
if (ret_code == SWI_FUNCTION_RETCODE_TIMEOUT) {
|
||||
return SHA204_RX_NO_RESPONSE;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return SHA204_RX_FAIL;
|
||||
}
|
||||
}
|
||||
@@ -249,7 +231,8 @@ static uint8_t sha204c_resync(uint8_t size, uint8_t *response)
|
||||
return (ret_code == SHA204_SUCCESS ? SHA204_RESYNC_WITH_WAKEUP : ret_code);
|
||||
}
|
||||
|
||||
static uint8_t sha204c_send_and_receive(uint8_t *tx_buffer, uint8_t rx_size, uint8_t *rx_buffer, uint8_t execution_delay, uint8_t execution_timeout)
|
||||
static uint8_t sha204c_send_and_receive(uint8_t *tx_buffer, uint8_t rx_size, uint8_t *rx_buffer,
|
||||
uint8_t execution_delay, uint8_t execution_timeout)
|
||||
{
|
||||
uint8_t ret_code = SHA204_FUNC_FAIL;
|
||||
uint8_t ret_code_resync;
|
||||
@@ -268,23 +251,19 @@ static uint8_t sha204c_send_and_receive(uint8_t *tx_buffer, uint8_t rx_size, uin
|
||||
// Retry loop for sending a command and receiving a response.
|
||||
n_retries_send = SHA204_RETRY_COUNT + 1;
|
||||
|
||||
while ((n_retries_send-- > 0) && (ret_code != SHA204_SUCCESS))
|
||||
{
|
||||
while ((n_retries_send-- > 0) && (ret_code != SHA204_SUCCESS)) {
|
||||
// Send command.
|
||||
ret_code = swi_send_byte(SHA204_SWI_FLAG_CMD);
|
||||
if (ret_code != SWI_FUNCTION_RETCODE_SUCCESS) {
|
||||
ret_code = SHA204_COMM_FAIL;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
ret_code = swi_send_bytes(count, tx_buffer);
|
||||
}
|
||||
|
||||
if (ret_code != SHA204_SUCCESS)
|
||||
{
|
||||
if (ret_code != SHA204_SUCCESS) {
|
||||
if (sha204c_resync(rx_size, rx_buffer) == SHA204_RX_NO_RESPONSE) {
|
||||
return ret_code; // The device seems to be dead in the water.
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -294,8 +273,7 @@ static uint8_t sha204c_send_and_receive(uint8_t *tx_buffer, uint8_t rx_size, uin
|
||||
|
||||
// Retry loop for receiving a response.
|
||||
n_retries_receive = SHA204_RETRY_COUNT + 1;
|
||||
while (n_retries_receive-- > 0)
|
||||
{
|
||||
while (n_retries_receive-- > 0) {
|
||||
// Reset response buffer.
|
||||
for (i = 0; i < rx_size; i++) {
|
||||
rx_buffer[i] = 0;
|
||||
@@ -303,28 +281,23 @@ static uint8_t sha204c_send_and_receive(uint8_t *tx_buffer, uint8_t rx_size, uin
|
||||
|
||||
// Poll for response.
|
||||
timeout_countdown = execution_timeout_us;
|
||||
do
|
||||
{
|
||||
do {
|
||||
ret_code = sha204p_receive_response(rx_size, rx_buffer);
|
||||
timeout_countdown -= SHA204_RESPONSE_TIMEOUT;
|
||||
}
|
||||
while ((timeout_countdown > SHA204_RESPONSE_TIMEOUT) && (ret_code == SHA204_RX_NO_RESPONSE));
|
||||
} while ((timeout_countdown > SHA204_RESPONSE_TIMEOUT) && (ret_code == SHA204_RX_NO_RESPONSE));
|
||||
|
||||
if (ret_code == SHA204_RX_NO_RESPONSE)
|
||||
{
|
||||
if (ret_code == SHA204_RX_NO_RESPONSE) {
|
||||
// We did not receive a response. Re-synchronize and send command again.
|
||||
if (sha204c_resync(rx_size, rx_buffer) == SHA204_RX_NO_RESPONSE) {
|
||||
// The device seems to be dead in the water.
|
||||
return ret_code;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Check whether we received a valid response.
|
||||
if (ret_code == SHA204_INVALID_SIZE)
|
||||
{
|
||||
if (ret_code == SHA204_INVALID_SIZE) {
|
||||
// We see 0xFF for the count when communication got out of sync.
|
||||
ret_code_resync = sha204c_resync(rx_size, rx_buffer);
|
||||
if (ret_code_resync == SHA204_SUCCESS) {
|
||||
@@ -335,8 +308,7 @@ static uint8_t sha204c_send_and_receive(uint8_t *tx_buffer, uint8_t rx_size, uin
|
||||
// We could re-synchronize, but only after waking up the device.
|
||||
// Re-send command.
|
||||
break;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// We failed to re-synchronize.
|
||||
return ret_code;
|
||||
}
|
||||
@@ -345,8 +317,7 @@ static uint8_t sha204c_send_and_receive(uint8_t *tx_buffer, uint8_t rx_size, uin
|
||||
// We received a response of valid size.
|
||||
// Check the consistency of the response.
|
||||
ret_code = sha204c_check_crc(rx_buffer);
|
||||
if (ret_code == SHA204_SUCCESS)
|
||||
{
|
||||
if (ret_code == SHA204_SUCCESS) {
|
||||
// Received valid response.
|
||||
if (rx_buffer[SHA204_BUFFER_POS_COUNT] > SHA204_RSP_SIZE_MIN) {
|
||||
// Received non-status response. We are done.
|
||||
@@ -364,8 +335,7 @@ static uint8_t sha204c_send_and_receive(uint8_t *tx_buffer, uint8_t rx_size, uin
|
||||
if (status_byte == SHA204_STATUS_BYTE_EXEC) {
|
||||
return SHA204_CMD_FAIL;
|
||||
}
|
||||
if (status_byte == SHA204_STATUS_BYTE_COMM)
|
||||
{
|
||||
if (status_byte == SHA204_STATUS_BYTE_COMM) {
|
||||
// In case of the device status byte indicating a communication
|
||||
// error this function exits the retry loop for receiving a response
|
||||
// and enters the overall retry loop
|
||||
@@ -379,8 +349,7 @@ static uint8_t sha204c_send_and_receive(uint8_t *tx_buffer, uint8_t rx_size, uin
|
||||
return ret_code;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
else {
|
||||
// Received response with incorrect CRC.
|
||||
ret_code_resync = sha204c_resync(rx_size, rx_buffer);
|
||||
if (ret_code_resync == SHA204_SUCCESS) {
|
||||
@@ -391,8 +360,7 @@ static uint8_t sha204c_send_and_receive(uint8_t *tx_buffer, uint8_t rx_size, uin
|
||||
// We could re-synchronize, but only after waking up the device.
|
||||
// Re-send command.
|
||||
break;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// We failed to re-synchronize.
|
||||
return ret_code;
|
||||
}
|
||||
@@ -422,7 +390,8 @@ static uint8_t sha204m_read(uint8_t *tx_buffer, uint8_t *rx_buffer, uint8_t zone
|
||||
|
||||
rx_size = (zone & SHA204_ZONE_COUNT_FLAG) ? READ_32_RSP_SIZE : READ_4_RSP_SIZE;
|
||||
|
||||
return sha204c_send_and_receive(&tx_buffer[0], rx_size, &rx_buffer[0], READ_DELAY, READ_EXEC_MAX - READ_DELAY);
|
||||
return sha204c_send_and_receive(&tx_buffer[0], rx_size, &rx_buffer[0], READ_DELAY,
|
||||
READ_EXEC_MAX - READ_DELAY);
|
||||
}
|
||||
|
||||
/* CRC Calculator and Checker */
|
||||
@@ -435,10 +404,8 @@ static void sha204c_calculate_crc(uint8_t length, uint8_t *data, uint8_t *crc)
|
||||
uint8_t shift_register;
|
||||
uint8_t data_bit, crc_bit;
|
||||
|
||||
for (counter = 0; counter < length; counter++)
|
||||
{
|
||||
for (shift_register = 0x01; shift_register > 0x00; shift_register <<= 1)
|
||||
{
|
||||
for (counter = 0; counter < length; counter++) {
|
||||
for (shift_register = 0x01; shift_register > 0x00; shift_register <<= 1) {
|
||||
data_bit = (data[counter] & shift_register) ? 1 : 0;
|
||||
crc_bit = crc_register >> 15;
|
||||
|
||||
@@ -510,12 +477,9 @@ uint8_t atsha204_wakeup(uint8_t *response)
|
||||
// Verify status response.
|
||||
if (response[SHA204_BUFFER_POS_COUNT] != SHA204_RSP_SIZE_MIN) {
|
||||
ret_code = SHA204_INVALID_SIZE;
|
||||
}
|
||||
else if (response[SHA204_BUFFER_POS_STATUS] != SHA204_STATUS_BYTE_WAKEUP) {
|
||||
} else if (response[SHA204_BUFFER_POS_STATUS] != SHA204_STATUS_BYTE_WAKEUP) {
|
||||
ret_code = SHA204_COMM_FAIL;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
if ((response[SHA204_RSP_SIZE_MIN - SHA204_CRC_SIZE] != 0x33)
|
||||
|| (response[SHA204_RSP_SIZE_MIN + 1 - SHA204_CRC_SIZE] != 0x43)) {
|
||||
ret_code = SHA204_BAD_CRC;
|
||||
@@ -529,7 +493,8 @@ uint8_t atsha204_wakeup(uint8_t *response)
|
||||
}
|
||||
|
||||
uint8_t atsha204_execute(uint8_t op_code, uint8_t param1, uint16_t param2,
|
||||
uint8_t datalen1, uint8_t *data1, uint8_t tx_size, uint8_t *tx_buffer, uint8_t rx_size, uint8_t *rx_buffer)
|
||||
uint8_t datalen1, uint8_t *data1, uint8_t tx_size, uint8_t *tx_buffer, uint8_t rx_size,
|
||||
uint8_t *rx_buffer)
|
||||
{
|
||||
uint8_t poll_delay, poll_timeout, response_size;
|
||||
uint8_t *p_buffer;
|
||||
@@ -537,8 +502,7 @@ uint8_t atsha204_execute(uint8_t op_code, uint8_t param1, uint16_t param2,
|
||||
(void)tx_size;
|
||||
|
||||
// Supply delays and response size.
|
||||
switch (op_code)
|
||||
{
|
||||
switch (op_code) {
|
||||
case SHA204_GENDIG:
|
||||
poll_delay = GENDIG_DELAY;
|
||||
poll_timeout = GENDIG_EXEC_MAX - GENDIG_DELAY;
|
||||
@@ -611,8 +575,7 @@ uint8_t atsha204_getSerialNumber(uint8_t * response)
|
||||
|
||||
/* read from bytes 0->3 of config zone */
|
||||
uint8_t returnCode = sha204m_read(readCommand, readResponse, SHA204_ZONE_CONFIG, ADDRESS_SN03);
|
||||
if (!returnCode)
|
||||
{
|
||||
if (!returnCode) {
|
||||
for (int i=0; i<4; i++) {// store bytes 0-3 into respones array
|
||||
response[i] = readResponse[SHA204_BUFFER_POS_DATA+i];
|
||||
}
|
||||
@@ -624,8 +587,8 @@ uint8_t atsha204_getSerialNumber(uint8_t * response)
|
||||
response[i] = readResponse[SHA204_BUFFER_POS_DATA+(i-4)];
|
||||
}
|
||||
|
||||
if (!returnCode)
|
||||
{ /* Finally if last two reads were successful, read byte 8 of the SN */
|
||||
if (!returnCode) {
|
||||
/* Finally if last two reads were successful, read byte 8 of the SN */
|
||||
returnCode = sha204m_read(readCommand, readResponse, SHA204_ZONE_CONFIG, ADDRESS_SN8);
|
||||
response[8] = readResponse[SHA204_BUFFER_POS_DATA]; // Byte 8 of SN should always be 0xEE
|
||||
}
|
||||
|
||||
+26
-10
@@ -32,17 +32,20 @@ const uint8_t sha256InitState[] PROGMEM = {
|
||||
0x19,0xcd,0xe0,0x5b // H7
|
||||
};
|
||||
|
||||
void Sha256Class::init(void) {
|
||||
void Sha256Class::init(void)
|
||||
{
|
||||
memcpy_P(state.b,sha256InitState,32);
|
||||
byteCount = 0;
|
||||
bufferOffset = 0;
|
||||
}
|
||||
|
||||
uint32_t Sha256Class::ror32(uint32_t number, uint8_t bits) {
|
||||
uint32_t Sha256Class::ror32(uint32_t number, uint8_t bits)
|
||||
{
|
||||
return ((number << (32-bits)) | (number >> bits));
|
||||
}
|
||||
|
||||
void Sha256Class::hashBlock() {
|
||||
void Sha256Class::hashBlock()
|
||||
{
|
||||
uint8_t i;
|
||||
uint32_t a,b,c,d,e,f,g,h,t1,t2;
|
||||
|
||||
@@ -71,7 +74,14 @@ void Sha256Class::hashBlock() {
|
||||
t1 += buffer.w[i&15]; // Wi
|
||||
t2 = ror32(a,2) ^ ror32(a,13) ^ ror32(a,22); // ∑0(a)
|
||||
t2 += ((b & c) | (a & (b | c))); // Maj(a,b,c)
|
||||
h=g; g=f; f=e; e=d+t1; d=c; c=b; b=a; a=t1+t2;
|
||||
h=g;
|
||||
g=f;
|
||||
f=e;
|
||||
e=d+t1;
|
||||
d=c;
|
||||
c=b;
|
||||
b=a;
|
||||
a=t1+t2;
|
||||
}
|
||||
state.w[0] += a;
|
||||
state.w[1] += b;
|
||||
@@ -83,7 +93,8 @@ void Sha256Class::hashBlock() {
|
||||
state.w[7] += h;
|
||||
}
|
||||
|
||||
void Sha256Class::addUncounted(uint8_t data) {
|
||||
void Sha256Class::addUncounted(uint8_t data)
|
||||
{
|
||||
buffer.b[bufferOffset ^ 3] = data;
|
||||
bufferOffset++;
|
||||
if (bufferOffset == BUFFER_SIZE) {
|
||||
@@ -92,12 +103,14 @@ void Sha256Class::addUncounted(uint8_t data) {
|
||||
}
|
||||
}
|
||||
|
||||
void Sha256Class::write(uint8_t data) {
|
||||
void Sha256Class::write(uint8_t data)
|
||||
{
|
||||
++byteCount;
|
||||
addUncounted(data);
|
||||
}
|
||||
|
||||
void Sha256Class::pad() {
|
||||
void Sha256Class::pad()
|
||||
{
|
||||
// Implement SHA-256 padding (fips180-2 §5.1.1)
|
||||
|
||||
// Pad with 0x80 followed by 0x00 until the end of the block
|
||||
@@ -118,7 +131,8 @@ void Sha256Class::pad() {
|
||||
}
|
||||
|
||||
|
||||
uint8_t* Sha256Class::result(void) {
|
||||
uint8_t* Sha256Class::result(void)
|
||||
{
|
||||
// Pad to complete the last block
|
||||
pad();
|
||||
|
||||
@@ -143,7 +157,8 @@ uint8_t* Sha256Class::result(void) {
|
||||
uint8_t keyBuffer[BLOCK_LENGTH]; // K0 in FIPS-198a
|
||||
uint8_t innerHash[HASH_LENGTH];
|
||||
|
||||
void Sha256Class::initHmac(const uint8_t* key, int keyLength) {
|
||||
void Sha256Class::initHmac(const uint8_t* key, int keyLength)
|
||||
{
|
||||
uint8_t i;
|
||||
memset(keyBuffer,0,BLOCK_LENGTH);
|
||||
if (keyLength > BLOCK_LENGTH) {
|
||||
@@ -164,7 +179,8 @@ void Sha256Class::initHmac(const uint8_t* key, int keyLength) {
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t* Sha256Class::resultHmac(void) {
|
||||
uint8_t* Sha256Class::resultHmac(void)
|
||||
{
|
||||
uint8_t i;
|
||||
// Complete inner hash
|
||||
memcpy(innerHash,result(),HASH_LENGTH);
|
||||
|
||||
@@ -402,7 +402,8 @@ void badPinNumber(void)
|
||||
/** Check for valid pin number
|
||||
* @param[in] pin Number of pin to be checked.
|
||||
*/
|
||||
static ALWAYS_INLINE void badPinCheck(uint8_t pin) {
|
||||
static ALWAYS_INLINE void badPinCheck(uint8_t pin)
|
||||
{
|
||||
if (!__builtin_constant_p(pin) || pin >= digitalPinCount) {
|
||||
badPinNumber();
|
||||
}
|
||||
@@ -413,7 +414,8 @@ static ALWAYS_INLINE void badPinCheck(uint8_t pin) {
|
||||
* @param[in] bit bit number to write
|
||||
* @param[in] level value for bit
|
||||
*/
|
||||
static ALWAYS_INLINE void fastBitWriteSafe(volatile uint8_t* address, uint8_t bit, bool level) {
|
||||
static ALWAYS_INLINE void fastBitWriteSafe(volatile uint8_t* address, uint8_t bit, bool level)
|
||||
{
|
||||
uint8_t oldSREG;
|
||||
if (address > (uint8_t*)0X5F) {
|
||||
oldSREG = SREG;
|
||||
@@ -433,7 +435,8 @@ static ALWAYS_INLINE void fastBitWriteSafe(volatile uint8_t* address, uint8_t bi
|
||||
* @param[in] pin Arduino pin number
|
||||
* @return value read
|
||||
*/
|
||||
static ALWAYS_INLINE bool fastDigitalRead(uint8_t pin) {
|
||||
static ALWAYS_INLINE bool fastDigitalRead(uint8_t pin)
|
||||
{
|
||||
badPinCheck(pin);
|
||||
return (*pinMap[pin].pin >> pinMap[pin].bit) & 1;
|
||||
}
|
||||
@@ -444,7 +447,8 @@ static ALWAYS_INLINE bool fastDigitalRead(uint8_t pin) {
|
||||
* If the pin is in output mode toggle the pin level.
|
||||
* If the pin is in input mode toggle the state of the 20K pullup.
|
||||
*/
|
||||
static ALWAYS_INLINE void fastDigitalToggle(uint8_t pin) {
|
||||
static ALWAYS_INLINE void fastDigitalToggle(uint8_t pin)
|
||||
{
|
||||
badPinCheck(pin);
|
||||
if (pinMap[pin].pin > (uint8_t*)0X5F) {
|
||||
// must write bit to high address port
|
||||
@@ -459,7 +463,8 @@ static ALWAYS_INLINE void fastDigitalToggle(uint8_t pin) {
|
||||
* @param[in] pin Arduino pin number
|
||||
* @param[in] level value to write
|
||||
*/
|
||||
static ALWAYS_INLINE void fastDigitalWrite(uint8_t pin, bool level) {
|
||||
static ALWAYS_INLINE void fastDigitalWrite(uint8_t pin, bool level)
|
||||
{
|
||||
badPinCheck(pin);
|
||||
fastBitWriteSafe(pinMap[pin].port, pinMap[pin].bit, level);
|
||||
}
|
||||
@@ -470,7 +475,8 @@ static ALWAYS_INLINE void fastDigitalWrite(uint8_t pin, bool level) {
|
||||
*
|
||||
* fastPinMode does not enable or disable the 20K pullup for input mode.
|
||||
*/
|
||||
static ALWAYS_INLINE void fastPinMode(uint8_t pin, bool mode) {
|
||||
static ALWAYS_INLINE void fastPinMode(uint8_t pin, bool mode)
|
||||
{
|
||||
badPinCheck(pin);
|
||||
fastBitWriteSafe(pinMap[pin].ddr, pinMap[pin].bit, mode);
|
||||
}
|
||||
@@ -481,7 +487,8 @@ static ALWAYS_INLINE void fastPinMode(uint8_t pin, bool mode) {
|
||||
* @param[in] level If mode is output, set level high/low.
|
||||
* If mode is input, enable or disable the pin's 20K pullup.
|
||||
*/
|
||||
static ALWAYS_INLINE void fastPinConfig(uint8_t pin, bool mode, bool level) {
|
||||
static ALWAYS_INLINE void fastPinConfig(uint8_t pin, bool mode, bool level)
|
||||
{
|
||||
fastPinMode(pin, mode);
|
||||
fastDigitalWrite(pin, level);
|
||||
}
|
||||
@@ -491,7 +498,8 @@ static ALWAYS_INLINE void fastPinConfig(uint8_t pin, bool mode, bool level) {
|
||||
* @brief Fast AVR digital port I/O
|
||||
*/
|
||||
template<uint8_t PinNumber>
|
||||
class DigitalPin {
|
||||
class DigitalPin
|
||||
{
|
||||
public:
|
||||
//----------------------------------------------------------------------------
|
||||
/** Constructor */
|
||||
@@ -500,7 +508,8 @@ class DigitalPin {
|
||||
/** Constructor
|
||||
* @param[in] pinMode if true set output mode else input mode.
|
||||
*/
|
||||
explicit DigitalPin(bool pinMode) {
|
||||
explicit DigitalPin(bool pinMode)
|
||||
{
|
||||
mode(pinMode);
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -509,7 +518,8 @@ class DigitalPin {
|
||||
* @param[in] level If mode is output, set level high/low.
|
||||
* If mode is input, enable or disable the pin's 20K pullup.
|
||||
*/
|
||||
DigitalPin(bool mode, bool level) {
|
||||
DigitalPin(bool mode, bool level)
|
||||
{
|
||||
config(mode, level);
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -519,7 +529,8 @@ class DigitalPin {
|
||||
*
|
||||
* @return This DigitalPin instance.
|
||||
*/
|
||||
inline DigitalPin & operator = (bool value) __attribute__((always_inline)) {
|
||||
inline DigitalPin & operator = (bool value) __attribute__((always_inline))
|
||||
{
|
||||
write(value);
|
||||
return *this;
|
||||
}
|
||||
@@ -527,7 +538,8 @@ class DigitalPin {
|
||||
/** Parenthesis operator
|
||||
* @return Pin's level
|
||||
*/
|
||||
inline operator bool () const __attribute__((always_inline)) {
|
||||
inline operator bool () const __attribute__((always_inline))
|
||||
{
|
||||
return read();
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -536,19 +548,26 @@ class DigitalPin {
|
||||
* @param[in] level If mode is output, set level high/low.
|
||||
* If mode is input, enable or disable the pin's 20K pullup.
|
||||
*/
|
||||
ALWAYS_INLINE void config(bool mode, bool level) {
|
||||
ALWAYS_INLINE void config(bool mode, bool level)
|
||||
{
|
||||
fastPinConfig(PinNumber, mode, level);
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
/**
|
||||
* Set pin level high if output mode or enable 20K pullup if input mode.
|
||||
*/
|
||||
ALWAYS_INLINE void high() {write(true);}
|
||||
ALWAYS_INLINE void high()
|
||||
{
|
||||
write(true);
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
/**
|
||||
* Set pin level low if output mode or disable 20K pullup if input mode.
|
||||
*/
|
||||
ALWAYS_INLINE void low() {write(false);}
|
||||
ALWAYS_INLINE void low()
|
||||
{
|
||||
write(false);
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
/**
|
||||
* Set pin mode
|
||||
@@ -556,12 +575,14 @@ class DigitalPin {
|
||||
*
|
||||
* mode() does not enable or disable the 20K pullup for input mode.
|
||||
*/
|
||||
ALWAYS_INLINE void mode(bool pinMode) {
|
||||
ALWAYS_INLINE void mode(bool pinMode)
|
||||
{
|
||||
fastPinMode(PinNumber, pinMode);
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
/** @return Pin's level */
|
||||
ALWAYS_INLINE bool read() const {
|
||||
ALWAYS_INLINE bool read() const
|
||||
{
|
||||
return fastDigitalRead(PinNumber);
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -570,7 +591,8 @@ class DigitalPin {
|
||||
* If the pin is in output mode toggle the pin's level.
|
||||
* If the pin is in input mode toggle the state of the 20K pullup.
|
||||
*/
|
||||
ALWAYS_INLINE void toggle() {
|
||||
ALWAYS_INLINE void toggle()
|
||||
{
|
||||
fastDigitalToggle(PinNumber);
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -578,7 +600,8 @@ class DigitalPin {
|
||||
* @param[in] value If true set the pin's level high else set the
|
||||
* pin's level low.
|
||||
*/
|
||||
ALWAYS_INLINE void write(bool value) {
|
||||
ALWAYS_INLINE void write(bool value)
|
||||
{
|
||||
fastDigitalWrite(PinNumber, value);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -32,7 +32,8 @@
|
||||
/** Constructor
|
||||
* @param[in] pin Pin assigned to this object.
|
||||
*/
|
||||
PinIO::PinIO(uint8_t pin) {
|
||||
PinIO::PinIO(uint8_t pin)
|
||||
{
|
||||
begin(pin);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -40,8 +41,11 @@ PinIO::PinIO(uint8_t pin) {
|
||||
* @param[in] pin Arduino board pin number.
|
||||
* @return true for success or false if invalid pin number.
|
||||
*/
|
||||
bool PinIO::begin(uint8_t pin) {
|
||||
if (pin >= NUM_DIGITAL_PINS) return false;
|
||||
bool PinIO::begin(uint8_t pin)
|
||||
{
|
||||
if (pin >= NUM_DIGITAL_PINS) {
|
||||
return false;
|
||||
}
|
||||
uint8_t port = digitalPinToPort(pin);
|
||||
pinReg_ = portInputRegister(port);
|
||||
bit_ = digitalPinToBitMask(pin);
|
||||
@@ -59,7 +63,8 @@ bool PinIO::begin(uint8_t pin) {
|
||||
* This function may be used with interrupts enabled or disabled.
|
||||
* The previous interrupt state will be restored.
|
||||
*/
|
||||
void PinIO::config(bool mode, bool data) {
|
||||
void PinIO::config(bool mode, bool data)
|
||||
{
|
||||
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
|
||||
modeI(mode);
|
||||
writeI(data);
|
||||
|
||||
@@ -37,7 +37,8 @@
|
||||
* @class PinIO
|
||||
* @brief AVR port I/O with runtime pin numbers.
|
||||
*/
|
||||
class PinIO {
|
||||
class PinIO
|
||||
{
|
||||
public:
|
||||
/** Create a PinIO object with no assigned pin. */
|
||||
PinIO() : bit_(0), mask_(0XFF) {}
|
||||
@@ -62,14 +63,20 @@ class PinIO {
|
||||
void config(bool mode, bool data);
|
||||
//----------------------------------------------------------------------------
|
||||
/** @return Pin's level */
|
||||
ALWAYS_INLINE bool read() {return *pinReg_ & bit_;}
|
||||
ALWAYS_INLINE bool read()
|
||||
{
|
||||
return *pinReg_ & bit_;
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
/** toggle a pin
|
||||
*
|
||||
* If the pin is in output mode toggle the pin's level.
|
||||
* If the pin is in input mode toggle the state of the 20K pullup.
|
||||
*/
|
||||
ALWAYS_INLINE void toggle() {*pinReg_ = bit_;}
|
||||
ALWAYS_INLINE void toggle()
|
||||
{
|
||||
*pinReg_ = bit_;
|
||||
}
|
||||
//============================================================================
|
||||
/**
|
||||
* Set pin high if output mode or enable 20K pullup if input mode.
|
||||
@@ -77,14 +84,20 @@ class PinIO {
|
||||
* This function must be called with interrupts disabled.
|
||||
* This function will not change the interrupt state.
|
||||
*/
|
||||
ALWAYS_INLINE void highI() {writeI(1);}
|
||||
ALWAYS_INLINE void highI()
|
||||
{
|
||||
writeI(1);
|
||||
}
|
||||
/**
|
||||
* Set pin low if output mode or disable 20K pullup if input mode.
|
||||
*
|
||||
* This function must be called with interrupts disabled.
|
||||
* This function will not change the interrupt state.
|
||||
*/
|
||||
ALWAYS_INLINE void lowI() {writeI(0);}
|
||||
ALWAYS_INLINE void lowI()
|
||||
{
|
||||
writeI(0);
|
||||
}
|
||||
/**
|
||||
* Set pin mode
|
||||
* @param[in] mode if true set output mode else input mode.
|
||||
@@ -94,7 +107,8 @@ class PinIO {
|
||||
* This function must be called with interrupts disabled.
|
||||
* This function will not change the interrupt state.
|
||||
*/
|
||||
ALWAYS_INLINE void modeI(bool mode) {
|
||||
ALWAYS_INLINE void modeI(bool mode)
|
||||
{
|
||||
volatile uint8_t* ddrReg = pinReg_ + 1;
|
||||
*ddrReg = mode ? *ddrReg | bit_ : *ddrReg & mask_;
|
||||
}
|
||||
@@ -106,7 +120,8 @@ class PinIO {
|
||||
* This function must be called with interrupts disabled.
|
||||
* This function will not change the interrupt state.
|
||||
*/
|
||||
ALWAYS_INLINE void writeI(bool level) {
|
||||
ALWAYS_INLINE void writeI(bool level)
|
||||
{
|
||||
*portReg_ = level ? *portReg_ | bit_ : *portReg_ & mask_;
|
||||
}
|
||||
//============================================================================
|
||||
@@ -116,14 +131,24 @@ class PinIO {
|
||||
* This function will enable interrupts. This function should not be
|
||||
* called in an ISR or where interrupts are disabled.
|
||||
*/
|
||||
ALWAYS_INLINE void high() {ATOMIC_BLOCK(ATOMIC_FORCEON) {highI();}}
|
||||
ALWAYS_INLINE void high()
|
||||
{
|
||||
ATOMIC_BLOCK(ATOMIC_FORCEON) {
|
||||
highI();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Set pin level low if output mode or disable 20K pullup if input mode.
|
||||
*
|
||||
* This function will enable interrupts. This function should not be
|
||||
* called in an ISR or where interrupts are disabled.
|
||||
*/
|
||||
ALWAYS_INLINE void low() {ATOMIC_BLOCK(ATOMIC_FORCEON) {lowI();}}
|
||||
ALWAYS_INLINE void low()
|
||||
{
|
||||
ATOMIC_BLOCK(ATOMIC_FORCEON) {
|
||||
lowI();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Set pin mode
|
||||
* @param[in] pinMode if true set output mode else input mode.
|
||||
@@ -133,7 +158,12 @@ class PinIO {
|
||||
* This function will enable interrupts. This function should not be
|
||||
* called in an ISR or where interrupts are disabled.
|
||||
*/
|
||||
ALWAYS_INLINE void mode(bool pinMode) {ATOMIC_BLOCK(ATOMIC_FORCEON) {modeI(pinMode);}}
|
||||
ALWAYS_INLINE void mode(bool pinMode)
|
||||
{
|
||||
ATOMIC_BLOCK(ATOMIC_FORCEON) {
|
||||
modeI(pinMode);
|
||||
}
|
||||
}
|
||||
/** Write pin.
|
||||
*
|
||||
* @param[in] level If output mode set pin high if true else low.
|
||||
@@ -142,7 +172,12 @@ class PinIO {
|
||||
* This function will enable interrupts. This function should not be
|
||||
* called in an ISR or where interrupts are disabled.
|
||||
*/
|
||||
ALWAYS_INLINE void write(bool level) {ATOMIC_BLOCK(ATOMIC_FORCEON) {writeI(level);}}
|
||||
ALWAYS_INLINE void write(bool level)
|
||||
{
|
||||
ATOMIC_BLOCK(ATOMIC_FORCEON) {
|
||||
writeI(level);
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
private:
|
||||
uint8_t bit_;
|
||||
|
||||
@@ -49,7 +49,8 @@
|
||||
* @return true for success else false.
|
||||
*/
|
||||
bool I2cMasterBase::transfer(uint8_t addrRW,
|
||||
void *buf, size_t nbytes, uint8_t option) {
|
||||
void *buf, size_t nbytes, uint8_t option)
|
||||
{
|
||||
if (_state != STATE_REP_START) {
|
||||
start();
|
||||
}
|
||||
@@ -76,7 +77,8 @@ bool I2cMasterBase::transfer(uint8_t addrRW,
|
||||
* .
|
||||
* @return true for success else false.
|
||||
*/
|
||||
bool I2cMasterBase::transferContinue(void *buf, size_t nbytes, uint8_t option) {
|
||||
bool I2cMasterBase::transferContinue(void *buf, size_t nbytes, uint8_t option)
|
||||
{
|
||||
uint8_t* p = reinterpret_cast<uint8_t*>(buf);
|
||||
if (_state == STATE_RX_DATA) {
|
||||
for (size_t i = 0; i < nbytes; i++) {
|
||||
@@ -111,7 +113,8 @@ bool I2cMasterBase::transferContinue(void *buf, size_t nbytes, uint8_t option) {
|
||||
*
|
||||
* @param[in] sclPin The software SCL pin number.
|
||||
*/
|
||||
SoftI2cMaster::SoftI2cMaster(uint8_t sclPin, uint8_t sdaPin) {
|
||||
SoftI2cMaster::SoftI2cMaster(uint8_t sclPin, uint8_t sdaPin)
|
||||
{
|
||||
begin(sclPin, sdaPin);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -122,7 +125,8 @@ SoftI2cMaster::SoftI2cMaster(uint8_t sclPin, uint8_t sdaPin) {
|
||||
*
|
||||
* @param[in] sclPin The software SCL pin number.
|
||||
*/
|
||||
void SoftI2cMaster::begin(uint8_t sclPin, uint8_t sdaPin) {
|
||||
void SoftI2cMaster::begin(uint8_t sclPin, uint8_t sdaPin)
|
||||
{
|
||||
uint8_t port;
|
||||
|
||||
// Get bit mask and address of scl registers.
|
||||
@@ -156,7 +160,8 @@ void SoftI2cMaster::begin(uint8_t sclPin, uint8_t sdaPin) {
|
||||
*
|
||||
* @return The byte read from the I2C bus.
|
||||
*/
|
||||
uint8_t SoftI2cMaster::read(uint8_t last) {
|
||||
uint8_t SoftI2cMaster::read(uint8_t last)
|
||||
{
|
||||
uint8_t b = 0;
|
||||
|
||||
// Set sda to high Z mode for read.
|
||||
@@ -168,7 +173,9 @@ uint8_t SoftI2cMaster::read(uint8_t last) {
|
||||
sclDelay(16);
|
||||
writeScl(HIGH);
|
||||
sclDelay(12);
|
||||
if (readSda()) b |= 1;
|
||||
if (readSda()) {
|
||||
b |= 1;
|
||||
}
|
||||
writeScl(LOW);
|
||||
}
|
||||
// send ACK or NACK
|
||||
@@ -182,7 +189,8 @@ uint8_t SoftI2cMaster::read(uint8_t last) {
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
/* Issue a start condition. */
|
||||
void SoftI2cMaster::start() {
|
||||
void SoftI2cMaster::start()
|
||||
{
|
||||
if (!readSda()) {
|
||||
writeSda(HIGH);
|
||||
writeScl(HIGH);
|
||||
@@ -194,7 +202,8 @@ void SoftI2cMaster::start() {
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
/* Issue a stop condition. */
|
||||
void SoftI2cMaster::stop(void) {
|
||||
void SoftI2cMaster::stop(void)
|
||||
{
|
||||
writeSda(LOW);
|
||||
sclDelay(20);
|
||||
writeScl(HIGH);
|
||||
@@ -210,7 +219,8 @@ void SoftI2cMaster::stop(void) {
|
||||
*
|
||||
* @return The value true, 1, if the slave returned an ACK or false for NACK.
|
||||
*/
|
||||
bool SoftI2cMaster::write(uint8_t data) {
|
||||
bool SoftI2cMaster::write(uint8_t data)
|
||||
{
|
||||
// write byte
|
||||
for (uint8_t m = 0X80; m != 0; m >>= 1) {
|
||||
// don't change this loop unless you verify the change with a scope
|
||||
|
||||
@@ -63,7 +63,8 @@ const uint8_t STATE_TX_DATA_NACK = 6;
|
||||
* @class I2cMasterBase
|
||||
* @brief Base class for FastI2cMaster, SoftI2cMaster
|
||||
*/
|
||||
class I2cMasterBase {
|
||||
class I2cMasterBase
|
||||
{
|
||||
public:
|
||||
I2cMasterBase() : _state(STATE_STOP) {}
|
||||
/** Read a byte
|
||||
@@ -148,7 +149,8 @@ class I2cMasterBase {
|
||||
* @class SoftI2cMaster
|
||||
* @brief Software I2C master class
|
||||
*/
|
||||
class SoftI2cMaster : public I2cMasterBase {
|
||||
class SoftI2cMaster : public I2cMasterBase
|
||||
{
|
||||
public:
|
||||
SoftI2cMaster() {}
|
||||
/**
|
||||
@@ -179,11 +181,18 @@ class SoftI2cMaster : public I2cMasterBase {
|
||||
volatile uint8_t* _sdaDDR;
|
||||
volatile uint8_t* _sdaInReg;
|
||||
//----------------------------------------------------------------------------
|
||||
bool readSda() {return *_sdaInReg & _sdaBit;}
|
||||
bool readSda()
|
||||
{
|
||||
return *_sdaInReg & _sdaBit;
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
void sclDelay(uint8_t n) {_delay_loop_1(n);}
|
||||
void sclDelay(uint8_t n)
|
||||
{
|
||||
_delay_loop_1(n);
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
void writeScl(bool value) {
|
||||
void writeScl(bool value)
|
||||
{
|
||||
uint8_t s = SREG;
|
||||
noInterrupts();
|
||||
if (value == LOW) {
|
||||
@@ -196,7 +205,8 @@ class SoftI2cMaster : public I2cMasterBase {
|
||||
SREG = s;
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
void writeSda(bool value) {
|
||||
void writeSda(bool value)
|
||||
{
|
||||
uint8_t s = SREG;
|
||||
noInterrupts();
|
||||
if (value == LOW) {
|
||||
@@ -217,15 +227,18 @@ class SoftI2cMaster : public I2cMasterBase {
|
||||
* @brief Fast software I2C master class.
|
||||
*/
|
||||
template<uint8_t sclPin, uint8_t sdaPin>
|
||||
class FastI2cMaster : public I2cMasterBase {
|
||||
class FastI2cMaster : public I2cMasterBase
|
||||
{
|
||||
public:
|
||||
//----------------------------------------------------------------------------
|
||||
FastI2cMaster() {
|
||||
FastI2cMaster()
|
||||
{
|
||||
begin();
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
/** Initialize I2C bus pins. */
|
||||
void begin() {
|
||||
void begin()
|
||||
{
|
||||
fastDigitalWrite(sclPin, LOW);
|
||||
fastDigitalWrite(sdaPin, LOW);
|
||||
|
||||
@@ -233,7 +246,8 @@ class FastI2cMaster : public I2cMasterBase {
|
||||
sdaWrite(HIGH);
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
uint8_t read(uint8_t last) {
|
||||
uint8_t read(uint8_t last)
|
||||
{
|
||||
uint8_t data = 0;
|
||||
sdaWrite(HIGH);
|
||||
|
||||
@@ -256,7 +270,8 @@ class FastI2cMaster : public I2cMasterBase {
|
||||
return data;
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
void start() {
|
||||
void start()
|
||||
{
|
||||
if (!fastDigitalRead(sdaPin)) {
|
||||
// It's a repeat start.
|
||||
sdaWrite(HIGH);
|
||||
@@ -270,7 +285,8 @@ class FastI2cMaster : public I2cMasterBase {
|
||||
sclDelay(8);
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
void stop(void) {
|
||||
void stop(void)
|
||||
{
|
||||
sdaWrite(LOW);
|
||||
sclDelay(8);
|
||||
sclWrite(HIGH);
|
||||
@@ -279,7 +295,8 @@ class FastI2cMaster : public I2cMasterBase {
|
||||
sclDelay(8);
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
bool write(uint8_t data) {
|
||||
bool write(uint8_t data)
|
||||
{
|
||||
// write byte
|
||||
writeBit(7, data);
|
||||
writeBit(6, data);
|
||||
@@ -304,24 +321,39 @@ class FastI2cMaster : public I2cMasterBase {
|
||||
private:
|
||||
//----------------------------------------------------------------------------
|
||||
inline __attribute__((always_inline))
|
||||
void sclWrite(bool value) {fastPinMode(sclPin, !value);}
|
||||
//----------------------------------------------------------------------------
|
||||
inline __attribute__((always_inline))
|
||||
void sdaWrite(bool value) {fastPinMode(sdaPin, !value);}
|
||||
//----------------------------------------------------------------------------
|
||||
inline __attribute__((always_inline))
|
||||
void readBit(uint8_t bit, uint8_t* data) {
|
||||
sclWrite(HIGH);
|
||||
sclDelay(5);
|
||||
if (fastDigitalRead(sdaPin)) *data |= 1 << bit;
|
||||
sclWrite(LOW);
|
||||
if (bit) sclDelay(6);
|
||||
void sclWrite(bool value)
|
||||
{
|
||||
fastPinMode(sclPin, !value);
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
void sclDelay(uint8_t n) {_delay_loop_1(n);}
|
||||
inline __attribute__((always_inline))
|
||||
void sdaWrite(bool value)
|
||||
{
|
||||
fastPinMode(sdaPin, !value);
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
inline __attribute__((always_inline))
|
||||
void writeBit(uint8_t bit, uint8_t data) {
|
||||
void readBit(uint8_t bit, uint8_t* data)
|
||||
{
|
||||
sclWrite(HIGH);
|
||||
sclDelay(5);
|
||||
if (fastDigitalRead(sdaPin)) {
|
||||
*data |= 1 << bit;
|
||||
}
|
||||
sclWrite(LOW);
|
||||
if (bit) {
|
||||
sclDelay(6);
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
void sclDelay(uint8_t n)
|
||||
{
|
||||
_delay_loop_1(n);
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
inline __attribute__((always_inline))
|
||||
void writeBit(uint8_t bit, uint8_t data)
|
||||
{
|
||||
uint8_t mask = 1 << bit;
|
||||
sdaWrite(data & mask);
|
||||
sclWrite(HIGH);
|
||||
|
||||
@@ -48,11 +48,13 @@ const bool SCK_MODE = true;
|
||||
* @brief Fast software SPI.
|
||||
*/
|
||||
template<uint8_t MisoPin, uint8_t MosiPin, uint8_t SckPin, uint8_t Mode = 0>
|
||||
class SoftSPI {
|
||||
class SoftSPI
|
||||
{
|
||||
public:
|
||||
//----------------------------------------------------------------------------
|
||||
/** Initialize SoftSPI pins. */
|
||||
void begin() {
|
||||
void begin()
|
||||
{
|
||||
fastPinConfig(MisoPin, MISO_MODE, MISO_LEVEL);
|
||||
fastPinConfig(MosiPin, MOSI_MODE, !MODE_CPHA(Mode));
|
||||
fastPinConfig(SckPin, SCK_MODE, MODE_CPOL(Mode));
|
||||
@@ -61,7 +63,8 @@ class SoftSPI {
|
||||
/** Soft SPI receive byte.
|
||||
* @return Data byte received.
|
||||
*/
|
||||
ALWAYS_INLINE uint8_t receive() {
|
||||
ALWAYS_INLINE uint8_t receive()
|
||||
{
|
||||
uint8_t data = 0;
|
||||
receiveBit(7, &data);
|
||||
receiveBit(6, &data);
|
||||
@@ -77,7 +80,8 @@ class SoftSPI {
|
||||
/** Soft SPI send byte.
|
||||
* @param[in] data Data byte to send.
|
||||
*/
|
||||
ALWAYS_INLINE void send(uint8_t data) {
|
||||
ALWAYS_INLINE void send(uint8_t data)
|
||||
{
|
||||
sendBit(7, data);
|
||||
sendBit(6, data);
|
||||
sendBit(5, data);
|
||||
@@ -92,7 +96,8 @@ class SoftSPI {
|
||||
* @param[in] txData Data byte to send.
|
||||
* @return Data byte received.
|
||||
*/
|
||||
ALWAYS_INLINE uint8_t transfer(uint8_t txData) {
|
||||
ALWAYS_INLINE uint8_t transfer(uint8_t txData)
|
||||
{
|
||||
uint8_t rxData = 0;
|
||||
transferBit(7, &rxData, txData);
|
||||
transferBit(6, &rxData, txData);
|
||||
@@ -107,9 +112,16 @@ class SoftSPI {
|
||||
|
||||
private:
|
||||
//----------------------------------------------------------------------------
|
||||
ALWAYS_INLINE bool MODE_CPHA(uint8_t mode) {return (mode & 1) != 0;}
|
||||
ALWAYS_INLINE bool MODE_CPOL(uint8_t mode) {return (mode & 2) != 0;}
|
||||
ALWAYS_INLINE void receiveBit(uint8_t bit, uint8_t* data) {
|
||||
ALWAYS_INLINE bool MODE_CPHA(uint8_t mode)
|
||||
{
|
||||
return (mode & 1) != 0;
|
||||
}
|
||||
ALWAYS_INLINE bool MODE_CPOL(uint8_t mode)
|
||||
{
|
||||
return (mode & 2) != 0;
|
||||
}
|
||||
ALWAYS_INLINE void receiveBit(uint8_t bit, uint8_t* data)
|
||||
{
|
||||
if (MODE_CPHA(Mode)) {
|
||||
fastDigitalWrite(SckPin, !MODE_CPOL(Mode));
|
||||
}
|
||||
@@ -117,13 +129,16 @@ class SoftSPI {
|
||||
nop;
|
||||
fastDigitalWrite(SckPin,
|
||||
MODE_CPHA(Mode) ? MODE_CPOL(Mode) : !MODE_CPOL(Mode));
|
||||
if (fastDigitalRead(MisoPin)) *data |= 1 << bit;
|
||||
if (fastDigitalRead(MisoPin)) {
|
||||
*data |= 1 << bit;
|
||||
}
|
||||
if (!MODE_CPHA(Mode)) {
|
||||
fastDigitalWrite(SckPin, MODE_CPOL(Mode));
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
ALWAYS_INLINE void sendBit(uint8_t bit, uint8_t data) {
|
||||
ALWAYS_INLINE void sendBit(uint8_t bit, uint8_t data)
|
||||
{
|
||||
if (MODE_CPHA(Mode)) {
|
||||
fastDigitalWrite(SckPin, !MODE_CPOL(Mode));
|
||||
}
|
||||
@@ -137,14 +152,17 @@ class SoftSPI {
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
ALWAYS_INLINE void transferBit(uint8_t bit, uint8_t* rxData, uint8_t txData) {
|
||||
ALWAYS_INLINE void transferBit(uint8_t bit, uint8_t* rxData, uint8_t txData)
|
||||
{
|
||||
if (MODE_CPHA(Mode)) {
|
||||
fastDigitalWrite(SckPin, !MODE_CPOL(Mode));
|
||||
}
|
||||
fastDigitalWrite(MosiPin, txData & (1 << bit));
|
||||
fastDigitalWrite(SckPin,
|
||||
MODE_CPHA(Mode) ? MODE_CPOL(Mode) : !MODE_CPOL(Mode));
|
||||
if (fastDigitalRead(MisoPin)) *rxData |= 1 << bit;
|
||||
if (fastDigitalRead(MisoPin)) {
|
||||
*rxData |= 1 << bit;
|
||||
}
|
||||
if (!MODE_CPHA(Mode)) {
|
||||
fastDigitalWrite(SckPin, MODE_CPOL(Mode));
|
||||
}
|
||||
|
||||
@@ -9,11 +9,13 @@
|
||||
//------------------------------------------------------------------------------
|
||||
template<uint8_t ClkPin, uint8_t ConvPin, uint8_t DataPin>
|
||||
/** ADS7818 class */
|
||||
class ADS7818 {
|
||||
class ADS7818
|
||||
{
|
||||
public:
|
||||
//----------------------------------------------------------------------------
|
||||
/** Set pin modes and initial levels. */
|
||||
void begin() {
|
||||
void begin()
|
||||
{
|
||||
fastPinMode(ClkPin, 1);
|
||||
fastDigitalWrite(ClkPin, 0);
|
||||
fastPinMode(ConvPin, 1);
|
||||
@@ -25,7 +27,8 @@ class ADS7818 {
|
||||
* \return 16-bit value read.
|
||||
*/
|
||||
inline __attribute__((always_inline))
|
||||
uint16_t read() {
|
||||
uint16_t read()
|
||||
{
|
||||
uint16_t v = 0;
|
||||
fastDigitalWrite(ConvPin, 0);
|
||||
fastDigitalWrite(ClkPin, 1);
|
||||
@@ -51,15 +54,19 @@ class ADS7818 {
|
||||
private:
|
||||
//----------------------------------------------------------------------------
|
||||
inline __attribute__((always_inline))
|
||||
void readBitFast16(uint16_t &v, uint8_t b) {
|
||||
void readBitFast16(uint16_t &v, uint8_t b)
|
||||
{
|
||||
fastDigitalWrite(ClkPin, 1);
|
||||
if (fastDigitalRead(DataPin)) v |= (1 << b);
|
||||
if (fastDigitalRead(DataPin)) {
|
||||
v |= (1 << b);
|
||||
}
|
||||
fastDigitalWrite(ClkPin, 0);
|
||||
}
|
||||
};
|
||||
#if 0
|
||||
/** initialize I/O ports */
|
||||
STATIC_ALWAYS_INLINE void adcBegin() {
|
||||
STATIC_ALWAYS_INLINE void adcBegin()
|
||||
{
|
||||
fastPinMode(ADC_CLK_PIN, 1);
|
||||
fastDigitalWrite(ADC_CLK_PIN, 0);
|
||||
fastPinMode(ADC_CONV_PIN, 1);
|
||||
@@ -69,8 +76,11 @@ STATIC_ALWAYS_INLINE void adcBegin() {
|
||||
//------------------------------------------------------------------------------
|
||||
/** clock for don't care bits
|
||||
*\param[in] delayBefore if true, delay before raising clock*/
|
||||
STATIC_ALWAYS_INLINE void fastDummy(bool first) {
|
||||
if (!first) nop;
|
||||
STATIC_ALWAYS_INLINE void fastDummy(bool first)
|
||||
{
|
||||
if (!first) {
|
||||
nop;
|
||||
}
|
||||
fastDigitalWrite(ADC_CLK_PIN, 1);
|
||||
nop;
|
||||
fastDigitalWrite(ADC_CLK_PIN, 0);
|
||||
@@ -80,16 +90,20 @@ STATIC_ALWAYS_INLINE void fastDummy(bool first) {
|
||||
* \param[in] v word to receive bit
|
||||
* \param[in] b bit number to be set. v |= (1 << b) if next bit is high.
|
||||
*/
|
||||
STATIC_ALWAYS_INLINE void readBitFast16(uint16_t &v, uint8_t b) {
|
||||
STATIC_ALWAYS_INLINE void readBitFast16(uint16_t &v, uint8_t b)
|
||||
{
|
||||
fastDigitalWrite(ADC_CLK_PIN, 1);
|
||||
if (fastDigitalRead(ADC_DATA_PIN)) v |= (1 << b);
|
||||
if (fastDigitalRead(ADC_DATA_PIN)) {
|
||||
v |= (1 << b);
|
||||
}
|
||||
fastDigitalWrite(ADC_CLK_PIN, 0);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
/** Read AD7680 16-bit ADC in less than 8 microseconds
|
||||
* cs is chip select pin
|
||||
*/
|
||||
STATIC_ALWAYS_INLINE uint16_t adcRead(bool centered = false) {
|
||||
STATIC_ALWAYS_INLINE uint16_t adcRead(bool centered = false)
|
||||
{
|
||||
uint16_t v = 0;
|
||||
fastDigitalWrite(ADC_CONV_PIN, 0);
|
||||
fastDigitalWrite(ADC_CLK_PIN, 1);
|
||||
|
||||
@@ -4,11 +4,13 @@
|
||||
//==============================================================================
|
||||
template<uint8_t CsPin, uint8_t ClkPin, uint8_t DoutPin, uint8_t UsecDelay = 0>
|
||||
/** MCP3201 class */
|
||||
class MCP3201 {
|
||||
class MCP3201
|
||||
{
|
||||
public:
|
||||
//----------------------------------------------------------------------------
|
||||
/** Set pin modes and initial levels. */
|
||||
void begin() {
|
||||
void begin()
|
||||
{
|
||||
fastPinMode(ClkPin, 1);
|
||||
fastDigitalWrite(ClkPin, 0);
|
||||
fastPinMode(CsPin, 1);
|
||||
@@ -20,7 +22,8 @@ class MCP3201 {
|
||||
* \return 16-bit value read.
|
||||
*/
|
||||
inline __attribute__((always_inline))
|
||||
uint16_t read() {
|
||||
uint16_t read()
|
||||
{
|
||||
fastDigitalWrite(CsPin, 0);
|
||||
// Start sample.
|
||||
mcpAdcDummy(3);
|
||||
@@ -54,16 +57,24 @@ class MCP3201 {
|
||||
* \param[in] n nops to delay, must be a constant so compiler optimizes if().
|
||||
*/
|
||||
inline __attribute__((always_inline))
|
||||
void delayCycles(uint8_t n) {
|
||||
if (n & 1) asm volatile("nop\n\t");
|
||||
if (n & 2) asm volatile("nop\n\t" "nop\n\t");
|
||||
if (n & 4) asm volatile("nop\n\t" "nop\n\t" "nop\n\t" "nop\n\t");
|
||||
void delayCycles(uint8_t n)
|
||||
{
|
||||
if (n & 1) {
|
||||
asm volatile("nop\n\t");
|
||||
}
|
||||
if (n & 2) {
|
||||
asm volatile("nop\n\t" "nop\n\t");
|
||||
}
|
||||
if (n & 4) {
|
||||
asm volatile("nop\n\t" "nop\n\t" "nop\n\t" "nop\n\t");
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
/** clock for don't care bits
|
||||
*\param[in] delayBefore if true, delay before raising clock*/
|
||||
inline __attribute__((always_inline))
|
||||
void mcpAdcDummy(uint8_t delayBefore) {
|
||||
void mcpAdcDummy(uint8_t delayBefore)
|
||||
{
|
||||
delayCycles(delayBefore);
|
||||
fastDigitalWrite(ClkPin, 1);
|
||||
delayCycles(3);
|
||||
@@ -71,11 +82,14 @@ class MCP3201 {
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
inline __attribute__((always_inline))
|
||||
void readBit(uint16_t &v, uint8_t b, uint8_t delayRead = 2) {
|
||||
void readBit(uint16_t &v, uint8_t b, uint8_t delayRead = 2)
|
||||
{
|
||||
delayCycles(3);
|
||||
fastDigitalWrite(ClkPin, 1);
|
||||
delayCycles(delayRead);
|
||||
if (fastDigitalRead(DoutPin)) v |= (1 << b);
|
||||
if (fastDigitalRead(DoutPin)) {
|
||||
v |= (1 << b);
|
||||
}
|
||||
fastDigitalWrite(ClkPin, 0);
|
||||
}
|
||||
};
|
||||
@@ -83,11 +97,13 @@ class MCP3201 {
|
||||
template<uint8_t CsPin, uint8_t ClkPin,
|
||||
uint8_t DoutPin, uint8_t DinPin, uint8_t UsecDelay = 0>
|
||||
/** MCP3202 class */
|
||||
class MCP3202 {
|
||||
class MCP3202
|
||||
{
|
||||
public:
|
||||
//----------------------------------------------------------------------------
|
||||
/** Set pin modes and initial levels. */
|
||||
void begin() {
|
||||
void begin()
|
||||
{
|
||||
fastPinMode(ClkPin, 1);
|
||||
fastDigitalWrite(ClkPin, 0);
|
||||
fastPinMode(CsPin, 1);
|
||||
@@ -100,7 +116,8 @@ class MCP3202 {
|
||||
* \return 16-bit value read.
|
||||
*/
|
||||
inline __attribute__((always_inline))
|
||||
uint16_t read(uint8_t config) {
|
||||
uint16_t read(uint8_t config)
|
||||
{
|
||||
uint16_t v = 0;
|
||||
fastDigitalWrite(CsPin, 0);
|
||||
// Start bit.
|
||||
@@ -139,16 +156,24 @@ class MCP3202 {
|
||||
* \param[in] n nops to delay, must be a constant so compiler optimizes if().
|
||||
*/
|
||||
inline __attribute__((always_inline))
|
||||
void delayCycles(uint8_t n) {
|
||||
if (n & 1) asm volatile("nop\n\t");
|
||||
if (n & 2) asm volatile("nop\n\t" "nop\n\t");
|
||||
if (n & 4) asm volatile("nop\n\t" "nop\n\t" "nop\n\t" "nop\n\t");
|
||||
void delayCycles(uint8_t n)
|
||||
{
|
||||
if (n & 1) {
|
||||
asm volatile("nop\n\t");
|
||||
}
|
||||
if (n & 2) {
|
||||
asm volatile("nop\n\t" "nop\n\t");
|
||||
}
|
||||
if (n & 4) {
|
||||
asm volatile("nop\n\t" "nop\n\t" "nop\n\t" "nop\n\t");
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
/** clock for don't care bits
|
||||
*\param[in] delayBefore if true, delay before raising clock*/
|
||||
inline __attribute__((always_inline))
|
||||
void writeBit(bool value) {
|
||||
void writeBit(bool value)
|
||||
{
|
||||
fastDigitalWrite(DinPin, value);
|
||||
fastDigitalWrite(ClkPin, 1);
|
||||
delayCycles(2);
|
||||
@@ -156,11 +181,14 @@ class MCP3202 {
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
inline __attribute__((always_inline))
|
||||
void readBit(uint16_t &v, uint8_t b, uint8_t delayRead = 1) {
|
||||
void readBit(uint16_t &v, uint8_t b, uint8_t delayRead = 1)
|
||||
{
|
||||
delayCycles(2);
|
||||
fastDigitalWrite(ClkPin, 1);
|
||||
delayCycles(delayRead);
|
||||
if (fastDigitalRead(DoutPin)) v |= (1 << b);
|
||||
if (fastDigitalRead(DoutPin)) {
|
||||
v |= (1 << b);
|
||||
}
|
||||
fastDigitalWrite(ClkPin, 0);
|
||||
}
|
||||
};
|
||||
@@ -168,11 +196,13 @@ class MCP3202 {
|
||||
template<uint8_t CsPin, uint8_t ClkPin,
|
||||
uint8_t DoutPin, uint8_t DinPin, uint8_t UsecDelay = 0>
|
||||
/** MCP3204 class */
|
||||
class MCP3204 {
|
||||
class MCP3204
|
||||
{
|
||||
public:
|
||||
//----------------------------------------------------------------------------
|
||||
/** Set pin modes and initial levels. */
|
||||
void begin() {
|
||||
void begin()
|
||||
{
|
||||
fastPinMode(ClkPin, 1);
|
||||
fastDigitalWrite(ClkPin, 0);
|
||||
fastPinMode(CsPin, 1);
|
||||
@@ -185,7 +215,8 @@ class MCP3204 {
|
||||
* \return 16-bit value read.
|
||||
*/
|
||||
inline __attribute__((always_inline))
|
||||
uint16_t read(uint8_t config) {
|
||||
uint16_t read(uint8_t config)
|
||||
{
|
||||
uint16_t v = 0;
|
||||
fastDigitalWrite(CsPin, 0);
|
||||
// Start bit.
|
||||
@@ -228,16 +259,24 @@ class MCP3204 {
|
||||
* \param[in] n nops to delay, must be a constant so compiler optimizes if().
|
||||
*/
|
||||
inline __attribute__((always_inline))
|
||||
void delayCycles(uint8_t n) {
|
||||
if (n & 1) asm volatile("nop\n\t");
|
||||
if (n & 2) asm volatile("nop\n\t" "nop\n\t");
|
||||
if (n & 4) asm volatile("nop\n\t" "nop\n\t" "nop\n\t" "nop\n\t");
|
||||
void delayCycles(uint8_t n)
|
||||
{
|
||||
if (n & 1) {
|
||||
asm volatile("nop\n\t");
|
||||
}
|
||||
if (n & 2) {
|
||||
asm volatile("nop\n\t" "nop\n\t");
|
||||
}
|
||||
if (n & 4) {
|
||||
asm volatile("nop\n\t" "nop\n\t" "nop\n\t" "nop\n\t");
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
/** clock for don't care bits
|
||||
*\param[in] delayBefore if true, delay before raising clock*/
|
||||
inline __attribute__((always_inline))
|
||||
void writeBit(bool value) {
|
||||
void writeBit(bool value)
|
||||
{
|
||||
fastDigitalWrite(DinPin, value);
|
||||
fastDigitalWrite(ClkPin, 1);
|
||||
delayCycles(2);
|
||||
@@ -245,11 +284,14 @@ class MCP3204 {
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
inline __attribute__((always_inline))
|
||||
void readBit(uint16_t &v, uint8_t b, uint8_t delayRead = 1) {
|
||||
void readBit(uint16_t &v, uint8_t b, uint8_t delayRead = 1)
|
||||
{
|
||||
delayCycles(2);
|
||||
fastDigitalWrite(ClkPin, 1);
|
||||
delayCycles(delayRead);
|
||||
if (fastDigitalRead(DoutPin)) v |= (1 << b);
|
||||
if (fastDigitalRead(DoutPin)) {
|
||||
v |= (1 << b);
|
||||
}
|
||||
fastDigitalWrite(ClkPin, 0);
|
||||
}
|
||||
};
|
||||
@@ -257,6 +299,7 @@ class MCP3204 {
|
||||
// MCP3204 and MCP3208 use the same code.
|
||||
template<uint8_t CsPin, uint8_t ClkPin,
|
||||
uint8_t DoutPin, uint8_t DinPin, uint8_t UsecDelay = 0>
|
||||
class MCP3208 : public MCP3204<CsPin, ClkPin, DoutPin, DinPin, UsecDelay> {
|
||||
class MCP3208 : public MCP3204<CsPin, ClkPin, DoutPin, DinPin, UsecDelay>
|
||||
{
|
||||
};
|
||||
#endif // MCP320X_h
|
||||
@@ -9,11 +9,13 @@ const uint8_t MCP355X_TO_MS = 100;
|
||||
//==============================================================================
|
||||
template<uint8_t CsPin, uint8_t SckPin, uint8_t SdoPin>
|
||||
/** MCP355X class */
|
||||
class MCP355X {
|
||||
class MCP355X
|
||||
{
|
||||
public:
|
||||
//----------------------------------------------------------------------------
|
||||
/** Set pin modes and initial levels. */
|
||||
void begin(bool singleMode = true) {
|
||||
void begin(bool singleMode = true)
|
||||
{
|
||||
m_singleMode = singleMode;
|
||||
fastPinMode(SdoPin, 0);
|
||||
fastPinMode(SckPin, 1);
|
||||
@@ -32,7 +34,8 @@ class MCP355X {
|
||||
* \return 22-bit value.
|
||||
*/
|
||||
inline __attribute__((always_inline))
|
||||
int32_t read() {
|
||||
int32_t read()
|
||||
{
|
||||
uint8_t t = 0;
|
||||
uint8_t v3 = 0;
|
||||
if (m_singleMode) {
|
||||
@@ -48,15 +51,23 @@ class MCP355X {
|
||||
fastDigitalWrite(CsPin, 0);
|
||||
// Delay while RDY settles.
|
||||
delayCycles(4);
|
||||
if (!fastDigitalRead(SdoPin)) break;
|
||||
if (!fastDigitalRead(SdoPin)) {
|
||||
break;
|
||||
}
|
||||
fastDigitalWrite(CsPin, 1);
|
||||
if (t++ > MCP355X_TO_MS) return MCP355X_ERR;
|
||||
if (t++ > MCP355X_TO_MS) {
|
||||
return MCP355X_ERR;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
while (1) {
|
||||
if (!fastDigitalRead(SdoPin)) break;
|
||||
if (!fastDigitalRead(SdoPin)) {
|
||||
break;
|
||||
}
|
||||
delay(1);
|
||||
if (t++ > MCP355X_TO_MS) return MCP355X_ERR;
|
||||
if (t++ > MCP355X_TO_MS) {
|
||||
return MCP355X_ERR;
|
||||
}
|
||||
}
|
||||
}
|
||||
uint8_t v2 = readByte();
|
||||
@@ -76,10 +87,14 @@ class MCP355X {
|
||||
v3 = 0XFF;
|
||||
} else if (v2 & 0X40) {
|
||||
// Overflow high. Cause value to be >= MCP355X_OVH.
|
||||
if (v2 & 0X20) v2 &= 0X3F;
|
||||
if (v2 & 0X20) {
|
||||
v2 &= 0X3F;
|
||||
}
|
||||
} else if (v2 & 0X80) {
|
||||
// Overflow low. Cause value to be <= MCP355X_OVH.
|
||||
if ((v2 & 0X20) == 0) v2 |= 0X40;
|
||||
if ((v2 & 0X20) == 0) {
|
||||
v2 |= 0X40;
|
||||
}
|
||||
v3 = 0XFF;
|
||||
}
|
||||
uint16_t v_high = (v3 << 8) | v2;
|
||||
@@ -92,24 +107,35 @@ class MCP355X {
|
||||
* \param[in] n nops to delay, must be a constant so compiler optimizes if().
|
||||
*/
|
||||
inline __attribute__((always_inline))
|
||||
void delayCycles(uint8_t n) {
|
||||
if (n & 1) asm volatile("nop\n\t");
|
||||
if (n & 2) asm volatile("nop\n\t" "nop\n\t");
|
||||
if (n & 4) asm volatile("nop\n\t" "nop\n\t" "nop\n\t" "nop\n\t");
|
||||
void delayCycles(uint8_t n)
|
||||
{
|
||||
if (n & 1) {
|
||||
asm volatile("nop\n\t");
|
||||
}
|
||||
if (n & 2) {
|
||||
asm volatile("nop\n\t" "nop\n\t");
|
||||
}
|
||||
if (n & 4) {
|
||||
asm volatile("nop\n\t" "nop\n\t" "nop\n\t" "nop\n\t");
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
// Default delay yields about 2 MHz clock.
|
||||
inline __attribute__((always_inline))
|
||||
void readBit(uint8_t &v, uint8_t b, uint8_t delayRead = 0) {
|
||||
void readBit(uint8_t &v, uint8_t b, uint8_t delayRead = 0)
|
||||
{
|
||||
fastDigitalWrite(SckPin, 0);
|
||||
delayCycles(2 + delayRead);
|
||||
fastDigitalWrite(SckPin, 1);
|
||||
if (fastDigitalRead(SdoPin)) v |= (1 << b);
|
||||
if (fastDigitalRead(SdoPin)) {
|
||||
v |= (1 << b);
|
||||
}
|
||||
delayCycles(delayRead);
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
inline __attribute__((always_inline))
|
||||
uint8_t readByte() {
|
||||
uint8_t readByte()
|
||||
{
|
||||
uint8_t v = 0;
|
||||
readBit(v, 7);
|
||||
readBit(v, 6);
|
||||
|
||||
@@ -4,7 +4,8 @@ DigitalPin<13> pin13(OUTPUT);
|
||||
|
||||
void setup() {}
|
||||
|
||||
void loop() {
|
||||
void loop()
|
||||
{
|
||||
// toggle is a two byte instruction that executes
|
||||
// in two cycles or 125 ns on a 16 MHz CPU
|
||||
pin13.toggle();
|
||||
|
||||
@@ -4,11 +4,13 @@
|
||||
// Class with compile time pin number.
|
||||
DigitalPin<13> pin13;
|
||||
|
||||
void setup() {
|
||||
void setup()
|
||||
{
|
||||
// Set mode to OUTPUT and level LOW.
|
||||
pin13.config(OUTPUT, LOW);
|
||||
}
|
||||
void loop() {
|
||||
void loop()
|
||||
{
|
||||
// toggle is a two byte instruction that executes
|
||||
// in two cycles or 125 ns on a 16 MHz CPU
|
||||
pin13.toggle();
|
||||
|
||||
@@ -6,6 +6,7 @@ DigitalPin<13> pin13(OUTPUT);
|
||||
|
||||
void setup() {}
|
||||
|
||||
void loop() {
|
||||
void loop()
|
||||
{
|
||||
pin13 = pin12;
|
||||
}
|
||||
@@ -10,7 +10,8 @@ DigitalPin<13> dataPin(OUTPUT, HIGH);
|
||||
//------------------------------------------------------------------------------
|
||||
// Time to send one bit is ten cycles or 625 ns for 16 MHz CPU.
|
||||
inline __attribute__((always_inline))
|
||||
void sendBit(uint8_t bit, uint8_t data) {
|
||||
void sendBit(uint8_t bit, uint8_t data)
|
||||
{
|
||||
dataPin = data & (1 << bit);
|
||||
clockPin = 1;
|
||||
// may want a nop here - clock pulse is 125 ns wide
|
||||
@@ -18,7 +19,8 @@ void sendBit(uint8_t bit, uint8_t data) {
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
// Time to send one byte is 5 usec.
|
||||
void shiftOut(uint8_t bits) {
|
||||
void shiftOut(uint8_t bits)
|
||||
{
|
||||
sendBit(7, bits);
|
||||
sendBit(6, bits);
|
||||
sendBit(5, bits);
|
||||
@@ -29,11 +31,13 @@ void shiftOut(uint8_t bits) {
|
||||
sendBit(0, bits);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void setup() {
|
||||
void setup()
|
||||
{
|
||||
// Not used.
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void loop() {
|
||||
void loop()
|
||||
{
|
||||
shiftOut(0X55);
|
||||
delay(2);
|
||||
}
|
||||
|
||||
@@ -6,7 +6,8 @@
|
||||
PinIO readPin;
|
||||
PinIO writePin;
|
||||
//------------------------------------------------------------------------------
|
||||
void setup() {
|
||||
void setup()
|
||||
{
|
||||
// Assign pin 12 to readPin.
|
||||
readPin.begin(12);
|
||||
|
||||
@@ -18,7 +19,8 @@ void setup() {
|
||||
writePin.mode(OUTPUT);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void loop() {
|
||||
void loop()
|
||||
{
|
||||
// Copy the value read from readPin to writePin.
|
||||
writePin.write(readPin.read());
|
||||
}
|
||||
@@ -4,11 +4,13 @@
|
||||
// Set runtime pin number.
|
||||
PinIO pin13(13);
|
||||
|
||||
void setup() {
|
||||
void setup()
|
||||
{
|
||||
// set mode to OUTPUT and level LOW
|
||||
pin13.config(OUTPUT, LOW);
|
||||
}
|
||||
void loop() {
|
||||
void loop()
|
||||
{
|
||||
pin13.toggle();
|
||||
delay(100);
|
||||
pin13.toggle();
|
||||
|
||||
@@ -4,13 +4,15 @@
|
||||
PinIO readPin(12);
|
||||
PinIO writePin(13);
|
||||
|
||||
void setup() {
|
||||
void setup()
|
||||
{
|
||||
// Set input mode and disable pull-up.
|
||||
readPin.config(INPUT, LOW);
|
||||
|
||||
// set output mode
|
||||
writePin.mode(OUTPUT);
|
||||
}
|
||||
void loop() {
|
||||
void loop()
|
||||
{
|
||||
writePin.write(readPin.read());
|
||||
}
|
||||
@@ -26,7 +26,8 @@ const uint8_t SCL_PIN = A5;
|
||||
SoftI2cMaster i2c(SCL_PIN, SDA_PIN);
|
||||
//FastI2cMaster<SCL_PIN, SDA_PIN> i2c;
|
||||
//------------------------------------------------------------------------------
|
||||
void setup() {
|
||||
void setup()
|
||||
{
|
||||
|
||||
Serial.begin(9600);
|
||||
while (!Serial);
|
||||
@@ -55,14 +56,19 @@ void setup() {
|
||||
Serial.print("Device at address: 0X");
|
||||
Serial.print(add, HEX);
|
||||
Serial.print(" responds to ");
|
||||
if (rd) Serial.print("Read");
|
||||
if (rd && wr) Serial.print(" and ");
|
||||
if (wr) Serial.print("Write");
|
||||
if (rd) {
|
||||
Serial.print("Read");
|
||||
}
|
||||
if (rd && wr) {
|
||||
Serial.print(" and ");
|
||||
}
|
||||
if (wr) {
|
||||
Serial.print("Write");
|
||||
}
|
||||
Serial.println('.');
|
||||
}
|
||||
add += 2;
|
||||
}
|
||||
while (add);
|
||||
} while (add);
|
||||
|
||||
if (!found) {
|
||||
Serial.println("No devices found.");
|
||||
@@ -70,7 +76,8 @@ void setup() {
|
||||
Serial.println("Done");
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void loop() {
|
||||
void loop()
|
||||
{
|
||||
// Not used.
|
||||
}
|
||||
|
||||
|
||||
@@ -16,10 +16,13 @@ FastI2cMaster<SCL_PIN, SDA_PIN> rtc;
|
||||
/*
|
||||
* Read 'count' bytes from the DS1307 starting at 'address'.
|
||||
*/
|
||||
uint8_t readDS1307(uint8_t address, uint8_t *buf, uint8_t count) {
|
||||
uint8_t readDS1307(uint8_t address, uint8_t *buf, uint8_t count)
|
||||
{
|
||||
|
||||
// Send address of data.
|
||||
if (!rtc.transfer(DS1307ADDR | I2C_WRITE, &address, 1)) return false;
|
||||
if (!rtc.transfer(DS1307ADDR | I2C_WRITE, &address, 1)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Read data.
|
||||
return rtc.transfer(DS1307ADDR | I2C_READ, buf, count);
|
||||
@@ -28,7 +31,8 @@ uint8_t readDS1307(uint8_t address, uint8_t *buf, uint8_t count) {
|
||||
/*
|
||||
* write 'count' bytes to DS1307 starting at 'address'.
|
||||
*/
|
||||
uint8_t writeDS1307(uint8_t address, uint8_t *buf, uint8_t count) {
|
||||
uint8_t writeDS1307(uint8_t address, uint8_t *buf, uint8_t count)
|
||||
{
|
||||
|
||||
// Write address and continue transfer for write of data.
|
||||
if (!rtc.transfer(DS1307ADDR | I2C_WRITE, &address, 1, I2C_CONTINUE)) {
|
||||
@@ -38,7 +42,8 @@ uint8_t writeDS1307(uint8_t address, uint8_t *buf, uint8_t count) {
|
||||
return rtc.transferContinue(buf, count);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void setup(void) {
|
||||
void setup(void)
|
||||
{
|
||||
Serial.begin(9600);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -50,18 +55,21 @@ void setup(void) {
|
||||
// Day of week U.S. convention.
|
||||
char *Ddd[] = {"Bad", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
|
||||
//------------------------------------------------------------------------------
|
||||
void hexPrint(uint8_t v) {
|
||||
void hexPrint(uint8_t v)
|
||||
{
|
||||
Serial.print(v >> 4, HEX);
|
||||
Serial.print(v & 0XF, HEX);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void hexPrintln(uint8_t v) {
|
||||
void hexPrintln(uint8_t v)
|
||||
{
|
||||
hexPrint(v);
|
||||
Serial.println();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
// read hex input
|
||||
uint8_t hexRead(uint16_t* v) {
|
||||
uint8_t hexRead(uint16_t* v)
|
||||
{
|
||||
bool valid = false;
|
||||
uint16_t n = 0;
|
||||
while (!Serial.available());
|
||||
@@ -77,14 +85,11 @@ uint8_t hexRead(uint16_t* v) {
|
||||
n <<= 4;
|
||||
if ('a' <= c && c <= 'f') {
|
||||
n += c - ('a' - 10);
|
||||
}
|
||||
else if ('A' <= c && c <= 'F') {
|
||||
} else if ('A' <= c && c <= 'F') {
|
||||
n += c - ('A' - 10);
|
||||
}
|
||||
else if ('0' <= c && c <= '9') {
|
||||
} else if ('0' <= c && c <= '9') {
|
||||
n += c - '0';
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
valid = false;
|
||||
break;
|
||||
}
|
||||
@@ -99,9 +104,12 @@ uint8_t hexRead(uint16_t* v) {
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
uint8_t bcdRead(uint8_t min, uint8_t max, uint8_t* n) {
|
||||
uint8_t bcdRead(uint8_t min, uint8_t max, uint8_t* n)
|
||||
{
|
||||
uint16_t v;
|
||||
if (!hexRead(&v)) return false;
|
||||
if (!hexRead(&v)) {
|
||||
return false;
|
||||
}
|
||||
uint8_t d = 10 * (v >> 4) + (v & 0XF);
|
||||
if ((v >> 4) > 9 || (v & 0XF) > 9 || d < min || d > max) {
|
||||
PgmPrintln("Invalid");
|
||||
@@ -111,7 +119,8 @@ uint8_t bcdRead(uint8_t min, uint8_t max, uint8_t* n) {
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void displayTime(void) {
|
||||
void displayTime(void)
|
||||
{
|
||||
uint8_t r[8];
|
||||
if (!readDS1307(0, r, 8)) {
|
||||
PgmPrintln("Read Failed for display time");
|
||||
@@ -150,7 +159,8 @@ void displayTime(void) {
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
// dump registers and 56 bytes of RAM
|
||||
void dumpAll(void) {
|
||||
void dumpAll(void)
|
||||
{
|
||||
uint8_t buf[8];
|
||||
for (uint8_t a = 0; a < 64; a += 8) {
|
||||
hexPrint(a);
|
||||
@@ -167,11 +177,14 @@ void dumpAll(void) {
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void fillNvRam(void) {
|
||||
void fillNvRam(void)
|
||||
{
|
||||
uint8_t buf[8];
|
||||
PgmPrint("Enter HEX value for all NV RAM locations (00-FF): ");
|
||||
uint16_t v;
|
||||
if (!hexRead(&v)) return;
|
||||
if (!hexRead(&v)) {
|
||||
return;
|
||||
}
|
||||
hexPrint(v);
|
||||
for (uint8_t a = 8; a < 64; a ++) {
|
||||
if (!writeDS1307(a, (uint8_t *)&v, 1)) {
|
||||
@@ -205,7 +218,8 @@ RS1 RS0 FREQUENCY
|
||||
1 0 8.192kHz
|
||||
1 1 32.768kHz
|
||||
*/
|
||||
void setControl(void) {
|
||||
void setControl(void)
|
||||
{
|
||||
PgmPrintln("SQW/OUT pin: ");
|
||||
PgmPrintln("(00) Low");
|
||||
PgmPrintln("(10) 1Hz");
|
||||
@@ -215,26 +229,37 @@ void setControl(void) {
|
||||
PgmPrintln("(80) High");
|
||||
PgmPrint("Enter control: ");
|
||||
uint16_t r;
|
||||
if (!hexRead(&r)) return;
|
||||
if (!hexRead(&r)) {
|
||||
return;
|
||||
}
|
||||
hexPrintln(r);
|
||||
if (!writeDS1307(7, (uint8_t *)&r, 1)) {
|
||||
PgmPrint("Write Failed for setControl");
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void setDate(void) {
|
||||
void setDate(void)
|
||||
{
|
||||
uint8_t r[4];
|
||||
PgmPrint("Enter year (00-99): ");
|
||||
if (!bcdRead(0, 99, &r[3])) return;
|
||||
if (!bcdRead(0, 99, &r[3])) {
|
||||
return;
|
||||
}
|
||||
hexPrintln(r[3]);
|
||||
PgmPrint("Enter month (01-12): ");
|
||||
if (!bcdRead(1, 12, &r[2])) return;
|
||||
if (!bcdRead(1, 12, &r[2])) {
|
||||
return;
|
||||
}
|
||||
hexPrintln(r[2]);
|
||||
PgmPrint("Enter day (01-31): ");
|
||||
if (!bcdRead(1, 31, &r[1])) return;
|
||||
if (!bcdRead(1, 31, &r[1])) {
|
||||
return;
|
||||
}
|
||||
hexPrintln(r[1]);
|
||||
PgmPrint("Enter day of week (01-07, Sun-Sat): ");
|
||||
if (!bcdRead(1, 7, &r[0])) return;
|
||||
if (!bcdRead(1, 7, &r[0])) {
|
||||
return;
|
||||
}
|
||||
hexPrintln(r[0]);
|
||||
|
||||
if (!writeDS1307(3, r, 4)) {
|
||||
@@ -242,12 +267,15 @@ void setDate(void) {
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void setNvRam() {
|
||||
void setNvRam()
|
||||
{
|
||||
uint8_t u;
|
||||
uint16_t a, v;
|
||||
while (true) {
|
||||
PgmPrint("Enter zero to quit or Hex address (8-3F):");
|
||||
if (!hexRead(&a) || a == 0) return;
|
||||
if (!hexRead(&a) || a == 0) {
|
||||
return;
|
||||
}
|
||||
if (a < 8 || a > 0X3F) {
|
||||
PgmPrintln("Invalid address");
|
||||
return;
|
||||
@@ -260,7 +288,9 @@ void setNvRam() {
|
||||
PgmPrint("Current value: ");
|
||||
hexPrintln(u);
|
||||
PgmPrint("Enter new HEX value (00-FF): ");
|
||||
if (!hexRead(&v)) return;
|
||||
if (!hexRead(&v)) {
|
||||
return;
|
||||
}
|
||||
hexPrintln(v);
|
||||
if (!writeDS1307(a, (uint8_t *)&v, 1)) {
|
||||
PgmPrint("Write Failed");
|
||||
@@ -269,16 +299,23 @@ void setNvRam() {
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void setTime(void) {
|
||||
void setTime(void)
|
||||
{
|
||||
uint8_t r[3];
|
||||
PgmPrint("Enter hours (00-23): ");
|
||||
if (!bcdRead(0, 23, &r[2])) return;
|
||||
if (!bcdRead(0, 23, &r[2])) {
|
||||
return;
|
||||
}
|
||||
hexPrintln(r[2]);
|
||||
PgmPrint("Enter minutes (00-59): ");
|
||||
if (!bcdRead(0, 59, &r[1])) return;
|
||||
if (!bcdRead(0, 59, &r[1])) {
|
||||
return;
|
||||
}
|
||||
hexPrintln(r[1]);
|
||||
PgmPrint("Enter seconds (00-59): ");
|
||||
if (!bcdRead(0, 59, &r[0])) return;
|
||||
if (!bcdRead(0, 59, &r[0])) {
|
||||
return;
|
||||
}
|
||||
hexPrintln(r[0]);
|
||||
|
||||
if (!writeDS1307(0, r, 3)) {
|
||||
@@ -287,7 +324,8 @@ void setTime(void) {
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void loop(void) {
|
||||
void loop(void)
|
||||
{
|
||||
Serial.println();
|
||||
displayTime();
|
||||
while (Serial.read() >= 0) {}
|
||||
@@ -302,9 +340,13 @@ void loop(void) {
|
||||
PgmPrint("Enter option: ");
|
||||
|
||||
uint16_t n;
|
||||
if (!hexRead(&n)) return;
|
||||
if (!hexRead(&n)) {
|
||||
return;
|
||||
}
|
||||
Serial.println(n, DEC);
|
||||
if (n == 0) return;
|
||||
if (n == 0) {
|
||||
return;
|
||||
}
|
||||
Serial.println();
|
||||
if (n == 1) {
|
||||
setTime();
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
// Scope test for write timing with Arduino digitaWrite().
|
||||
const uint8_t PIN13 = 13;
|
||||
|
||||
void setup() {
|
||||
void setup()
|
||||
{
|
||||
// Set mode to OUTPUT.
|
||||
pinMode(PIN13, OUTPUT);
|
||||
}
|
||||
void loop() {
|
||||
void loop()
|
||||
{
|
||||
digitalWrite(PIN13, HIGH);
|
||||
digitalWrite(PIN13, LOW);
|
||||
digitalWrite(PIN13, HIGH);
|
||||
|
||||
@@ -4,11 +4,13 @@
|
||||
// Class with compile time pin number.
|
||||
DigitalPin<13> pin13;
|
||||
|
||||
void setup() {
|
||||
void setup()
|
||||
{
|
||||
// set mode to OUTPUT
|
||||
pin13.mode(OUTPUT);
|
||||
}
|
||||
void loop() {
|
||||
void loop()
|
||||
{
|
||||
pin13.high();
|
||||
pin13.low();
|
||||
pin13.write(1);
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
// Test fastDigital function timing with a scope.
|
||||
#include <DigitalIO.h>
|
||||
const uint8_t PIN = 13;
|
||||
void setup() {
|
||||
void setup()
|
||||
{
|
||||
fastPinMode(PIN, OUTPUT);
|
||||
}
|
||||
void loop() {
|
||||
void loop()
|
||||
{
|
||||
fastDigitalWrite(PIN, HIGH);
|
||||
fastDigitalWrite(PIN, LOW);
|
||||
fastDigitalToggle(PIN);
|
||||
|
||||
@@ -4,11 +4,13 @@
|
||||
// Class with runtime pin numbers.
|
||||
PinIO pin(13);
|
||||
|
||||
void setup() {
|
||||
void setup()
|
||||
{
|
||||
// Set mode to OUTPUT.
|
||||
pin.mode(OUTPUT);
|
||||
}
|
||||
void loop() {
|
||||
void loop()
|
||||
{
|
||||
pin.high();
|
||||
pin.low();
|
||||
pin.write(1);
|
||||
|
||||
@@ -9,7 +9,8 @@ const uint8_t SPI_MODE = 0;
|
||||
SoftSPI<SOFT_SPI_MISO_PIN, SOFT_SPI_MOSI_PIN, SOFT_SPI_SCK_PIN, SPI_MODE> spi;
|
||||
|
||||
int test;
|
||||
void setup() {
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(9600);
|
||||
spi.begin();
|
||||
while(1) {
|
||||
@@ -19,14 +20,19 @@ void setup() {
|
||||
Serial.println("T - Transfer");
|
||||
while ((test = Serial.read()) <= 0) {}
|
||||
test = toupper(test);
|
||||
if (strchr("RST", test)) break;
|
||||
if (strchr("RST", test)) {
|
||||
break;
|
||||
}
|
||||
Serial.println("Invalid entry");
|
||||
};
|
||||
Serial.print("Starting test ");
|
||||
Serial.println((char)test);
|
||||
}
|
||||
void loop() {
|
||||
if (test == 'S') spi.send(0X55);
|
||||
void loop()
|
||||
{
|
||||
if (test == 'S') {
|
||||
spi.send(0X55);
|
||||
}
|
||||
if (test == 'R') {
|
||||
Serial.println(spi.receive(), HEX);
|
||||
}
|
||||
|
||||
@@ -44,28 +44,61 @@ class AltSoftSerial : public Stream
|
||||
{
|
||||
public:
|
||||
AltSoftSerial() { } //!< Constructor
|
||||
~AltSoftSerial() { end(); } //!< Destructor
|
||||
static void begin(uint32_t baud) { init((ALTSS_BASE_FREQ + baud / 2) / baud); } //!< begin
|
||||
~AltSoftSerial()
|
||||
{
|
||||
end(); //!< Destructor
|
||||
}
|
||||
static void begin(uint32_t baud)
|
||||
{
|
||||
init((ALTSS_BASE_FREQ + baud / 2) / baud); //!< begin
|
||||
}
|
||||
static void end(); //!< end
|
||||
int peek(); //!< peek
|
||||
int read(); //!< read
|
||||
int available(); //!< available
|
||||
#if ARDUINO >= 100
|
||||
size_t write(uint8_t byte) { writeByte(byte); return 1; } //!< write
|
||||
void flush() { flushOutput(); } //!< flush
|
||||
size_t write(uint8_t byte)
|
||||
{
|
||||
writeByte(byte); //!< write
|
||||
return 1;
|
||||
}
|
||||
void flush()
|
||||
{
|
||||
flushOutput(); //!< flush
|
||||
}
|
||||
#else
|
||||
void write(uint8_t byte) { writeByte(byte); } //!< write
|
||||
void flush() { flushInput(); } //!< flush
|
||||
void write(uint8_t byte)
|
||||
{
|
||||
writeByte(byte); //!< write
|
||||
}
|
||||
void flush()
|
||||
{
|
||||
flushInput(); //!< flush
|
||||
}
|
||||
#endif
|
||||
using Print::write;
|
||||
static void flushInput(); //!< flushInput
|
||||
static void flushOutput(); //!< flushOutput
|
||||
// for drop-in compatibility with NewSoftSerial, rxPin & txPin ignored
|
||||
//AltSoftSerial(uint8_t rxPin, uint8_t txPin, bool inverse = false) { }
|
||||
bool listen() { return false; } //!< listen
|
||||
bool isListening() { return true; } //!< isListening
|
||||
bool overflow() { bool r = timing_error; timing_error = false; return r; } //!< overflow
|
||||
static int library_version() { return 1; } //!< library_version
|
||||
bool listen()
|
||||
{
|
||||
return false; //!< listen
|
||||
}
|
||||
bool isListening()
|
||||
{
|
||||
return true; //!< isListening
|
||||
}
|
||||
bool overflow()
|
||||
{
|
||||
bool r = timing_error; //!< overflow
|
||||
timing_error = false;
|
||||
return r;
|
||||
}
|
||||
static int library_version()
|
||||
{
|
||||
return 1; //!< library_version
|
||||
}
|
||||
static void enable_timer0(bool) { } //!< enable_timer0
|
||||
static bool timing_error; //!< timing_error
|
||||
private:
|
||||
|
||||
@@ -50,8 +50,7 @@ template <class T> class CircularBuffer
|
||||
*/
|
||||
void clear(void)
|
||||
{
|
||||
MY_CRITICAL_SECTION
|
||||
{
|
||||
MY_CRITICAL_SECTION {
|
||||
m_front = 0;
|
||||
m_fill = 0;
|
||||
}
|
||||
@@ -64,8 +63,7 @@ template <class T> class CircularBuffer
|
||||
inline bool empty(void) const
|
||||
{
|
||||
bool empty;
|
||||
MY_CRITICAL_SECTION
|
||||
{
|
||||
MY_CRITICAL_SECTION {
|
||||
empty = !m_fill;
|
||||
}
|
||||
return empty;
|
||||
@@ -78,8 +76,7 @@ template <class T> class CircularBuffer
|
||||
inline bool full(void) const
|
||||
{
|
||||
bool full;
|
||||
MY_CRITICAL_SECTION
|
||||
{
|
||||
MY_CRITICAL_SECTION {
|
||||
full = m_fill == m_size;
|
||||
}
|
||||
return full;
|
||||
@@ -91,8 +88,7 @@ template <class T> class CircularBuffer
|
||||
*/
|
||||
inline uint8_t available(void) const
|
||||
{
|
||||
MY_CRITICAL_SECTION
|
||||
{
|
||||
MY_CRITICAL_SECTION {
|
||||
return m_fill;
|
||||
}
|
||||
}
|
||||
@@ -105,9 +101,11 @@ template <class T> class CircularBuffer
|
||||
*/
|
||||
T* getFront(void) const
|
||||
{
|
||||
MY_CRITICAL_SECTION
|
||||
MY_CRITICAL_SECTION {
|
||||
if (!full())
|
||||
{
|
||||
if (!full()) return get(m_front);
|
||||
return get(m_front);
|
||||
}
|
||||
}
|
||||
return static_cast<T*>(NULL);
|
||||
}
|
||||
@@ -120,13 +118,13 @@ template <class T> class CircularBuffer
|
||||
*/
|
||||
bool pushFront(T* record)
|
||||
{
|
||||
MY_CRITICAL_SECTION
|
||||
{
|
||||
MY_CRITICAL_SECTION {
|
||||
if (!full())
|
||||
{
|
||||
T* f = get(m_front);
|
||||
if (f != record)
|
||||
if (f != record) {
|
||||
*f = *record;
|
||||
}
|
||||
m_front = (m_front+1) % m_size;
|
||||
m_fill++;
|
||||
return true;
|
||||
@@ -143,9 +141,11 @@ template <class T> class CircularBuffer
|
||||
*/
|
||||
T* getBack(void) const
|
||||
{
|
||||
MY_CRITICAL_SECTION
|
||||
MY_CRITICAL_SECTION {
|
||||
if (!empty())
|
||||
{
|
||||
if (!empty()) return get(back());
|
||||
return get(back());
|
||||
}
|
||||
}
|
||||
return static_cast<T*>(NULL);
|
||||
}
|
||||
@@ -156,8 +156,7 @@ template <class T> class CircularBuffer
|
||||
*/
|
||||
bool popBack(void)
|
||||
{
|
||||
MY_CRITICAL_SECTION
|
||||
{
|
||||
MY_CRITICAL_SECTION {
|
||||
if (!empty())
|
||||
{
|
||||
m_fill--;
|
||||
|
||||
@@ -26,7 +26,8 @@
|
||||
#include "IPAddress.h"
|
||||
|
||||
#if !DOXYGEN
|
||||
class Client : public Stream {
|
||||
class Client : public Stream
|
||||
{
|
||||
|
||||
public:
|
||||
virtual int connect(IPAddress ip, uint16_t port) = 0;
|
||||
@@ -43,7 +44,10 @@ public:
|
||||
virtual operator bool() = 0;
|
||||
|
||||
protected:
|
||||
uint8_t* rawIPAddress(IPAddress& addr) { return addr.raw_address(); };
|
||||
uint8_t* rawIPAddress(IPAddress& addr)
|
||||
{
|
||||
return addr.raw_address();
|
||||
};
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
@@ -32,13 +32,16 @@
|
||||
#include "log.h"
|
||||
#include "EthernetClient.h"
|
||||
|
||||
EthernetClient::EthernetClient() : _sock(-1) {
|
||||
EthernetClient::EthernetClient() : _sock(-1)
|
||||
{
|
||||
}
|
||||
|
||||
EthernetClient::EthernetClient(int sock) : _sock(sock) {
|
||||
EthernetClient::EthernetClient(int sock) : _sock(sock)
|
||||
{
|
||||
}
|
||||
|
||||
int EthernetClient::connect(const char* host, uint16_t port) {
|
||||
int EthernetClient::connect(const char* host, uint16_t port)
|
||||
{
|
||||
int sockfd;
|
||||
struct addrinfo hints, *servinfo, *p;
|
||||
int rv;
|
||||
@@ -88,15 +91,18 @@ int EthernetClient::connect(const char* host, uint16_t port) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
int EthernetClient::connect(IPAddress ip, uint16_t port) {
|
||||
int EthernetClient::connect(IPAddress ip, uint16_t port)
|
||||
{
|
||||
return connect(ip.toString().c_str(), port);
|
||||
}
|
||||
|
||||
size_t EthernetClient::write(uint8_t b) {
|
||||
size_t EthernetClient::write(uint8_t b)
|
||||
{
|
||||
return write(&b, 1);
|
||||
}
|
||||
|
||||
size_t EthernetClient::write(const uint8_t *buf, size_t size) {
|
||||
size_t EthernetClient::write(const uint8_t *buf, size_t size)
|
||||
{
|
||||
int rc = 0;
|
||||
int bytes = 0;
|
||||
|
||||
@@ -119,17 +125,20 @@ size_t EthernetClient::write(const uint8_t *buf, size_t size) {
|
||||
return bytes;
|
||||
}
|
||||
|
||||
size_t EthernetClient::write(const char *str) {
|
||||
size_t EthernetClient::write(const char *str)
|
||||
{
|
||||
if (str == NULL) {
|
||||
return 0;
|
||||
}
|
||||
return write((const uint8_t *)str, strlen(str));
|
||||
}
|
||||
size_t EthernetClient::write(const char *buffer, size_t size) {
|
||||
size_t EthernetClient::write(const char *buffer, size_t size)
|
||||
{
|
||||
return write((const uint8_t *)buffer, size);
|
||||
}
|
||||
|
||||
int EthernetClient::available() {
|
||||
int EthernetClient::available()
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
if (_sock != -1) {
|
||||
@@ -139,10 +148,10 @@ int EthernetClient::available() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int EthernetClient::read() {
|
||||
uint8_t b;
|
||||
if ( recv(_sock, &b, 1, 0) > 0 )
|
||||
int EthernetClient::read()
|
||||
{
|
||||
uint8_t b;
|
||||
if ( recv(_sock, &b, 1, 0) > 0 ) {
|
||||
// recv worked
|
||||
return b;
|
||||
} else {
|
||||
@@ -151,22 +160,26 @@ int EthernetClient::read() {
|
||||
}
|
||||
}
|
||||
|
||||
int EthernetClient::read(uint8_t *buf, size_t size) {
|
||||
int EthernetClient::read(uint8_t *buf, size_t size)
|
||||
{
|
||||
return recv(_sock, buf, size, 0);
|
||||
}
|
||||
|
||||
int EthernetClient::peek() {
|
||||
int EthernetClient::peek()
|
||||
{
|
||||
uint8_t b;
|
||||
|
||||
return recv(_sock, &b, 1, MSG_PEEK | MSG_DONTWAIT);
|
||||
}
|
||||
|
||||
void EthernetClient::flush() {
|
||||
void EthernetClient::flush()
|
||||
{
|
||||
// There isn't much we can do here
|
||||
return;
|
||||
}
|
||||
|
||||
void EthernetClient::stop() {
|
||||
void EthernetClient::stop()
|
||||
{
|
||||
if (_sock == -1) {
|
||||
return;
|
||||
}
|
||||
@@ -186,7 +199,8 @@ void EthernetClient::stop() {
|
||||
}
|
||||
usleep(1000);
|
||||
gettimeofday(&curTime, NULL);
|
||||
} while (((curTime.tv_sec - startTime.tv_sec) * 1000000) + (curTime.tv_usec - startTime.tv_usec) < 1000000);
|
||||
} while (((curTime.tv_sec - startTime.tv_sec) * 1000000) + (curTime.tv_usec - startTime.tv_usec) <
|
||||
1000000);
|
||||
|
||||
// if it hasn't closed, close it forcefully
|
||||
if (s != ETHERNETCLIENT_W5100_CLOSED) {
|
||||
@@ -195,7 +209,8 @@ void EthernetClient::stop() {
|
||||
_sock = -1;
|
||||
}
|
||||
|
||||
uint8_t EthernetClient::status() {
|
||||
uint8_t EthernetClient::status()
|
||||
{
|
||||
if (_sock == -1) {
|
||||
return ETHERNETCLIENT_W5100_CLOSED;
|
||||
}
|
||||
@@ -203,7 +218,8 @@ uint8_t EthernetClient::status() {
|
||||
struct tcp_info tcp_info;
|
||||
int tcp_info_length = sizeof(tcp_info);
|
||||
|
||||
if ( getsockopt( _sock, SOL_TCP, TCP_INFO, (void *)&tcp_info, (socklen_t *)&tcp_info_length ) == 0 ) {
|
||||
if ( getsockopt( _sock, SOL_TCP, TCP_INFO, (void *)&tcp_info,
|
||||
(socklen_t *)&tcp_info_length ) == 0 ) {
|
||||
switch (tcp_info.tcpi_state) {
|
||||
case TCP_ESTABLISHED:
|
||||
return ETHERNETCLIENT_W5100_ESTABLISHED;
|
||||
@@ -232,7 +248,8 @@ uint8_t EthernetClient::status() {
|
||||
return ETHERNETCLIENT_W5100_CLOSED;
|
||||
}
|
||||
|
||||
uint8_t EthernetClient::connected() {
|
||||
uint8_t EthernetClient::connected()
|
||||
{
|
||||
if (_sock == -1) {
|
||||
return 0;
|
||||
}
|
||||
@@ -246,17 +263,20 @@ uint8_t EthernetClient::connected() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
int EthernetClient::getSocketNumber() {
|
||||
int EthernetClient::getSocketNumber()
|
||||
{
|
||||
return _sock;
|
||||
}
|
||||
|
||||
// the next function allows us to use the client returned by
|
||||
// EthernetServer::available() as the condition in an if-statement.
|
||||
|
||||
EthernetClient::operator bool() {
|
||||
EthernetClient::operator bool()
|
||||
{
|
||||
return _sock != -1;
|
||||
}
|
||||
|
||||
bool EthernetClient::operator==(const EthernetClient& rhs) {
|
||||
bool EthernetClient::operator==(const EthernetClient& rhs)
|
||||
{
|
||||
return _sock == rhs._sock && _sock != -1 && rhs._sock != -1;
|
||||
}
|
||||
|
||||
@@ -40,7 +40,8 @@
|
||||
/**
|
||||
* EthernetClient class
|
||||
*/
|
||||
class EthernetClient : public Client {
|
||||
class EthernetClient : public Client
|
||||
{
|
||||
|
||||
private:
|
||||
int _sock; //!< @brief Network socket.
|
||||
@@ -168,12 +169,18 @@ public:
|
||||
* @brief Overloaded cast operators.
|
||||
*
|
||||
*/
|
||||
virtual bool operator==(const bool value) { return bool() == value; }
|
||||
virtual bool operator==(const bool value)
|
||||
{
|
||||
return bool() == value;
|
||||
}
|
||||
/**
|
||||
* @brief Overloaded cast operators.
|
||||
*
|
||||
*/
|
||||
virtual bool operator!=(const bool value) { return bool() != value; }
|
||||
virtual bool operator!=(const bool value)
|
||||
{
|
||||
return bool() != value;
|
||||
}
|
||||
/**
|
||||
* @brief Overloaded cast operators.
|
||||
*
|
||||
@@ -183,7 +190,10 @@ public:
|
||||
* @brief Overloaded cast operators.
|
||||
*
|
||||
*/
|
||||
virtual bool operator!=(const EthernetClient& rhs) { return !this->operator==(rhs); };
|
||||
virtual bool operator!=(const EthernetClient& rhs)
|
||||
{
|
||||
return !this->operator==(rhs);
|
||||
};
|
||||
|
||||
friend class EthernetServer;
|
||||
};
|
||||
|
||||
@@ -32,7 +32,8 @@
|
||||
#include "EthernetClient.h"
|
||||
#include "EthernetServer.h"
|
||||
|
||||
EthernetServer::EthernetServer(uint16_t port, uint16_t max_clients) : port(port), max_clients(max_clients)
|
||||
EthernetServer::EthernetServer(uint16_t port, uint16_t max_clients) : port(port),
|
||||
max_clients(max_clients)
|
||||
{
|
||||
clients.reserve(max_clients);
|
||||
}
|
||||
|
||||
@@ -39,7 +39,8 @@ class EthernetClient;
|
||||
/**
|
||||
* @brief EthernetServer class
|
||||
*/
|
||||
class EthernetServer : public Server {
|
||||
class EthernetServer : public Server
|
||||
{
|
||||
|
||||
private:
|
||||
uint16_t port; //!< @brief Port number for the network socket.
|
||||
|
||||
+23
-19
@@ -24,53 +24,53 @@
|
||||
#include <cstring>
|
||||
#include "IPAddress.h"
|
||||
|
||||
IPAddress::IPAddress() {
|
||||
IPAddress::IPAddress()
|
||||
{
|
||||
_address.dword = 0;
|
||||
}
|
||||
|
||||
IPAddress::IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet) {
|
||||
IPAddress::IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet,
|
||||
uint8_t fourth_octet)
|
||||
{
|
||||
_address.bytes[0] = first_octet;
|
||||
_address.bytes[1] = second_octet;
|
||||
_address.bytes[2] = third_octet;
|
||||
_address.bytes[3] = fourth_octet;
|
||||
}
|
||||
|
||||
IPAddress::IPAddress(uint32_t address) {
|
||||
IPAddress::IPAddress(uint32_t address)
|
||||
{
|
||||
_address.dword = address;
|
||||
}
|
||||
|
||||
IPAddress::IPAddress(const uint8_t *address) {
|
||||
IPAddress::IPAddress(const uint8_t *address)
|
||||
{
|
||||
memcpy(_address.bytes, address, sizeof(_address.bytes));
|
||||
}
|
||||
|
||||
bool IPAddress::fromString(const char *address) {
|
||||
bool IPAddress::fromString(const char *address)
|
||||
{
|
||||
// TODO: add support for "a", "a.b", "a.b.c" formats
|
||||
|
||||
uint16_t acc = 0; // Accumulator
|
||||
uint8_t dots = 0;
|
||||
|
||||
while (*address)
|
||||
{
|
||||
while (*address) {
|
||||
char c = *address++;
|
||||
if (c >= '0' && c <= '9')
|
||||
{
|
||||
if (c >= '0' && c <= '9') {
|
||||
acc = acc * 10 + (c - '0');
|
||||
if (acc > 255) {
|
||||
// Value out of [0..255] range
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (c == '.')
|
||||
{
|
||||
} else if (c == '.') {
|
||||
if (dots == 3) {
|
||||
// Too much dots (there must be 3 dots)
|
||||
return false;
|
||||
}
|
||||
_address.bytes[dots++] = acc;
|
||||
acc = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
// Invalid char
|
||||
return false;
|
||||
}
|
||||
@@ -84,23 +84,27 @@ bool IPAddress::fromString(const char *address) {
|
||||
return true;
|
||||
}
|
||||
|
||||
IPAddress& IPAddress::operator=(const uint8_t *address) {
|
||||
IPAddress& IPAddress::operator=(const uint8_t *address)
|
||||
{
|
||||
memcpy(_address.bytes, address, sizeof(_address.bytes));
|
||||
return *this;
|
||||
}
|
||||
|
||||
IPAddress& IPAddress::operator=(uint32_t address) {
|
||||
IPAddress& IPAddress::operator=(uint32_t address)
|
||||
{
|
||||
_address.dword = address;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool IPAddress::operator==(const uint8_t* addr) const {
|
||||
bool IPAddress::operator==(const uint8_t* addr) const
|
||||
{
|
||||
return memcmp(addr, _address.bytes, sizeof(_address.bytes)) == 0;
|
||||
}
|
||||
|
||||
std::string IPAddress::toString()
|
||||
{
|
||||
char szRet[16];
|
||||
sprintf(szRet,"%u.%u.%u.%u", _address.bytes[0], _address.bytes[1], _address.bytes[2], _address.bytes[3]);
|
||||
sprintf(szRet,"%u.%u.%u.%u", _address.bytes[0], _address.bytes[1], _address.bytes[2],
|
||||
_address.bytes[3]);
|
||||
return std::string(szRet);
|
||||
}
|
||||
|
||||
@@ -29,7 +29,8 @@
|
||||
/**
|
||||
* @brief A class to make it easier to handle and pass around IP addresses
|
||||
*/
|
||||
class IPAddress {
|
||||
class IPAddress
|
||||
{
|
||||
private:
|
||||
union {
|
||||
uint8_t bytes[4]; //!< IPv4 address as an array
|
||||
@@ -45,7 +46,8 @@ class IPAddress {
|
||||
*
|
||||
* @return pointer to the internal structure.
|
||||
*/
|
||||
uint8_t* raw_address() {
|
||||
uint8_t* raw_address()
|
||||
{
|
||||
return _address.bytes;
|
||||
}
|
||||
|
||||
@@ -86,27 +88,33 @@ class IPAddress {
|
||||
*
|
||||
* @param address to be set.
|
||||
*/
|
||||
bool fromString(const std::string &address) { return fromString(address.c_str()); }
|
||||
bool fromString(const std::string &address)
|
||||
{
|
||||
return fromString(address.c_str());
|
||||
}
|
||||
/**
|
||||
* @brief Overloaded cast operator
|
||||
*
|
||||
* Allow IPAddress objects to be used where a pointer to a four-byte uint8_t array is expected
|
||||
*/
|
||||
operator uint32_t() const {
|
||||
operator uint32_t() const
|
||||
{
|
||||
return _address.dword;
|
||||
}
|
||||
/**
|
||||
* @brief Overloaded cast operator
|
||||
*
|
||||
*/
|
||||
bool operator==(const IPAddress& addr) const {
|
||||
bool operator==(const IPAddress& addr) const
|
||||
{
|
||||
return _address.dword == addr._address.dword;
|
||||
}
|
||||
/**
|
||||
* @brief Overloaded cast operator
|
||||
*
|
||||
*/
|
||||
bool operator==(uint32_t addr) const {
|
||||
bool operator==(uint32_t addr) const
|
||||
{
|
||||
return _address.dword == addr;
|
||||
}
|
||||
/**
|
||||
@@ -120,14 +128,16 @@ class IPAddress {
|
||||
* Allow getting and setting individual octets of the address.
|
||||
*
|
||||
*/
|
||||
uint8_t operator[](int index) const {
|
||||
uint8_t operator[](int index) const
|
||||
{
|
||||
return _address.bytes[index];
|
||||
}
|
||||
/**
|
||||
* @brief Overloaded index operator
|
||||
*
|
||||
*/
|
||||
uint8_t& operator[](int index) {
|
||||
uint8_t& operator[](int index)
|
||||
{
|
||||
return _address.bytes[index];
|
||||
}
|
||||
/**
|
||||
|
||||
+47
-25
@@ -30,7 +30,8 @@
|
||||
|
||||
// Public Methods //////////////////////////////////////////////////////////////
|
||||
|
||||
size_t Print::write(const uint8_t *buffer, size_t size) {
|
||||
size_t Print::write(const uint8_t *buffer, size_t size)
|
||||
{
|
||||
size_t n = 0;
|
||||
while(size--) {
|
||||
n += write(*buffer++);
|
||||
@@ -42,7 +43,8 @@ size_t
|
||||
#ifdef __GNUC__
|
||||
__attribute__((format(printf, 2, 3)))
|
||||
#endif
|
||||
Print::printf(const char *format, ...) {
|
||||
Print::printf(const char *format, ...)
|
||||
{
|
||||
va_list arg;
|
||||
va_start(arg, format);
|
||||
char temp[64];
|
||||
@@ -65,31 +67,38 @@ Print::printf(const char *format, ...) {
|
||||
return len;
|
||||
}
|
||||
|
||||
size_t Print::print(const std::string &s) {
|
||||
size_t Print::print(const std::string &s)
|
||||
{
|
||||
return write(s.c_str(), s.length());
|
||||
}
|
||||
|
||||
size_t Print::print(const char str[]) {
|
||||
size_t Print::print(const char str[])
|
||||
{
|
||||
return write(str);
|
||||
}
|
||||
|
||||
size_t Print::print(char c) {
|
||||
size_t Print::print(char c)
|
||||
{
|
||||
return write(c);
|
||||
}
|
||||
|
||||
size_t Print::print(unsigned char b, int base) {
|
||||
size_t Print::print(unsigned char b, int base)
|
||||
{
|
||||
return print((unsigned long) b, base);
|
||||
}
|
||||
|
||||
size_t Print::print(int n, int base) {
|
||||
size_t Print::print(int n, int base)
|
||||
{
|
||||
return print((long) n, base);
|
||||
}
|
||||
|
||||
size_t Print::print(unsigned int n, int base) {
|
||||
size_t Print::print(unsigned int n, int base)
|
||||
{
|
||||
return print((unsigned long) n, base);
|
||||
}
|
||||
|
||||
size_t Print::print(long n, int base) {
|
||||
size_t Print::print(long n, int base)
|
||||
{
|
||||
if(base == 0) {
|
||||
return write(n);
|
||||
} else if(base == 10) {
|
||||
@@ -104,72 +113,83 @@ size_t Print::print(long n, int base) {
|
||||
}
|
||||
}
|
||||
|
||||
size_t Print::print(unsigned long n, int base) {
|
||||
size_t Print::print(unsigned long n, int base)
|
||||
{
|
||||
if(base == 0) {
|
||||
return write(n);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return printNumber(n, base);
|
||||
}
|
||||
}
|
||||
|
||||
size_t Print::print(double n, int digits) {
|
||||
size_t Print::print(double n, int digits)
|
||||
{
|
||||
return printFloat(n, digits);
|
||||
}
|
||||
|
||||
size_t Print::println(void) {
|
||||
size_t Print::println(void)
|
||||
{
|
||||
return print("\r\n");
|
||||
}
|
||||
|
||||
size_t Print::println(const std::string &s) {
|
||||
size_t Print::println(const std::string &s)
|
||||
{
|
||||
size_t n = print(s);
|
||||
n += println();
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t Print::println(const char c[]) {
|
||||
size_t Print::println(const char c[])
|
||||
{
|
||||
size_t n = print(c);
|
||||
n += println();
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t Print::println(char c) {
|
||||
size_t Print::println(char c)
|
||||
{
|
||||
size_t n = print(c);
|
||||
n += println();
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t Print::println(unsigned char b, int base) {
|
||||
size_t Print::println(unsigned char b, int base)
|
||||
{
|
||||
size_t n = print(b, base);
|
||||
n += println();
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t Print::println(int num, int base) {
|
||||
size_t Print::println(int num, int base)
|
||||
{
|
||||
size_t n = print(num, base);
|
||||
n += println();
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t Print::println(unsigned int num, int base) {
|
||||
size_t Print::println(unsigned int num, int base)
|
||||
{
|
||||
size_t n = print(num, base);
|
||||
n += println();
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t Print::println(long num, int base) {
|
||||
size_t Print::println(long num, int base)
|
||||
{
|
||||
size_t n = print(num, base);
|
||||
n += println();
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t Print::println(unsigned long num, int base) {
|
||||
size_t Print::println(unsigned long num, int base)
|
||||
{
|
||||
size_t n = print(num, base);
|
||||
n += println();
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t Print::println(double num, int digits) {
|
||||
size_t Print::println(double num, int digits)
|
||||
{
|
||||
size_t n = print(num, digits);
|
||||
n += println();
|
||||
return n;
|
||||
@@ -177,7 +197,8 @@ size_t Print::println(double num, int digits) {
|
||||
|
||||
// Private Methods /////////////////////////////////////////////////////////////
|
||||
|
||||
size_t Print::printNumber(unsigned long n, uint8_t base) {
|
||||
size_t Print::printNumber(unsigned long n, uint8_t base)
|
||||
{
|
||||
char buf[8 * sizeof(long) + 1]; // Assumes 8-bit chars plus zero byte.
|
||||
char *str = &buf[sizeof(buf) - 1];
|
||||
|
||||
@@ -198,7 +219,8 @@ size_t Print::printNumber(unsigned long n, uint8_t base) {
|
||||
return write(str);
|
||||
}
|
||||
|
||||
size_t Print::printFloat(double number, uint8_t digits) {
|
||||
size_t Print::printFloat(double number, uint8_t digits)
|
||||
{
|
||||
size_t n = 0;
|
||||
|
||||
if(std::isnan(number)) {
|
||||
|
||||
+20
-7
@@ -32,29 +32,42 @@
|
||||
#define OCT 8
|
||||
#define BIN 2
|
||||
|
||||
class Print {
|
||||
class Print
|
||||
{
|
||||
private:
|
||||
int write_error;
|
||||
size_t printNumber(unsigned long n, uint8_t base);
|
||||
size_t printFloat(double number, uint8_t digits);
|
||||
|
||||
protected:
|
||||
void setWriteError(int err = 1) { write_error = err; }
|
||||
void setWriteError(int err = 1)
|
||||
{
|
||||
write_error = err;
|
||||
}
|
||||
|
||||
public:
|
||||
Print() : write_error(0) {}
|
||||
|
||||
int getWriteError() { return write_error; }
|
||||
void clearWriteError() { setWriteError(0); }
|
||||
int getWriteError()
|
||||
{
|
||||
return write_error;
|
||||
}
|
||||
void clearWriteError()
|
||||
{
|
||||
setWriteError(0);
|
||||
}
|
||||
|
||||
virtual size_t write(uint8_t) = 0;
|
||||
size_t write(const char *str) {
|
||||
if (str == NULL)
|
||||
size_t write(const char *str)
|
||||
{
|
||||
if (str == NULL) {
|
||||
return 0;
|
||||
}
|
||||
return write((const uint8_t *) str, strlen(str));
|
||||
}
|
||||
virtual size_t write(const uint8_t *buffer, size_t size);
|
||||
size_t write(const char *buffer, size_t size) {
|
||||
size_t write(const char *buffer, size_t size)
|
||||
{
|
||||
return write((const uint8_t *) buffer, size);
|
||||
}
|
||||
|
||||
|
||||
@@ -69,7 +69,8 @@ bool SerialPort::open(int bauds)
|
||||
/* create a symlink with predictable name to the PTY device */
|
||||
unlink(serialPort.c_str()); // remove the symlink if it already exists
|
||||
if (symlink(ptsname(sd), serialPort.c_str()) != 0) {
|
||||
logError("Couldn't create a symlink '%s' to PTY! (%d) %s\n", serialPort.c_str(), errno, strerror(errno));
|
||||
logError("Couldn't create a symlink '%s' to PTY! (%d) %s\n", serialPort.c_str(), errno,
|
||||
strerror(errno));
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
@@ -83,23 +84,57 @@ bool SerialPort::open(int bauds)
|
||||
}
|
||||
|
||||
switch (bauds) {
|
||||
case 50: speed = B50 ; break ;
|
||||
case 75: speed = B75 ; break ;
|
||||
case 110: speed = B110 ; break ;
|
||||
case 134: speed = B134 ; break ;
|
||||
case 150: speed = B150 ; break ;
|
||||
case 200: speed = B200 ; break ;
|
||||
case 300: speed = B300 ; break ;
|
||||
case 600: speed = B600 ; break ;
|
||||
case 1200: speed = B1200 ; break ;
|
||||
case 1800: speed = B1800 ; break ;
|
||||
case 2400: speed = B2400 ; break ;
|
||||
case 9600: speed = B9600 ; break ;
|
||||
case 19200: speed = B19200 ; break ;
|
||||
case 38400: speed = B38400 ; break ;
|
||||
case 57600: speed = B57600 ; break ;
|
||||
case 115200: speed = B115200 ; break ;
|
||||
default: speed = B115200 ; break ;
|
||||
case 50:
|
||||
speed = B50 ;
|
||||
break ;
|
||||
case 75:
|
||||
speed = B75 ;
|
||||
break ;
|
||||
case 110:
|
||||
speed = B110 ;
|
||||
break ;
|
||||
case 134:
|
||||
speed = B134 ;
|
||||
break ;
|
||||
case 150:
|
||||
speed = B150 ;
|
||||
break ;
|
||||
case 200:
|
||||
speed = B200 ;
|
||||
break ;
|
||||
case 300:
|
||||
speed = B300 ;
|
||||
break ;
|
||||
case 600:
|
||||
speed = B600 ;
|
||||
break ;
|
||||
case 1200:
|
||||
speed = B1200 ;
|
||||
break ;
|
||||
case 1800:
|
||||
speed = B1800 ;
|
||||
break ;
|
||||
case 2400:
|
||||
speed = B2400 ;
|
||||
break ;
|
||||
case 9600:
|
||||
speed = B9600 ;
|
||||
break ;
|
||||
case 19200:
|
||||
speed = B19200 ;
|
||||
break ;
|
||||
case 38400:
|
||||
speed = B38400 ;
|
||||
break ;
|
||||
case 57600:
|
||||
speed = B57600 ;
|
||||
break ;
|
||||
case 115200:
|
||||
speed = B115200 ;
|
||||
break ;
|
||||
default:
|
||||
speed = B115200 ;
|
||||
break ;
|
||||
}
|
||||
|
||||
// Get the current options of the port
|
||||
|
||||
@@ -28,7 +28,8 @@
|
||||
* SerialPort Class
|
||||
* Class that provides the functionality of arduino Serial library
|
||||
*/
|
||||
class SerialPort : public Stream {
|
||||
class SerialPort : public Stream
|
||||
{
|
||||
|
||||
private:
|
||||
int sd; //!< @brief file descriptor number.
|
||||
|
||||
@@ -23,7 +23,8 @@
|
||||
#include "Print.h"
|
||||
|
||||
#if !DOXYGEN
|
||||
class Server : public Print {
|
||||
class Server : public Print
|
||||
{
|
||||
public:
|
||||
virtual void begin() =0;
|
||||
};
|
||||
|
||||
@@ -52,7 +52,8 @@ SoftEeprom::SoftEeprom(const char *fileName, size_t length)
|
||||
myFile.write((const char*)_values, _length);
|
||||
myFile.close();
|
||||
} else if (fileInfo.st_size < 0 || (size_t)fileInfo.st_size != _length) {
|
||||
logError("Config file %s is not the correct size of %zu. Please remove the file and a new one will be created.\n", _fileName, _length);
|
||||
logError("Config file %s is not the correct size of %zu. Please remove the file and a new one will be created.\n",
|
||||
_fileName, _length);
|
||||
exit(1);
|
||||
} else {
|
||||
//Read config into local memory.
|
||||
|
||||
@@ -30,7 +30,8 @@
|
||||
/**
|
||||
* SoftEeprom class
|
||||
*/
|
||||
class SoftEeprom {
|
||||
class SoftEeprom
|
||||
{
|
||||
|
||||
private:
|
||||
size_t _length; //!< @brief Eeprom max size.
|
||||
|
||||
+37
-27
@@ -28,7 +28,8 @@
|
||||
#define NO_SKIP_CHAR 1 // a magic char not found in a valid ASCII numeric field
|
||||
|
||||
// private method to read stream with timeout
|
||||
int Stream::timedRead() {
|
||||
int Stream::timedRead()
|
||||
{
|
||||
int c;
|
||||
_startMillis = millis();
|
||||
do {
|
||||
@@ -42,7 +43,8 @@ int Stream::timedRead() {
|
||||
}
|
||||
|
||||
// private method to peek stream with timeout
|
||||
int Stream::timedPeek() {
|
||||
int Stream::timedPeek()
|
||||
{
|
||||
int c;
|
||||
_startMillis = millis();
|
||||
do {
|
||||
@@ -57,7 +59,8 @@ int Stream::timedPeek() {
|
||||
|
||||
// returns peek of the next digit in the stream or -1 if timeout
|
||||
// discards non-numeric characters
|
||||
int Stream::peekNextDigit() {
|
||||
int Stream::peekNextDigit()
|
||||
{
|
||||
int c;
|
||||
while(1) {
|
||||
c = timedPeek();
|
||||
@@ -83,25 +86,30 @@ void Stream::setTimeout(unsigned long timeout) // sets the maximum number of mi
|
||||
}
|
||||
|
||||
// find returns true if the target string is found
|
||||
bool Stream::find(const char *target) {
|
||||
bool Stream::find(const char *target)
|
||||
{
|
||||
return findUntil(target, (char*) "");
|
||||
}
|
||||
|
||||
// reads data from the stream until the target string of given length is found
|
||||
// returns true if target string is found, false if timed out
|
||||
bool Stream::find(const char *target, size_t length) {
|
||||
bool Stream::find(const char *target, size_t length)
|
||||
{
|
||||
return findUntil(target, length, NULL, 0);
|
||||
}
|
||||
|
||||
// as find but search ends if the terminator string is found
|
||||
bool Stream::findUntil(const char *target, const char *terminator) {
|
||||
bool Stream::findUntil(const char *target, const char *terminator)
|
||||
{
|
||||
return findUntil(target, strlen(target), terminator, strlen(terminator));
|
||||
}
|
||||
|
||||
// reads data from the stream until the target string of the given length is found
|
||||
// search terminated if the terminator string is found
|
||||
// returns true if target string is found, false if terminated or timed out
|
||||
bool Stream::findUntil(const char *target, size_t targetLen, const char *terminator, size_t termLen) {
|
||||
bool Stream::findUntil(const char *target, size_t targetLen, const char *terminator,
|
||||
size_t termLen)
|
||||
{
|
||||
size_t index = 0; // maximum target string length is 64k bytes!
|
||||
size_t termIndex = 0;
|
||||
int c;
|
||||
@@ -135,13 +143,15 @@ bool Stream::findUntil(const char *target, size_t targetLen, const char *termina
|
||||
// returns the first valid (long) integer value from the current position.
|
||||
// initial characters that are not digits (or the minus sign) are skipped
|
||||
// function is terminated by the first character that is not a digit.
|
||||
long Stream::parseInt() {
|
||||
long Stream::parseInt()
|
||||
{
|
||||
return parseInt(NO_SKIP_CHAR); // terminate on first non-digit character (or timeout)
|
||||
}
|
||||
|
||||
// as above but a given skipChar is ignored
|
||||
// this allows format characters (typically commas) in values to be ignored
|
||||
long Stream::parseInt(char skipChar) {
|
||||
long Stream::parseInt(char skipChar)
|
||||
{
|
||||
boolean isNegative = false;
|
||||
long value = 0;
|
||||
int c;
|
||||
@@ -155,11 +165,9 @@ long Stream::parseInt(char skipChar) {
|
||||
do {
|
||||
if(c == skipChar) {
|
||||
// ignore this charactor
|
||||
}
|
||||
else if(c == '-') {
|
||||
} else if(c == '-') {
|
||||
isNegative = true;
|
||||
}
|
||||
else if(c >= '0' && c <= '9') { // is c a digit?
|
||||
} else if(c >= '0' && c <= '9') { // is c a digit?
|
||||
value = value * 10 + c - '0';
|
||||
}
|
||||
read(); // consume the character we got with peek
|
||||
@@ -173,13 +181,15 @@ long Stream::parseInt(char skipChar) {
|
||||
}
|
||||
|
||||
// as parseInt but returns a floating point value
|
||||
float Stream::parseFloat() {
|
||||
float Stream::parseFloat()
|
||||
{
|
||||
return parseFloat(NO_SKIP_CHAR);
|
||||
}
|
||||
|
||||
// as above but the given skipChar is ignored
|
||||
// this allows format characters (typically commas) in values to be ignored
|
||||
float Stream::parseFloat(char skipChar) {
|
||||
float Stream::parseFloat(char skipChar)
|
||||
{
|
||||
boolean isNegative = false;
|
||||
boolean isFraction = false;
|
||||
long value = 0;
|
||||
@@ -195,14 +205,11 @@ float Stream::parseFloat(char skipChar) {
|
||||
do {
|
||||
if(c == skipChar) {
|
||||
// ignore
|
||||
}
|
||||
else if(c == '-') {
|
||||
} else if(c == '-') {
|
||||
isNegative = true;
|
||||
}
|
||||
else if(c == '.') {
|
||||
} else if(c == '.') {
|
||||
isFraction = true;
|
||||
}
|
||||
else if(c >= '0' && c <= '9') { // is c a digit?
|
||||
} else if(c >= '0' && c <= '9') { // is c a digit?
|
||||
value = value * 10 + c - '0';
|
||||
if(isFraction) {
|
||||
fraction *= 0.1;
|
||||
@@ -217,8 +224,7 @@ float Stream::parseFloat(char skipChar) {
|
||||
}
|
||||
if(isFraction) {
|
||||
return value * fraction;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
@@ -228,7 +234,8 @@ float Stream::parseFloat(char skipChar) {
|
||||
// returns the number of characters placed in the buffer
|
||||
// the buffer is NOT null terminated.
|
||||
//
|
||||
size_t Stream::readBytes(char *buffer, size_t length) {
|
||||
size_t Stream::readBytes(char *buffer, size_t length)
|
||||
{
|
||||
size_t count = 0;
|
||||
while(count < length) {
|
||||
int c = timedRead();
|
||||
@@ -245,7 +252,8 @@ size_t Stream::readBytes(char *buffer, size_t length) {
|
||||
// terminates if length characters have been read, timeout, or if the terminator character detected
|
||||
// returns the number of characters placed in the buffer (0 means no valid data found)
|
||||
|
||||
size_t Stream::readBytesUntil(char terminator, char *buffer, size_t length) {
|
||||
size_t Stream::readBytesUntil(char terminator, char *buffer, size_t length)
|
||||
{
|
||||
if(length < 1) {
|
||||
return 0;
|
||||
}
|
||||
@@ -261,7 +269,8 @@ size_t Stream::readBytesUntil(char terminator, char *buffer, size_t length) {
|
||||
return index; // return number of characters, not including null terminator
|
||||
}
|
||||
|
||||
std::string Stream::readString() {
|
||||
std::string Stream::readString()
|
||||
{
|
||||
std::string ret;
|
||||
int c = timedRead();
|
||||
while(c >= 0) {
|
||||
@@ -271,7 +280,8 @@ std::string Stream::readString() {
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::string Stream::readStringUntil(char terminator) {
|
||||
std::string Stream::readStringUntil(char terminator)
|
||||
{
|
||||
std::string ret;
|
||||
int c = timedRead();
|
||||
while(c >= 0 && c != terminator) {
|
||||
|
||||
+32
-15
@@ -38,9 +38,11 @@
|
||||
*/
|
||||
|
||||
#if !DOXYGEN
|
||||
class Stream: public Print {
|
||||
class Stream: public Print
|
||||
{
|
||||
protected:
|
||||
unsigned long _timeout; // number of milliseconds to wait for the next char before aborting timed read
|
||||
unsigned long
|
||||
_timeout; // number of milliseconds to wait for the next char before aborting timed read
|
||||
unsigned long _startMillis; // used for timeout measurement
|
||||
int timedRead(); // private method to read stream with timeout
|
||||
int timedPeek(); // private method to peek stream with timeout
|
||||
@@ -52,35 +54,47 @@ class Stream: public Print {
|
||||
virtual int peek() = 0;
|
||||
virtual void flush() = 0;
|
||||
|
||||
Stream() {
|
||||
Stream()
|
||||
{
|
||||
_timeout = 1000;
|
||||
}
|
||||
|
||||
// parsing methods
|
||||
|
||||
void setTimeout(unsigned long timeout); // sets maximum milliseconds to wait for stream data, default is 1 second
|
||||
void setTimeout(unsigned long
|
||||
timeout); // sets maximum milliseconds to wait for stream data, default is 1 second
|
||||
|
||||
bool find(const char *target); // reads data from the stream until the target string is found
|
||||
bool find(uint8_t *target) {
|
||||
bool find(uint8_t *target)
|
||||
{
|
||||
return find((char *) target);
|
||||
}
|
||||
// returns true if target string is found, false if timed out (see setTimeout)
|
||||
|
||||
bool find(const char *target, size_t length); // reads data from the stream until the target string of given length is found
|
||||
bool find(const uint8_t *target, size_t length) {
|
||||
bool find(const char *target, size_t
|
||||
length); // reads data from the stream until the target string of given length is found
|
||||
bool find(const uint8_t *target, size_t length)
|
||||
{
|
||||
return find((char *) target, length);
|
||||
}
|
||||
// returns true if target string is found, false if timed out
|
||||
|
||||
bool find(char target) { return find (&target, 1); }
|
||||
bool find(char target)
|
||||
{
|
||||
return find (&target, 1);
|
||||
}
|
||||
|
||||
bool findUntil(const char *target, const char *terminator); // as find but search ends if the terminator string is found
|
||||
bool findUntil(const uint8_t *target, const char *terminator) {
|
||||
bool findUntil(const char *target,
|
||||
const char *terminator); // as find but search ends if the terminator string is found
|
||||
bool findUntil(const uint8_t *target, const char *terminator)
|
||||
{
|
||||
return findUntil((char *) target, terminator);
|
||||
}
|
||||
|
||||
bool findUntil(const char *target, size_t targetLen, const char *terminate, size_t termLen); // as above but search ends if the terminate string is found
|
||||
bool findUntil(const uint8_t *target, size_t targetLen, const char *terminate, size_t termLen) {
|
||||
bool findUntil(const char *target, size_t targetLen, const char *terminate,
|
||||
size_t termLen); // as above but search ends if the terminate string is found
|
||||
bool findUntil(const uint8_t *target, size_t targetLen, const char *terminate, size_t termLen)
|
||||
{
|
||||
return findUntil((char *) target, targetLen, terminate, termLen);
|
||||
}
|
||||
|
||||
@@ -91,14 +105,17 @@ class Stream: public Print {
|
||||
float parseFloat(); // float version of parseInt
|
||||
|
||||
virtual size_t readBytes(char *buffer, size_t length); // read chars from stream into buffer
|
||||
virtual size_t readBytes(uint8_t *buffer, size_t length) {
|
||||
virtual size_t readBytes(uint8_t *buffer, size_t length)
|
||||
{
|
||||
return readBytes((char *) buffer, length);
|
||||
}
|
||||
// terminates if length characters have been read or timeout (see setTimeout)
|
||||
// returns the number of characters placed in the buffer (0 means no valid data found)
|
||||
|
||||
size_t readBytesUntil(char terminator, char *buffer, size_t length); // as readBytes with terminator character
|
||||
size_t readBytesUntil(char terminator, uint8_t *buffer, size_t length) {
|
||||
size_t readBytesUntil(char terminator, char *buffer,
|
||||
size_t length); // as readBytes with terminator character
|
||||
size_t readBytesUntil(char terminator, uint8_t *buffer, size_t length)
|
||||
{
|
||||
return readBytesUntil(terminator, (char *) buffer, length);
|
||||
}
|
||||
// terminates if length characters have been read, timeout, or if the terminator character detected
|
||||
|
||||
@@ -23,7 +23,8 @@
|
||||
#include <math.h>
|
||||
#include "stdlib_noniso.h"
|
||||
|
||||
char* utoa(unsigned value, char* result, int base) {
|
||||
char* utoa(unsigned value, char* result, int base)
|
||||
{
|
||||
if(base < 2 || base > 16) {
|
||||
*result = 0;
|
||||
return result;
|
||||
@@ -44,7 +45,8 @@ char* utoa(unsigned value, char* result, int base) {
|
||||
return result;
|
||||
}
|
||||
|
||||
char* itoa(int value, char* result, int base) {
|
||||
char* itoa(int value, char* result, int base)
|
||||
{
|
||||
if(base < 2 || base > 16) {
|
||||
*result = 0;
|
||||
return result;
|
||||
@@ -70,21 +72,25 @@ char* itoa(int value, char* result, int base) {
|
||||
return result;
|
||||
}
|
||||
|
||||
int atoi(const char* s) {
|
||||
int atoi(const char* s)
|
||||
{
|
||||
return (int) atol(s);
|
||||
}
|
||||
|
||||
long atol(const char* s) {
|
||||
long atol(const char* s)
|
||||
{
|
||||
char * tmp;
|
||||
return strtol(s, &tmp, 10);
|
||||
}
|
||||
|
||||
double atof(const char* s) {
|
||||
double atof(const char* s)
|
||||
{
|
||||
char * tmp;
|
||||
return strtod(s, &tmp);
|
||||
}
|
||||
|
||||
void reverse(char* begin, char* end) {
|
||||
void reverse(char* begin, char* end)
|
||||
{
|
||||
char *is = begin;
|
||||
char *ie = end - 1;
|
||||
while(is < ie) {
|
||||
@@ -96,7 +102,8 @@ void reverse(char* begin, char* end) {
|
||||
}
|
||||
}
|
||||
|
||||
char* ltoa(long value, char* result, int base) {
|
||||
char* ltoa(long value, char* result, int base)
|
||||
{
|
||||
if(base < 2 || base > 16) {
|
||||
*result = 0;
|
||||
return result;
|
||||
@@ -122,7 +129,8 @@ char* ltoa(long value, char* result, int base) {
|
||||
return result;
|
||||
}
|
||||
|
||||
char* ultoa(unsigned long value, char* result, int base) {
|
||||
char* ultoa(unsigned long value, char* result, int base)
|
||||
{
|
||||
if(base < 2 || base > 16) {
|
||||
*result = 0;
|
||||
return result;
|
||||
@@ -143,7 +151,8 @@ char* ultoa(unsigned long value, char* result, int base) {
|
||||
return result;
|
||||
}
|
||||
|
||||
char* dtostrf (double val, signed char width, unsigned char prec, char *s) {
|
||||
char* dtostrf (double val, signed char width, unsigned char prec, char *s)
|
||||
{
|
||||
sprintf(s,"%*.*f", width, prec, val);
|
||||
return s;
|
||||
}
|
||||
|
||||
@@ -7,39 +7,46 @@
|
||||
#include "PubSubClient.h"
|
||||
#include "Arduino.h"
|
||||
|
||||
PubSubClient::PubSubClient() {
|
||||
PubSubClient::PubSubClient()
|
||||
{
|
||||
this->_state = MQTT_DISCONNECTED;
|
||||
this->_client = NULL;
|
||||
this->stream = NULL;
|
||||
setCallback(NULL);
|
||||
}
|
||||
|
||||
PubSubClient::PubSubClient(Client& client) {
|
||||
PubSubClient::PubSubClient(Client& client)
|
||||
{
|
||||
this->_state = MQTT_DISCONNECTED;
|
||||
setClient(client);
|
||||
this->stream = NULL;
|
||||
}
|
||||
|
||||
PubSubClient::PubSubClient(IPAddress addr, uint16_t port, Client& client) {
|
||||
PubSubClient::PubSubClient(IPAddress addr, uint16_t port, Client& client)
|
||||
{
|
||||
this->_state = MQTT_DISCONNECTED;
|
||||
setServer(addr, port);
|
||||
setClient(client);
|
||||
this->stream = NULL;
|
||||
}
|
||||
PubSubClient::PubSubClient(IPAddress addr, uint16_t port, Client& client, Stream& stream) {
|
||||
PubSubClient::PubSubClient(IPAddress addr, uint16_t port, Client& client, Stream& stream)
|
||||
{
|
||||
this->_state = MQTT_DISCONNECTED;
|
||||
setServer(addr,port);
|
||||
setClient(client);
|
||||
setStream(stream);
|
||||
}
|
||||
PubSubClient::PubSubClient(IPAddress addr, uint16_t port, MQTT_CALLBACK_SIGNATURE, Client& client) {
|
||||
PubSubClient::PubSubClient(IPAddress addr, uint16_t port, MQTT_CALLBACK_SIGNATURE, Client& client)
|
||||
{
|
||||
this->_state = MQTT_DISCONNECTED;
|
||||
setServer(addr, port);
|
||||
setCallback(callback);
|
||||
setClient(client);
|
||||
this->stream = NULL;
|
||||
}
|
||||
PubSubClient::PubSubClient(IPAddress addr, uint16_t port, MQTT_CALLBACK_SIGNATURE, Client& client, Stream& stream) {
|
||||
PubSubClient::PubSubClient(IPAddress addr, uint16_t port, MQTT_CALLBACK_SIGNATURE, Client& client,
|
||||
Stream& stream)
|
||||
{
|
||||
this->_state = MQTT_DISCONNECTED;
|
||||
setServer(addr,port);
|
||||
setCallback(callback);
|
||||
@@ -47,26 +54,31 @@ PubSubClient::PubSubClient(IPAddress addr, uint16_t port, MQTT_CALLBACK_SIGNATUR
|
||||
setStream(stream);
|
||||
}
|
||||
|
||||
PubSubClient::PubSubClient(uint8_t *ip, uint16_t port, Client& client) {
|
||||
PubSubClient::PubSubClient(uint8_t *ip, uint16_t port, Client& client)
|
||||
{
|
||||
this->_state = MQTT_DISCONNECTED;
|
||||
setServer(ip, port);
|
||||
setClient(client);
|
||||
this->stream = NULL;
|
||||
}
|
||||
PubSubClient::PubSubClient(uint8_t *ip, uint16_t port, Client& client, Stream& stream) {
|
||||
PubSubClient::PubSubClient(uint8_t *ip, uint16_t port, Client& client, Stream& stream)
|
||||
{
|
||||
this->_state = MQTT_DISCONNECTED;
|
||||
setServer(ip,port);
|
||||
setClient(client);
|
||||
setStream(stream);
|
||||
}
|
||||
PubSubClient::PubSubClient(uint8_t *ip, uint16_t port, MQTT_CALLBACK_SIGNATURE, Client& client) {
|
||||
PubSubClient::PubSubClient(uint8_t *ip, uint16_t port, MQTT_CALLBACK_SIGNATURE, Client& client)
|
||||
{
|
||||
this->_state = MQTT_DISCONNECTED;
|
||||
setServer(ip, port);
|
||||
setCallback(callback);
|
||||
setClient(client);
|
||||
this->stream = NULL;
|
||||
}
|
||||
PubSubClient::PubSubClient(uint8_t *ip, uint16_t port, MQTT_CALLBACK_SIGNATURE, Client& client, Stream& stream) {
|
||||
PubSubClient::PubSubClient(uint8_t *ip, uint16_t port, MQTT_CALLBACK_SIGNATURE, Client& client,
|
||||
Stream& stream)
|
||||
{
|
||||
this->_state = MQTT_DISCONNECTED;
|
||||
setServer(ip,port);
|
||||
setCallback(callback);
|
||||
@@ -74,26 +86,32 @@ PubSubClient::PubSubClient(uint8_t *ip, uint16_t port, MQTT_CALLBACK_SIGNATURE,
|
||||
setStream(stream);
|
||||
}
|
||||
|
||||
PubSubClient::PubSubClient(const char* domain, uint16_t port, Client& client) {
|
||||
PubSubClient::PubSubClient(const char* domain, uint16_t port, Client& client)
|
||||
{
|
||||
this->_state = MQTT_DISCONNECTED;
|
||||
setServer(domain,port);
|
||||
setClient(client);
|
||||
this->stream = NULL;
|
||||
}
|
||||
PubSubClient::PubSubClient(const char* domain, uint16_t port, Client& client, Stream& stream) {
|
||||
PubSubClient::PubSubClient(const char* domain, uint16_t port, Client& client, Stream& stream)
|
||||
{
|
||||
this->_state = MQTT_DISCONNECTED;
|
||||
setServer(domain,port);
|
||||
setClient(client);
|
||||
setStream(stream);
|
||||
}
|
||||
PubSubClient::PubSubClient(const char* domain, uint16_t port, MQTT_CALLBACK_SIGNATURE, Client& client) {
|
||||
PubSubClient::PubSubClient(const char* domain, uint16_t port, MQTT_CALLBACK_SIGNATURE,
|
||||
Client& client)
|
||||
{
|
||||
this->_state = MQTT_DISCONNECTED;
|
||||
setServer(domain,port);
|
||||
setCallback(callback);
|
||||
setClient(client);
|
||||
this->stream = NULL;
|
||||
}
|
||||
PubSubClient::PubSubClient(const char* domain, uint16_t port, MQTT_CALLBACK_SIGNATURE, Client& client, Stream& stream) {
|
||||
PubSubClient::PubSubClient(const char* domain, uint16_t port, MQTT_CALLBACK_SIGNATURE,
|
||||
Client& client, Stream& stream)
|
||||
{
|
||||
this->_state = MQTT_DISCONNECTED;
|
||||
setServer(domain,port);
|
||||
setCallback(callback);
|
||||
@@ -101,19 +119,25 @@ PubSubClient::PubSubClient(const char* domain, uint16_t port, MQTT_CALLBACK_SIGN
|
||||
setStream(stream);
|
||||
}
|
||||
|
||||
boolean PubSubClient::connect(const char *id) {
|
||||
boolean PubSubClient::connect(const char *id)
|
||||
{
|
||||
return connect(id,NULL,NULL,0,0,0,0);
|
||||
}
|
||||
|
||||
boolean PubSubClient::connect(const char *id, const char *user, const char *pass) {
|
||||
boolean PubSubClient::connect(const char *id, const char *user, const char *pass)
|
||||
{
|
||||
return connect(id,user,pass,0,0,0,0);
|
||||
}
|
||||
|
||||
boolean PubSubClient::connect(const char *id, const char* willTopic, uint8_t willQos, boolean willRetain, const char* willMessage) {
|
||||
boolean PubSubClient::connect(const char *id, const char* willTopic, uint8_t willQos,
|
||||
boolean willRetain, const char* willMessage)
|
||||
{
|
||||
return connect(id,NULL,NULL,willTopic,willQos,willRetain,willMessage);
|
||||
}
|
||||
|
||||
boolean PubSubClient::connect(const char *id, const char *user, const char *pass, const char* willTopic, uint8_t willQos, boolean willRetain, const char* willMessage) {
|
||||
boolean PubSubClient::connect(const char *id, const char *user, const char *pass,
|
||||
const char* willTopic, uint8_t willQos, boolean willRetain, const char* willMessage)
|
||||
{
|
||||
if (!connected()) {
|
||||
int result = 0;
|
||||
|
||||
@@ -206,7 +230,8 @@ boolean PubSubClient::connect(const char *id, const char *user, const char *pass
|
||||
}
|
||||
|
||||
// reads a byte into result
|
||||
boolean PubSubClient::readByte(uint8_t * result) {
|
||||
boolean PubSubClient::readByte(uint8_t * result)
|
||||
{
|
||||
uint32_t previousMillis = millis();
|
||||
while(!_client->available()) {
|
||||
uint32_t currentMillis = millis();
|
||||
@@ -219,7 +244,8 @@ boolean PubSubClient::readByte(uint8_t * result) {
|
||||
}
|
||||
|
||||
// reads a byte into result[*index] and increments index
|
||||
boolean PubSubClient::readByte(uint8_t * result, uint16_t * index){
|
||||
boolean PubSubClient::readByte(uint8_t * result, uint16_t * index)
|
||||
{
|
||||
uint16_t current_index = *index;
|
||||
uint8_t * write_address = &(result[current_index]);
|
||||
if(readByte(write_address)) {
|
||||
@@ -229,7 +255,8 @@ boolean PubSubClient::readByte(uint8_t * result, uint16_t * index){
|
||||
return false;
|
||||
}
|
||||
|
||||
uint16_t PubSubClient::readPacket(uint8_t* lengthLength) {
|
||||
uint16_t PubSubClient::readPacket(uint8_t* lengthLength)
|
||||
{
|
||||
uint16_t len = 0;
|
||||
if(!readByte(buffer, &len)) {
|
||||
return 0;
|
||||
@@ -289,7 +316,8 @@ uint16_t PubSubClient::readPacket(uint8_t* lengthLength) {
|
||||
return len;
|
||||
}
|
||||
|
||||
boolean PubSubClient::loop() {
|
||||
boolean PubSubClient::loop()
|
||||
{
|
||||
if (connected()) {
|
||||
unsigned long t = millis();
|
||||
if ((t - lastInActivity > MQTT_KEEPALIVE*1000UL) || (t - lastOutActivity > MQTT_KEEPALIVE*1000UL)) {
|
||||
@@ -354,19 +382,24 @@ boolean PubSubClient::loop() {
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean PubSubClient::publish(const char* topic, const char* payload) {
|
||||
boolean PubSubClient::publish(const char* topic, const char* payload)
|
||||
{
|
||||
return publish(topic,(const uint8_t*)payload,strlen(payload),false);
|
||||
}
|
||||
|
||||
boolean PubSubClient::publish(const char* topic, const char* payload, boolean retained) {
|
||||
boolean PubSubClient::publish(const char* topic, const char* payload, boolean retained)
|
||||
{
|
||||
return publish(topic,(const uint8_t*)payload,strlen(payload),retained);
|
||||
}
|
||||
|
||||
boolean PubSubClient::publish(const char* topic, const uint8_t* payload, unsigned int plength) {
|
||||
boolean PubSubClient::publish(const char* topic, const uint8_t* payload, unsigned int plength)
|
||||
{
|
||||
return publish(topic, payload, plength, false);
|
||||
}
|
||||
|
||||
boolean PubSubClient::publish(const char* topic, const uint8_t* payload, unsigned int plength, boolean retained) {
|
||||
boolean PubSubClient::publish(const char* topic, const uint8_t* payload, unsigned int plength,
|
||||
boolean retained)
|
||||
{
|
||||
if (connected()) {
|
||||
if (MQTT_MAX_PACKET_SIZE < 5 + 2+strlen(topic) + plength) {
|
||||
// Too long
|
||||
@@ -388,7 +421,9 @@ boolean PubSubClient::publish(const char* topic, const uint8_t* payload, unsigne
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean PubSubClient::publish_P(const char* topic, const uint8_t* payload, unsigned int plength, boolean retained) {
|
||||
boolean PubSubClient::publish_P(const char* topic, const uint8_t* payload, unsigned int plength,
|
||||
boolean retained)
|
||||
{
|
||||
uint8_t llen = 0;
|
||||
uint8_t digit;
|
||||
unsigned int rc = 0;
|
||||
@@ -433,7 +468,8 @@ boolean PubSubClient::publish_P(const char* topic, const uint8_t* payload, unsig
|
||||
return rc == tlen + 4 + plength;
|
||||
}
|
||||
|
||||
boolean PubSubClient::write(uint8_t header, uint8_t* buf, uint16_t length) {
|
||||
boolean PubSubClient::write(uint8_t header, uint8_t* buf, uint16_t length)
|
||||
{
|
||||
uint8_t lenBuf[4];
|
||||
uint8_t llen = 0;
|
||||
uint8_t digit;
|
||||
@@ -475,11 +511,13 @@ boolean PubSubClient::write(uint8_t header, uint8_t* buf, uint16_t length) {
|
||||
#endif
|
||||
}
|
||||
|
||||
boolean PubSubClient::subscribe(const char* topic) {
|
||||
boolean PubSubClient::subscribe(const char* topic)
|
||||
{
|
||||
return subscribe(topic, 0);
|
||||
}
|
||||
|
||||
boolean PubSubClient::subscribe(const char* topic, uint8_t qos) {
|
||||
boolean PubSubClient::subscribe(const char* topic, uint8_t qos)
|
||||
{
|
||||
// original: if (qos < 0 || qos > 1) { (qos is uint8_t, hence qos < 0 impossible, tekka)
|
||||
if (qos > 1) {
|
||||
return false;
|
||||
@@ -504,7 +542,8 @@ boolean PubSubClient::subscribe(const char* topic, uint8_t qos) {
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean PubSubClient::unsubscribe(const char* topic) {
|
||||
boolean PubSubClient::unsubscribe(const char* topic)
|
||||
{
|
||||
if (MQTT_MAX_PACKET_SIZE < 9 + strlen(topic)) {
|
||||
// Too long
|
||||
return false;
|
||||
@@ -523,7 +562,8 @@ boolean PubSubClient::unsubscribe(const char* topic) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void PubSubClient::disconnect() {
|
||||
void PubSubClient::disconnect()
|
||||
{
|
||||
buffer[0] = MQTTDISCONNECT;
|
||||
buffer[1] = 0;
|
||||
_client->write(buffer,2);
|
||||
@@ -532,7 +572,8 @@ void PubSubClient::disconnect() {
|
||||
lastInActivity = lastOutActivity = millis();
|
||||
}
|
||||
|
||||
uint16_t PubSubClient::writeString(const char* string, uint8_t* buf, uint16_t pos) {
|
||||
uint16_t PubSubClient::writeString(const char* string, uint8_t* buf, uint16_t pos)
|
||||
{
|
||||
const char* idp = string;
|
||||
uint16_t i = 0;
|
||||
pos += 2;
|
||||
@@ -546,7 +587,8 @@ uint16_t PubSubClient::writeString(const char* string, uint8_t* buf, uint16_t po
|
||||
}
|
||||
|
||||
|
||||
boolean PubSubClient::connected() {
|
||||
boolean PubSubClient::connected()
|
||||
{
|
||||
boolean rc;
|
||||
if (_client == NULL ) {
|
||||
rc = false;
|
||||
@@ -563,39 +605,46 @@ boolean PubSubClient::connected() {
|
||||
return rc;
|
||||
}
|
||||
|
||||
PubSubClient& PubSubClient::setServer(uint8_t * ip, uint16_t port) {
|
||||
PubSubClient& PubSubClient::setServer(uint8_t * ip, uint16_t port)
|
||||
{
|
||||
IPAddress addr(ip[0],ip[1],ip[2],ip[3]);
|
||||
return setServer(addr,port);
|
||||
}
|
||||
|
||||
PubSubClient& PubSubClient::setServer(IPAddress ip, uint16_t port) {
|
||||
PubSubClient& PubSubClient::setServer(IPAddress ip, uint16_t port)
|
||||
{
|
||||
this->ip = ip;
|
||||
this->port = port;
|
||||
this->domain = NULL;
|
||||
return *this;
|
||||
}
|
||||
|
||||
PubSubClient& PubSubClient::setServer(const char * domain, uint16_t port) {
|
||||
PubSubClient& PubSubClient::setServer(const char * domain, uint16_t port)
|
||||
{
|
||||
this->domain = domain;
|
||||
this->port = port;
|
||||
return *this;
|
||||
}
|
||||
|
||||
PubSubClient& PubSubClient::setCallback(MQTT_CALLBACK_SIGNATURE) {
|
||||
PubSubClient& PubSubClient::setCallback(MQTT_CALLBACK_SIGNATURE)
|
||||
{
|
||||
this->callback = callback;
|
||||
return *this;
|
||||
}
|
||||
|
||||
PubSubClient& PubSubClient::setClient(Client& client){
|
||||
PubSubClient& PubSubClient::setClient(Client& client)
|
||||
{
|
||||
this->_client = &client;
|
||||
return *this;
|
||||
}
|
||||
|
||||
PubSubClient& PubSubClient::setStream(Stream& stream){
|
||||
PubSubClient& PubSubClient::setStream(Stream& stream)
|
||||
{
|
||||
this->stream = &stream;
|
||||
return *this;
|
||||
}
|
||||
|
||||
int PubSubClient::state() {
|
||||
int PubSubClient::state()
|
||||
{
|
||||
return this->_state;
|
||||
}
|
||||
|
||||
@@ -81,7 +81,8 @@
|
||||
#endif
|
||||
|
||||
/** PubSubClient class */
|
||||
class PubSubClient {
|
||||
class PubSubClient
|
||||
{
|
||||
private:
|
||||
Client* _client;
|
||||
uint8_t buffer[MQTT_MAX_PACKET_SIZE];
|
||||
@@ -106,15 +107,18 @@ public:
|
||||
PubSubClient(IPAddress, uint16_t, Client& client); //!< PubSubClient
|
||||
PubSubClient(IPAddress, uint16_t, Client& client, Stream&); //!< PubSubClient
|
||||
PubSubClient(IPAddress, uint16_t, MQTT_CALLBACK_SIGNATURE,Client& client); //!< PubSubClient
|
||||
PubSubClient(IPAddress, uint16_t, MQTT_CALLBACK_SIGNATURE,Client& client, Stream&); //!< PubSubClient
|
||||
PubSubClient(IPAddress, uint16_t, MQTT_CALLBACK_SIGNATURE,Client& client,
|
||||
Stream&); //!< PubSubClient
|
||||
PubSubClient(uint8_t *, uint16_t, Client& client); //!< PubSubClient
|
||||
PubSubClient(uint8_t *, uint16_t, Client& client, Stream&); //!< PubSubClient
|
||||
PubSubClient(uint8_t *, uint16_t, MQTT_CALLBACK_SIGNATURE,Client& client); //!< PubSubClient
|
||||
PubSubClient(uint8_t *, uint16_t, MQTT_CALLBACK_SIGNATURE,Client& client, Stream&); //!< PubSubClient
|
||||
PubSubClient(uint8_t *, uint16_t, MQTT_CALLBACK_SIGNATURE,Client& client,
|
||||
Stream&); //!< PubSubClient
|
||||
PubSubClient(const char*, uint16_t, Client& client); //!< PubSubClient
|
||||
PubSubClient(const char*, uint16_t, Client& client, Stream&); //!< PubSubClient
|
||||
PubSubClient(const char*, uint16_t, MQTT_CALLBACK_SIGNATURE,Client& client); //!< PubSubClient
|
||||
PubSubClient(const char*, uint16_t, MQTT_CALLBACK_SIGNATURE,Client& client, Stream&); //!< PubSubClient
|
||||
PubSubClient(const char*, uint16_t, MQTT_CALLBACK_SIGNATURE,Client& client,
|
||||
Stream&); //!< PubSubClient
|
||||
|
||||
PubSubClient& setServer(IPAddress ip, uint16_t port); //!< setServer
|
||||
PubSubClient& setServer(uint8_t * ip, uint16_t port); //!< setServer
|
||||
@@ -125,14 +129,18 @@ public:
|
||||
|
||||
boolean connect(const char* id); //!< connect
|
||||
boolean connect(const char* id, const char* user, const char* pass); //!< connect
|
||||
boolean connect(const char* id, const char* willTopic, uint8_t willQos, boolean willRetain, const char* willMessage); //!< connect
|
||||
boolean connect(const char* id, const char* user, const char* pass, const char* willTopic, uint8_t willQos, boolean willRetain, const char* willMessage); //!< connect
|
||||
boolean connect(const char* id, const char* willTopic, uint8_t willQos, boolean willRetain,
|
||||
const char* willMessage); //!< connect
|
||||
boolean connect(const char* id, const char* user, const char* pass, const char* willTopic,
|
||||
uint8_t willQos, boolean willRetain, const char* willMessage); //!< connect
|
||||
void disconnect(); //!< disconnect
|
||||
boolean publish(const char* topic, const char* payload); //!< publish
|
||||
boolean publish(const char* topic, const char* payload, boolean retained); //!< publish
|
||||
boolean publish(const char* topic, const uint8_t * payload, unsigned int plength); //!< publish
|
||||
boolean publish(const char* topic, const uint8_t * payload, unsigned int plength, boolean retained); //!< publish
|
||||
boolean publish_P(const char* topic, const uint8_t * payload, unsigned int plength, boolean retained); //!< publish_P
|
||||
boolean publish(const char* topic, const uint8_t * payload, unsigned int plength,
|
||||
boolean retained); //!< publish
|
||||
boolean publish_P(const char* topic, const uint8_t * payload, unsigned int plength,
|
||||
boolean retained); //!< publish_P
|
||||
boolean subscribe(const char* topic); //!< subscribe
|
||||
boolean subscribe(const char* topic, uint8_t qos); //!< subscribe
|
||||
boolean unsubscribe(const char* topic); //!< unsubscribe
|
||||
|
||||
+10
-5
@@ -44,12 +44,14 @@ LOCAL void RF24_ce(const bool level)
|
||||
hwDigitalWrite(MY_RF24_CE_PIN, level);
|
||||
}
|
||||
|
||||
LOCAL uint8_t RF24_spiMultiByteTransfer(const uint8_t cmd, uint8_t* buf, uint8_t len, const bool aReadMode)
|
||||
LOCAL uint8_t RF24_spiMultiByteTransfer(const uint8_t cmd, uint8_t* buf, uint8_t len,
|
||||
const bool aReadMode)
|
||||
{
|
||||
uint8_t status;
|
||||
uint8_t* current = buf;
|
||||
#if !defined(MY_SOFTSPI)
|
||||
_SPI.beginTransaction(SPISettings(MY_RF24_SPI_MAX_SPEED, MY_RF24_SPI_DATA_ORDER, MY_RF24_SPI_DATA_MODE));
|
||||
_SPI.beginTransaction(SPISettings(MY_RF24_SPI_MAX_SPEED, MY_RF24_SPI_DATA_ORDER,
|
||||
MY_RF24_SPI_DATA_MODE));
|
||||
#endif
|
||||
RF24_csn(LOW);
|
||||
// timing
|
||||
@@ -261,7 +263,8 @@ LOCAL bool RF24_sendMessage(const uint8_t recipient, const void* buf, const uint
|
||||
RF24_flushTX();
|
||||
// this command is affected in clones (e.g. Si24R1): flipped NoACK bit when using W_TX_PAYLOAD_NO_ACK / W_TX_PAYLOAD
|
||||
// AutoACK is disabled on the broadcasting pipe - NO_ACK prevents resending
|
||||
RF24_spiMultiByteTransfer(recipient == BROADCAST_ADDRESS ? RF24_WRITE_TX_PAYLOAD_NO_ACK : RF24_WRITE_TX_PAYLOAD, (uint8_t*)buf, len, false );
|
||||
RF24_spiMultiByteTransfer(recipient == BROADCAST_ADDRESS ? RF24_WRITE_TX_PAYLOAD_NO_ACK :
|
||||
RF24_WRITE_TX_PAYLOAD, (uint8_t*)buf, len, false );
|
||||
// go, TX starts after ~10us
|
||||
RF24_ce(HIGH);
|
||||
// timeout counter to detect HW issues
|
||||
@@ -331,7 +334,8 @@ LOCAL uint8_t RF24_getNodeID(void)
|
||||
LOCAL bool RF24_sanityCheck(void)
|
||||
{
|
||||
// detect HW defect, configuration errors or interrupted SPI line, CE disconnect cannot be detected
|
||||
return (RF24_readByteRegister(RF24_RF_SETUP) == MY_RF24_RF_SETUP) & (RF24_readByteRegister(RF24_RF_CH) == MY_RF24_CHANNEL);
|
||||
return (RF24_readByteRegister(RF24_RF_SETUP) == MY_RF24_RF_SETUP) & (RF24_readByteRegister(
|
||||
RF24_RF_CH) == MY_RF24_CHANNEL);
|
||||
}
|
||||
|
||||
#if defined(MY_RX_MESSAGE_BUFFER_FEATURE)
|
||||
@@ -427,7 +431,8 @@ LOCAL bool RF24_initialize(void)
|
||||
RF24_setDynamicPayload(_BV(RF24_DPL_P0 + RF24_BROADCAST_PIPE) | _BV(RF24_DPL_P0));
|
||||
// listen to broadcast pipe
|
||||
MY_RF24_BASE_ADDR[0] = BROADCAST_ADDRESS;
|
||||
RF24_setPipeAddress(RF24_RX_ADDR_P0 + RF24_BROADCAST_PIPE, (uint8_t*)&MY_RF24_BASE_ADDR, RF24_BROADCAST_PIPE > 1 ? 1 : MY_RF24_ADDR_WIDTH);
|
||||
RF24_setPipeAddress(RF24_RX_ADDR_P0 + RF24_BROADCAST_PIPE, (uint8_t*)&MY_RF24_BASE_ADDR,
|
||||
RF24_BROADCAST_PIPE > 1 ? 1 : MY_RF24_ADDR_WIDTH);
|
||||
// pipe 0, set full address, later only LSB is updated
|
||||
RF24_setPipeAddress(RF24_RX_ADDR_P0, (uint8_t*)&MY_RF24_BASE_ADDR, MY_RF24_ADDR_WIDTH);
|
||||
RF24_setPipeAddress(RF24_TX_ADDR, (uint8_t*)&MY_RF24_BASE_ADDR, MY_RF24_ADDR_WIDTH);
|
||||
|
||||
+4
-2
@@ -36,7 +36,8 @@
|
||||
#if defined (ARDUINO) && !defined (__arm__) && !defined (_SPI)
|
||||
#include <SPI.h>
|
||||
#if defined(MY_SOFTSPI)
|
||||
SoftSPI<MY_SOFT_SPI_MISO_PIN, MY_SOFT_SPI_MOSI_PIN, MY_SOFT_SPI_SCK_PIN, MY_RF24_SPI_DATA_MODE> _SPI;
|
||||
SoftSPI<MY_SOFT_SPI_MISO_PIN, MY_SOFT_SPI_MOSI_PIN, MY_SOFT_SPI_SCK_PIN, MY_RF24_SPI_DATA_MODE>
|
||||
_SPI;
|
||||
#else
|
||||
#define _SPI SPI
|
||||
#endif
|
||||
@@ -234,7 +235,8 @@
|
||||
|
||||
LOCAL void RF24_csn(const bool level);
|
||||
LOCAL void RF24_ce(const bool level);
|
||||
LOCAL uint8_t RF24_spiMultiByteTransfer(const uint8_t cmd, uint8_t* buf, const uint8_t len, const bool aReadMode);
|
||||
LOCAL uint8_t RF24_spiMultiByteTransfer(const uint8_t cmd, uint8_t* buf, const uint8_t len,
|
||||
const bool aReadMode);
|
||||
LOCAL uint8_t RF24_spiByteTransfer(const uint8_t cmd);
|
||||
LOCAL uint8_t RF24_RAW_readByteRegister(const uint8_t cmd);
|
||||
LOCAL uint8_t RF24_RAW_writeByteRegister(const uint8_t cmd, const uint8_t value);
|
||||
|
||||
+91
-68
@@ -39,14 +39,15 @@ volatile uint8_t RFM69::SENDERID;
|
||||
volatile uint8_t RFM69::TARGETID; // should match _address
|
||||
volatile uint8_t RFM69::PAYLOADLEN;
|
||||
volatile uint8_t RFM69::ACK_REQUESTED;
|
||||
volatile uint8_t RFM69::ACK_RECEIVED; // should be polled immediately after sending a packet with ACK request
|
||||
volatile int16_t RFM69::RSSI; // most accurate RSSI during reception (closest to the reception)
|
||||
volatile uint8_t
|
||||
RFM69::ACK_RECEIVED; // should be polled immediately after sending a packet with ACK request
|
||||
volatile int16_t
|
||||
RFM69::RSSI; // most accurate RSSI during reception (closest to the reception)
|
||||
RFM69* RFM69::selfPointer;
|
||||
|
||||
bool RFM69::initialize(uint8_t freqBand, uint8_t nodeID, uint8_t networkID)
|
||||
{
|
||||
const uint8_t CONFIG[][2] =
|
||||
{
|
||||
const uint8_t CONFIG[][2] = {
|
||||
/* 0x01 */ { REG_OPMODE, RF_OPMODE_SEQUENCER_ON | RF_OPMODE_LISTEN_OFF | RF_OPMODE_STANDBY },
|
||||
/* 0x02 */ { REG_DATAMODUL, RF_DATAMODUL_DATAMODE_PACKET | RF_DATAMODUL_MODULATIONTYPE_FSK | RF_DATAMODUL_MODULATIONSHAPING_00 }, // no shaping
|
||||
/* 0x03 */ { REG_BITRATEMSB, RF_BITRATEMSB_55555}, // default: 4.8 KBPS
|
||||
@@ -129,7 +130,8 @@ bool RFM69::initialize(uint8_t freqBand, uint8_t nodeID, uint8_t networkID)
|
||||
// return the frequency (in Hz)
|
||||
uint32_t RFM69::getFrequency()
|
||||
{
|
||||
return RF69_FSTEP * (((uint32_t) readReg(REG_FRFMSB) << 16) + ((uint16_t) readReg(REG_FRFMID) << 8) + readReg(REG_FRFLSB));
|
||||
return RF69_FSTEP * (((uint32_t) readReg(REG_FRFMSB) << 16) + ((uint16_t) readReg(
|
||||
REG_FRFMID) << 8) + readReg(REG_FRFLSB));
|
||||
}
|
||||
|
||||
// set the frequency (in Hz)
|
||||
@@ -183,13 +185,15 @@ void RFM69::setMode(uint8_t newMode)
|
||||
|
||||
// we are using packet mode, so this check is not really needed
|
||||
// but waiting for mode ready is necessary when going from sleep because the FIFO may not be immediately available from previous mode
|
||||
while (_mode == RF69_MODE_SLEEP && (readReg(REG_IRQFLAGS1) & RF_IRQFLAGS1_MODEREADY) == 0x00); // wait for ModeReady
|
||||
while (_mode == RF69_MODE_SLEEP &&
|
||||
(readReg(REG_IRQFLAGS1) & RF_IRQFLAGS1_MODEREADY) == 0x00); // wait for ModeReady
|
||||
|
||||
_mode = newMode;
|
||||
}
|
||||
|
||||
//put transceiver in sleep mode to save battery - to wake or resume receiving just call receiveDone()
|
||||
void RFM69::sleep() {
|
||||
void RFM69::sleep()
|
||||
{
|
||||
setMode(RF69_MODE_SLEEP);
|
||||
}
|
||||
|
||||
@@ -224,8 +228,8 @@ void RFM69::setPowerLevel(uint8_t powerLevel)
|
||||
|
||||
bool RFM69::canSend()
|
||||
{
|
||||
if (_mode == RF69_MODE_RX && PAYLOADLEN == 0 && readRSSI() < CSMA_LIMIT) // if signal stronger than -100dBm is detected assume channel activity
|
||||
{
|
||||
if (_mode == RF69_MODE_RX && PAYLOADLEN == 0 &&
|
||||
readRSSI() < CSMA_LIMIT) { // if signal stronger than -100dBm is detected assume channel activity
|
||||
setMode(RF69_MODE_STANDBY);
|
||||
return true;
|
||||
}
|
||||
@@ -234,7 +238,8 @@ bool RFM69::canSend()
|
||||
|
||||
void RFM69::send(uint8_t toAddress, const void* buffer, uint8_t bufferSize, bool requestACK)
|
||||
{
|
||||
writeReg(REG_PACKETCONFIG2, (readReg(REG_PACKETCONFIG2) & 0xFB) | RF_PACKET2_RXRESTART); // avoid RX deadlocks
|
||||
writeReg(REG_PACKETCONFIG2, (readReg(REG_PACKETCONFIG2) & 0xFB) |
|
||||
RF_PACKET2_RXRESTART); // avoid RX deadlocks
|
||||
uint32_t now = millis();
|
||||
while (!canSend() && millis() - now < RF69_CSMA_LIMIT_MS) {
|
||||
receiveDone();
|
||||
@@ -248,16 +253,15 @@ void RFM69::send(uint8_t toAddress, const void* buffer, uint8_t bufferSize, bool
|
||||
// The reason for the semi-automaton is that the lib is interrupt driven and
|
||||
// requires user action to read the received data and decide what to do with it
|
||||
// replies usually take only 5..8ms at 50kbps@915MHz
|
||||
bool RFM69::sendWithRetry(uint8_t toAddress, const void* buffer, uint8_t bufferSize, uint8_t retries, uint8_t retryWaitTime) {
|
||||
uint32_t sentTime;
|
||||
for (uint8_t i = 0; i <= retries; i++)
|
||||
bool RFM69::sendWithRetry(uint8_t toAddress, const void* buffer, uint8_t bufferSize,
|
||||
uint8_t retries, uint8_t retryWaitTime)
|
||||
{
|
||||
uint32_t sentTime;
|
||||
for (uint8_t i = 0; i <= retries; i++) {
|
||||
send(toAddress, buffer, bufferSize, true);
|
||||
sentTime = millis();
|
||||
while (millis() - sentTime < retryWaitTime)
|
||||
{
|
||||
if (ACKReceived(toAddress))
|
||||
{
|
||||
while (millis() - sentTime < retryWaitTime) {
|
||||
if (ACKReceived(toAddress)) {
|
||||
//Serial.print(" ~ms:"); Serial.print(millis() - sentTime);
|
||||
return true;
|
||||
}
|
||||
@@ -268,7 +272,8 @@ bool RFM69::sendWithRetry(uint8_t toAddress, const void* buffer, uint8_t bufferS
|
||||
}
|
||||
|
||||
// should be polled immediately after sending a packet with ACK request
|
||||
bool RFM69::ACKReceived(uint8_t fromNodeID) {
|
||||
bool RFM69::ACKReceived(uint8_t fromNodeID)
|
||||
{
|
||||
if (receiveDone()) {
|
||||
return (SENDERID == fromNodeID || fromNodeID == RF69_BROADCAST_ADDR) && ACK_RECEIVED;
|
||||
}
|
||||
@@ -276,16 +281,20 @@ bool RFM69::ACKReceived(uint8_t fromNodeID) {
|
||||
}
|
||||
|
||||
// check whether an ACK was requested in the last received packet (non-broadcasted packet)
|
||||
bool RFM69::ACKRequested() {
|
||||
bool RFM69::ACKRequested()
|
||||
{
|
||||
return ACK_REQUESTED && (TARGETID != RF69_BROADCAST_ADDR);
|
||||
}
|
||||
|
||||
// should be called immediately after reception in case sender wants ACK
|
||||
void RFM69::sendACK(const void* buffer, uint8_t bufferSize) {
|
||||
ACK_REQUESTED = 0; // TWS added to make sure we don't end up in a timing race and infinite loop sending Acks
|
||||
void RFM69::sendACK(const void* buffer, uint8_t bufferSize)
|
||||
{
|
||||
ACK_REQUESTED =
|
||||
0; // TWS added to make sure we don't end up in a timing race and infinite loop sending Acks
|
||||
uint8_t sender = SENDERID;
|
||||
int16_t _RSSI = RSSI; // save payload received RSSI value
|
||||
writeReg(REG_PACKETCONFIG2, (readReg(REG_PACKETCONFIG2) & 0xFB) | RF_PACKET2_RXRESTART); // avoid RX deadlocks
|
||||
writeReg(REG_PACKETCONFIG2, (readReg(REG_PACKETCONFIG2) & 0xFB) |
|
||||
RF_PACKET2_RXRESTART); // avoid RX deadlocks
|
||||
uint32_t now = millis();
|
||||
while (!canSend() && millis() - now < RF69_CSMA_LIMIT_MS) {
|
||||
receiveDone();
|
||||
@@ -296,12 +305,14 @@ void RFM69::sendACK(const void* buffer, uint8_t bufferSize) {
|
||||
RSSI = _RSSI; // restore payload RSSI
|
||||
}
|
||||
|
||||
void RFM69::interruptHook(uint8_t CTLbyte) {
|
||||
void RFM69::interruptHook(uint8_t CTLbyte)
|
||||
{
|
||||
(void)CTLbyte;
|
||||
};
|
||||
|
||||
// internal function
|
||||
void RFM69::sendFrame(uint8_t toAddress, const void* buffer, uint8_t bufferSize, bool requestACK, bool sendACK)
|
||||
void RFM69::sendFrame(uint8_t toAddress, const void* buffer, uint8_t bufferSize, bool requestACK,
|
||||
bool sendACK)
|
||||
{
|
||||
setMode(RF69_MODE_STANDBY); // turn off receiver to prevent reception while filling fifo
|
||||
while ((readReg(REG_IRQFLAGS1) & RF_IRQFLAGS1_MODEREADY) == 0x00) {} // wait for ModeReady
|
||||
@@ -314,8 +325,7 @@ void RFM69::sendFrame(uint8_t toAddress, const void* buffer, uint8_t bufferSize,
|
||||
uint8_t CTLbyte = 0x00;
|
||||
if (sendACK) {
|
||||
CTLbyte = RFM69_CTL_SENDACK;
|
||||
}
|
||||
else if (requestACK) {
|
||||
} else if (requestACK) {
|
||||
CTLbyte = RFM69_CTL_REQACK;
|
||||
}
|
||||
|
||||
@@ -335,17 +345,18 @@ void RFM69::sendFrame(uint8_t toAddress, const void* buffer, uint8_t bufferSize,
|
||||
// no need to wait for transmit mode to be ready since its handled by the radio
|
||||
setMode(RF69_MODE_TX);
|
||||
uint32_t txStart = millis();
|
||||
while (hwDigitalRead(_interruptPin) == 0 && millis() - txStart < RF69_TX_LIMIT_MS) {} // wait for DIO0 to turn HIGH signalling transmission finish
|
||||
while (hwDigitalRead(_interruptPin) == 0 &&
|
||||
millis() - txStart < RF69_TX_LIMIT_MS) {} // wait for DIO0 to turn HIGH signalling transmission finish
|
||||
//while (readReg(REG_IRQFLAGS2) & RF_IRQFLAGS2_PACKETSENT == 0x00); // wait for ModeReady
|
||||
setMode(RF69_MODE_STANDBY);
|
||||
}
|
||||
|
||||
// internal function - interrupt gets called when a packet is received
|
||||
void RFM69::interruptHandler() {
|
||||
void RFM69::interruptHandler()
|
||||
{
|
||||
//hwPinMode(4, OUTPUT);
|
||||
//hwDigitalWrite(4, 1);
|
||||
if (_mode == RF69_MODE_RX && (readReg(REG_IRQFLAGS2) & RF_IRQFLAGS2_PAYLOADREADY))
|
||||
{
|
||||
if (_mode == RF69_MODE_RX && (readReg(REG_IRQFLAGS2) & RF_IRQFLAGS2_PAYLOADREADY)) {
|
||||
//RSSI = readRSSI();
|
||||
setMode(RF69_MODE_STANDBY);
|
||||
select();
|
||||
@@ -353,9 +364,10 @@ void RFM69::interruptHandler() {
|
||||
PAYLOADLEN = SPI.transfer(0);
|
||||
PAYLOADLEN = PAYLOADLEN > 66 ? 66 : PAYLOADLEN; // precaution
|
||||
TARGETID = SPI.transfer(0);
|
||||
if(!(_promiscuousMode || TARGETID == _address || TARGETID == RF69_BROADCAST_ADDR) // match this node's address, or broadcast address or anything in promiscuous mode
|
||||
|| PAYLOADLEN < 3) // address situation could receive packets that are malformed and don't fit this libraries extra fields
|
||||
{
|
||||
if(!(_promiscuousMode || TARGETID == _address ||
|
||||
TARGETID == RF69_BROADCAST_ADDR) // match this node's address, or broadcast address or anything in promiscuous mode
|
||||
|| PAYLOADLEN <
|
||||
3) { // address situation could receive packets that are malformed and don't fit this libraries extra fields
|
||||
PAYLOADLEN = 0;
|
||||
unselect();
|
||||
receiveBegin();
|
||||
@@ -372,8 +384,7 @@ void RFM69::interruptHandler() {
|
||||
|
||||
interruptHook(CTLbyte); // TWS: hook to derived class interrupt function
|
||||
|
||||
for (uint8_t i = 0; i < DATALEN; i++)
|
||||
{
|
||||
for (uint8_t i = 0; i < DATALEN; i++) {
|
||||
DATA[i] = SPI.transfer(0);
|
||||
}
|
||||
if (DATALEN < RF69_MAX_DATA_LEN) {
|
||||
@@ -387,10 +398,14 @@ void RFM69::interruptHandler() {
|
||||
}
|
||||
|
||||
// internal function
|
||||
void RFM69::isr0() { selfPointer->interruptHandler(); }
|
||||
void RFM69::isr0()
|
||||
{
|
||||
selfPointer->interruptHandler();
|
||||
}
|
||||
|
||||
// internal function
|
||||
void RFM69::receiveBegin() {
|
||||
void RFM69::receiveBegin()
|
||||
{
|
||||
DATALEN = 0;
|
||||
SENDERID = 0;
|
||||
TARGETID = 0;
|
||||
@@ -399,24 +414,23 @@ void RFM69::receiveBegin() {
|
||||
ACK_RECEIVED = 0;
|
||||
RSSI = 0;
|
||||
if (readReg(REG_IRQFLAGS2) & RF_IRQFLAGS2_PAYLOADREADY) {
|
||||
writeReg(REG_PACKETCONFIG2, (readReg(REG_PACKETCONFIG2) & 0xFB) | RF_PACKET2_RXRESTART); // avoid RX deadlocks
|
||||
writeReg(REG_PACKETCONFIG2, (readReg(REG_PACKETCONFIG2) & 0xFB) |
|
||||
RF_PACKET2_RXRESTART); // avoid RX deadlocks
|
||||
}
|
||||
writeReg(REG_DIOMAPPING1, RF_DIOMAPPING1_DIO0_01); // set DIO0 to "PAYLOADREADY" in receive mode
|
||||
setMode(RF69_MODE_RX);
|
||||
}
|
||||
|
||||
// checks if a packet was received and/or puts transceiver in receive (ie RX or listen) mode
|
||||
bool RFM69::receiveDone() {
|
||||
bool RFM69::receiveDone()
|
||||
{
|
||||
//ATOMIC_BLOCK(ATOMIC_FORCEON)
|
||||
//{
|
||||
noInterrupts(); // re-enabled in unselect() via setMode() or via receiveBegin()
|
||||
if (_mode == RF69_MODE_RX && PAYLOADLEN > 0)
|
||||
{
|
||||
if (_mode == RF69_MODE_RX && PAYLOADLEN > 0) {
|
||||
setMode(RF69_MODE_STANDBY); // enables interrupts
|
||||
return true;
|
||||
}
|
||||
else if (_mode == RF69_MODE_RX) // already in RX no payload yet
|
||||
{
|
||||
} else if (_mode == RF69_MODE_RX) { // already in RX no payload yet
|
||||
interrupts(); // explicitly re-enable interrupts
|
||||
return false;
|
||||
}
|
||||
@@ -428,10 +442,10 @@ bool RFM69::receiveDone() {
|
||||
// To enable encryption: radio.encrypt("ABCDEFGHIJKLMNOP");
|
||||
// To disable encryption: radio.encrypt(null) or radio.encrypt(0)
|
||||
// KEY HAS TO BE 16 bytes !!!
|
||||
void RFM69::encrypt(const char* key) {
|
||||
setMode(RF69_MODE_STANDBY);
|
||||
if (key != 0)
|
||||
void RFM69::encrypt(const char* key)
|
||||
{
|
||||
setMode(RF69_MODE_STANDBY);
|
||||
if (key != 0) {
|
||||
select();
|
||||
SPI.transfer(REG_AESKEY1 | 0x80);
|
||||
for (uint8_t i = 0; i < 16; i++) {
|
||||
@@ -443,10 +457,10 @@ void RFM69::encrypt(const char* key) {
|
||||
}
|
||||
|
||||
// get the received signal strength indicator (RSSI)
|
||||
int16_t RFM69::readRSSI(bool forceTrigger) {
|
||||
int16_t rssi = 0;
|
||||
if (forceTrigger)
|
||||
int16_t RFM69::readRSSI(bool forceTrigger)
|
||||
{
|
||||
int16_t rssi = 0;
|
||||
if (forceTrigger) {
|
||||
// RSSI trigger not needed if DAGC is in continuous mode
|
||||
writeReg(REG_RSSICONFIG, RF_RSSI_START);
|
||||
while ((readReg(REG_RSSICONFIG) & RF_RSSI_DONE) == 0x00) {} // wait for RSSI_Ready
|
||||
@@ -474,7 +488,8 @@ void RFM69::writeReg(uint8_t addr, uint8_t value)
|
||||
}
|
||||
|
||||
// select the RFM69 transceiver (save SPI settings, set CS low)
|
||||
void RFM69::select() {
|
||||
void RFM69::select()
|
||||
{
|
||||
noInterrupts();
|
||||
#if defined (SPCR) && defined (SPSR)
|
||||
// save current SPI settings
|
||||
@@ -484,12 +499,14 @@ void RFM69::select() {
|
||||
// set RFM69 SPI settings
|
||||
SPI.setDataMode(SPI_MODE0);
|
||||
SPI.setBitOrder(MSBFIRST);
|
||||
SPI.setClockDivider(SPI_CLOCK_DIV4); // decided to slow down from DIV2 after SPI stalling in some instances, especially visible on mega1284p when RFM69 and FLASH chip both present
|
||||
SPI.setClockDivider(
|
||||
SPI_CLOCK_DIV4); // decided to slow down from DIV2 after SPI stalling in some instances, especially visible on mega1284p when RFM69 and FLASH chip both present
|
||||
hwDigitalWrite(_slaveSelectPin, LOW);
|
||||
}
|
||||
|
||||
// unselect the RFM69 transceiver (set CS high, restore SPI settings)
|
||||
void RFM69::unselect() {
|
||||
void RFM69::unselect()
|
||||
{
|
||||
hwDigitalWrite(_slaveSelectPin, HIGH);
|
||||
// restore SPI settings to what they were before talking to RFM69
|
||||
#if defined (SPCR) && defined (SPSR)
|
||||
@@ -501,31 +518,36 @@ void RFM69::unselect() {
|
||||
|
||||
// true = disable filtering to capture all frames on network
|
||||
// false = enable node/broadcast filtering to capture only frames sent to this/broadcast address
|
||||
void RFM69::promiscuous(bool onOff) {
|
||||
void RFM69::promiscuous(bool onOff)
|
||||
{
|
||||
_promiscuousMode = onOff;
|
||||
//writeReg(REG_PACKETCONFIG1, (readReg(REG_PACKETCONFIG1) & 0xF9) | (onOff ? RF_PACKET1_ADRSFILTERING_OFF : RF_PACKET1_ADRSFILTERING_NODEBROADCAST));
|
||||
}
|
||||
|
||||
// for RFM69HW only: you must call setHighPower(true) after initialize() or else transmission won't work
|
||||
void RFM69::setHighPower(bool onOff) {
|
||||
void RFM69::setHighPower(bool onOff)
|
||||
{
|
||||
_isRFM69HW = onOff;
|
||||
writeReg(REG_OCP, _isRFM69HW ? RF_OCP_OFF : RF_OCP_ON);
|
||||
if (_isRFM69HW) { // turning ON
|
||||
writeReg(REG_PALEVEL, (readReg(REG_PALEVEL) & 0x1F) | RF_PALEVEL_PA1_ON | RF_PALEVEL_PA2_ON); // enable P1 & P2 amplifier stages
|
||||
}
|
||||
else {
|
||||
writeReg(REG_PALEVEL, RF_PALEVEL_PA0_ON | RF_PALEVEL_PA1_OFF | RF_PALEVEL_PA2_OFF | _powerLevel); // enable P0 only
|
||||
writeReg(REG_PALEVEL, (readReg(REG_PALEVEL) & 0x1F) | RF_PALEVEL_PA1_ON |
|
||||
RF_PALEVEL_PA2_ON); // enable P1 & P2 amplifier stages
|
||||
} else {
|
||||
writeReg(REG_PALEVEL, RF_PALEVEL_PA0_ON | RF_PALEVEL_PA1_OFF | RF_PALEVEL_PA2_OFF |
|
||||
_powerLevel); // enable P0 only
|
||||
}
|
||||
}
|
||||
|
||||
// internal function
|
||||
void RFM69::setHighPowerRegs(bool onOff) {
|
||||
void RFM69::setHighPowerRegs(bool onOff)
|
||||
{
|
||||
writeReg(REG_TESTPA1, onOff ? 0x5D : 0x55);
|
||||
writeReg(REG_TESTPA2, onOff ? 0x7C : 0x70);
|
||||
}
|
||||
|
||||
// set the slave select (CS) pin
|
||||
void RFM69::setCS(uint8_t newSPISlaveSelect) {
|
||||
void RFM69::setCS(uint8_t newSPISlaveSelect)
|
||||
{
|
||||
_slaveSelectPin = newSPISlaveSelect;
|
||||
hwDigitalWrite(_slaveSelectPin, HIGH);
|
||||
hwPinMode(_slaveSelectPin, OUTPUT);
|
||||
@@ -537,11 +559,13 @@ void RFM69::setCS(uint8_t newSPISlaveSelect) {
|
||||
// SERIAL PRINT
|
||||
// replace Serial.print("string") with SerialPrint("string")
|
||||
#define SerialPrint(x) SerialPrint_P(PSTR(x))
|
||||
void SerialWrite ( uint8_t c ) {
|
||||
void SerialWrite ( uint8_t c )
|
||||
{
|
||||
Serial.write ( c );
|
||||
}
|
||||
|
||||
void SerialPrint_P(PGM_P str, void (*f)(uint8_t) = SerialWrite ) {
|
||||
void SerialPrint_P(PGM_P str, void (*f)(uint8_t) = SerialWrite )
|
||||
{
|
||||
for (uint8_t c; (c = pgm_read_byte(str)); str++) {
|
||||
(*f)(c);
|
||||
}
|
||||
@@ -563,8 +587,7 @@ void RFM69::readAllRegs()
|
||||
#endif
|
||||
|
||||
Serial.println("Address - HEX - BIN");
|
||||
for (uint8_t regAddr = 1; regAddr <= 0x4F; regAddr++)
|
||||
{
|
||||
for (uint8_t regAddr = 1; regAddr <= 0x4F; regAddr++) {
|
||||
select();
|
||||
SPI.transfer(regAddr & 0x7F); // send address + r/w bit
|
||||
regVal = SPI.transfer(0);
|
||||
@@ -577,8 +600,7 @@ void RFM69::readAllRegs()
|
||||
Serial.println(regVal,BIN);
|
||||
|
||||
#if REGISTER_DETAIL
|
||||
switch ( regAddr )
|
||||
{
|
||||
switch ( regAddr ) {
|
||||
case 0x1 : {
|
||||
SerialPrint ( "Controls the automatic Sequencer ( see section 4.2 )\nSequencerOff : " );
|
||||
if ( 0x80 & regVal ) {
|
||||
@@ -820,7 +842,8 @@ uint8_t RFM69::readTemperature(uint8_t calFactor) // returns centigrade
|
||||
setMode(RF69_MODE_STANDBY);
|
||||
writeReg(REG_TEMP1, RF_TEMP1_MEAS_START);
|
||||
while ((readReg(REG_TEMP1) & RF_TEMP1_MEAS_RUNNING)) {}
|
||||
return ~readReg(REG_TEMP2) + COURSE_TEMP_COEF + calFactor; // 'complement' corrects the slope, rising temp = rising val
|
||||
return ~readReg(REG_TEMP2) + COURSE_TEMP_COEF +
|
||||
calFactor; // 'complement' corrects the slope, rising temp = rising val
|
||||
} // COURSE_TEMP_COEF puts reading in the ballpark, user can add additional correction
|
||||
|
||||
void RFM69::rcCalibration()
|
||||
|
||||
+24
-7
@@ -79,7 +79,8 @@
|
||||
#define RFM69_CTL_REQACK 0x40
|
||||
|
||||
/** RFM69 class */
|
||||
class RFM69 {
|
||||
class RFM69
|
||||
{
|
||||
public:
|
||||
static volatile uint8_t DATA[RF69_MAX_DATA_LEN]; //!< recv/xmit buf, including hdr & crc bytes
|
||||
static volatile uint8_t DATALEN; //!< DATALEN
|
||||
@@ -87,11 +88,22 @@ class RFM69 {
|
||||
static volatile uint8_t TARGETID; //!< should match _address
|
||||
static volatile uint8_t PAYLOADLEN; //!< PAYLOADLEN
|
||||
static volatile uint8_t ACK_REQUESTED; //!< ACK_REQUESTED
|
||||
static volatile uint8_t ACK_RECEIVED; //!< Should be polled immediately after sending a packet with ACK requestwith ACK request
|
||||
static volatile uint8_t
|
||||
ACK_RECEIVED; //!< Should be polled immediately after sending a packet with ACK requestwith ACK request
|
||||
static volatile int16_t RSSI; //!< most accurate RSSI during reception (closest to the reception)
|
||||
static volatile uint8_t _mode; //!< should be protected?
|
||||
|
||||
RFM69(uint8_t slaveSelectPin=RF69_SPI_CS, uint8_t interruptPin=RF69_IRQ_PIN, bool isRFM69HW=false, uint8_t interruptNum=RF69_IRQ_NUM) { //!< Constructor
|
||||
/**
|
||||
* @brief Constructor
|
||||
*
|
||||
* @param slaveSelectPin ChipSelect pin.
|
||||
* @param interruptPin Interrupt pin.
|
||||
* @param isRFM69HW Set to @c true to indicate RFM69HW variant.
|
||||
* @param interruptNum Interrupt number.
|
||||
*/
|
||||
RFM69(uint8_t slaveSelectPin=RF69_SPI_CS, uint8_t interruptPin=RF69_IRQ_PIN, bool isRFM69HW=false,
|
||||
uint8_t interruptNum=RF69_IRQ_NUM)
|
||||
{
|
||||
_slaveSelectPin = slaveSelectPin;
|
||||
_interruptPin = interruptPin;
|
||||
_interruptNum = interruptNum;
|
||||
@@ -105,8 +117,11 @@ class RFM69 {
|
||||
void setAddress(uint8_t addr); //!< setAddress
|
||||
void setNetwork(uint8_t networkID); //!< setNetwork
|
||||
bool canSend(); //!< canSend
|
||||
virtual void send(uint8_t toAddress, const void* buffer, uint8_t bufferSize, bool requestACK=false); //!< send
|
||||
virtual bool sendWithRetry(uint8_t toAddress, const void* buffer, uint8_t bufferSize, uint8_t retries=2, uint8_t retryWaitTime=40); //!< sendWithRetry (40ms roundtrip req for 61byte packets)
|
||||
virtual void send(uint8_t toAddress, const void* buffer, uint8_t bufferSize,
|
||||
bool requestACK=false); //!< send
|
||||
virtual bool sendWithRetry(uint8_t toAddress, const void* buffer, uint8_t bufferSize,
|
||||
uint8_t retries=2, uint8_t retryWaitTime=
|
||||
40); //!< sendWithRetry (40ms roundtrip req for 61byte packets)
|
||||
virtual bool receiveDone(); //!< receiveDone
|
||||
bool ACKReceived(uint8_t fromNodeID); //!< ACKReceived
|
||||
bool ACKRequested(); //!< ACKRequested
|
||||
@@ -117,7 +132,8 @@ class RFM69 {
|
||||
void setCS(uint8_t newSPISlaveSelect); //!< setCS
|
||||
int16_t readRSSI(bool forceTrigger=false); //!< readRSSI
|
||||
void promiscuous(bool onOff=true); //!< promiscuous
|
||||
virtual void setHighPower(bool onOFF=true); //!< setHighPower (have to call it after initialize for RFM69HW)
|
||||
virtual void setHighPower(bool onOFF=
|
||||
true); //!< setHighPower (have to call it after initialize for RFM69HW)
|
||||
virtual void setPowerLevel(uint8_t level); //!< setPowerLevel (reduce/increase transmit power level)
|
||||
void sleep(); //!< sleep
|
||||
uint8_t readTemperature(uint8_t calFactor=0); //!< readTemperature (get CMOS temperature (8bit))
|
||||
@@ -132,7 +148,8 @@ class RFM69 {
|
||||
static void isr0(); //!< isr0
|
||||
void virtual interruptHandler(); //!< interruptHandler
|
||||
virtual void interruptHook(uint8_t CTLbyte); //!< interruptHook
|
||||
virtual void sendFrame(uint8_t toAddress, const void* buffer, uint8_t size, bool requestACK=false, bool sendACK=false); //!< sendFrame
|
||||
virtual void sendFrame(uint8_t toAddress, const void* buffer, uint8_t size, bool requestACK=false,
|
||||
bool sendACK=false); //!< sendFrame
|
||||
|
||||
static RFM69* selfPointer; //!< selfPointer
|
||||
uint8_t _slaveSelectPin; //!< _slaveSelectPin
|
||||
|
||||
+90
-63
@@ -26,18 +26,23 @@
|
||||
|
||||
#if defined(LINUX_ARCH_RASPBERRYPI)
|
||||
uint8_t spi_rxbuff[32 + 1]; //SPI receive buffer (payload max 32 bytes, MYS protocol limitation)
|
||||
uint8_t spi_txbuff[32 + 1]; //SPI transmit buffer (payload max 32 bytes + 1 byte for the command, MYS protocol limitation)
|
||||
uint8_t spi_txbuff[32 +
|
||||
1]; //SPI transmit buffer (payload max 32 bytes + 1 byte for the command, MYS protocol limitation)
|
||||
#endif
|
||||
|
||||
LOCAL void RFM95_csn(const bool level) {
|
||||
LOCAL void RFM95_csn(const bool level)
|
||||
{
|
||||
hwDigitalWrite(MY_RFM95_SPI_CS, level);
|
||||
}
|
||||
|
||||
LOCAL uint8_t RFM95_spiMultiByteTransfer(const uint8_t cmd, uint8_t* buf, uint8_t len, const bool aReadMode) {
|
||||
LOCAL uint8_t RFM95_spiMultiByteTransfer(const uint8_t cmd, uint8_t* buf, uint8_t len,
|
||||
const bool aReadMode)
|
||||
{
|
||||
uint8_t status;
|
||||
uint8_t* current = buf;
|
||||
#if !defined(MY_SOFTSPI)
|
||||
_SPI.beginTransaction(SPISettings(MY_RFM95_SPI_MAX_SPEED, MY_RFM95_SPI_DATA_ORDER, MY_RFM95_SPI_DATA_MODE));
|
||||
_SPI.beginTransaction(SPISettings(MY_RFM95_SPI_MAX_SPEED, MY_RFM95_SPI_DATA_ORDER,
|
||||
MY_RFM95_SPI_DATA_MODE));
|
||||
#endif
|
||||
RFM95_csn(LOW);
|
||||
#if defined(LINUX_ARCH_RASPBERRYPI)
|
||||
@@ -49,8 +54,7 @@ LOCAL uint8_t RFM95_spiMultiByteTransfer(const uint8_t cmd, uint8_t* buf, uint8_
|
||||
while (len--) {
|
||||
if (aReadMode) {
|
||||
*ptx++ = RF24_NOP;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
*ptx++ = *current++;
|
||||
}
|
||||
}
|
||||
@@ -58,16 +62,14 @@ LOCAL uint8_t RFM95_spiMultiByteTransfer(const uint8_t cmd, uint8_t* buf, uint8_
|
||||
if (aReadMode) {
|
||||
if (size == 2) {
|
||||
status = *++prx; // result is 2nd byte of receive buffer
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
status = *prx++; // status is 1st byte of receive buffer
|
||||
// decrement before to skip status byte
|
||||
while (--size) {
|
||||
*buf++ = *prx++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
status = *prx; // status is 1st byte of receive buffer
|
||||
}
|
||||
#else
|
||||
@@ -78,8 +80,9 @@ LOCAL uint8_t RFM95_spiMultiByteTransfer(const uint8_t cmd, uint8_t* buf, uint8_
|
||||
if (buf != NULL) {
|
||||
*current++ = status;
|
||||
}
|
||||
} else {
|
||||
status = _SPI.transfer(*current++);
|
||||
}
|
||||
else status = _SPI.transfer(*current++);
|
||||
}
|
||||
#endif
|
||||
RFM95_csn(HIGH);
|
||||
@@ -90,12 +93,14 @@ LOCAL uint8_t RFM95_spiMultiByteTransfer(const uint8_t cmd, uint8_t* buf, uint8_
|
||||
}
|
||||
|
||||
// low level register access
|
||||
LOCAL uint8_t RFM95_RAW_readByteRegister(const uint8_t address) {
|
||||
LOCAL uint8_t RFM95_RAW_readByteRegister(const uint8_t address)
|
||||
{
|
||||
return RFM95_spiMultiByteTransfer(address, NULL, 1, true);
|
||||
}
|
||||
|
||||
// low level register access
|
||||
LOCAL uint8_t RFM95_RAW_writeByteRegister(const uint8_t address, uint8_t value) {
|
||||
LOCAL uint8_t RFM95_RAW_writeByteRegister(const uint8_t address, uint8_t value)
|
||||
{
|
||||
return RFM95_spiMultiByteTransfer(address, &value, 1, false);
|
||||
}
|
||||
|
||||
@@ -109,7 +114,8 @@ LOCAL uint8_t RFM95_RAW_writeByteRegister(const uint8_t address, uint8_t value)
|
||||
// check RegPktRssiValue (0x1A) vs. RegRssiValue (0x1B)
|
||||
|
||||
|
||||
LOCAL bool RFM95_initialise(const float frequency) {
|
||||
LOCAL bool RFM95_initialise(const float frequency)
|
||||
{
|
||||
RFM95_DEBUG(PSTR("RFM95:INIT\n"));
|
||||
// reset radio module if rst pin defined
|
||||
#if defined(MY_RFM95_RST_PIN)
|
||||
@@ -167,14 +173,15 @@ LOCAL bool RFM95_initialise(const float frequency) {
|
||||
}
|
||||
|
||||
// RxDone, TxDone, CADDone is mapped to DI0
|
||||
LOCAL void RFM95_interruptHandler(void) {
|
||||
LOCAL void RFM95_interruptHandler(void)
|
||||
{
|
||||
// Read the interrupt register
|
||||
const uint8_t irqFlags = RFM95_readReg(RFM95_REG_12_IRQ_FLAGS);
|
||||
if (RFM95.radioMode == RFM95_RADIO_MODE_RX && (irqFlags & (RFM95_RX_TIMEOUT | RFM95_PAYLOAD_CRC_ERROR)) ) {
|
||||
if (RFM95.radioMode == RFM95_RADIO_MODE_RX &&
|
||||
(irqFlags & (RFM95_RX_TIMEOUT | RFM95_PAYLOAD_CRC_ERROR)) ) {
|
||||
// CRC error or timeout
|
||||
// RXcontinuous mode: radio stays in RX mode, clearing IRQ needed
|
||||
}
|
||||
else if (RFM95.radioMode == RFM95_RADIO_MODE_RX && (irqFlags & RFM95_RX_DONE)) {
|
||||
} else if (RFM95.radioMode == RFM95_RADIO_MODE_RX && (irqFlags & RFM95_RX_DONE)) {
|
||||
// set radio to STDBY (we are in RXcontinuous mode)
|
||||
(void)RFM95_setRadioMode(RFM95_RADIO_MODE_STDBY);
|
||||
// Have received a packet
|
||||
@@ -189,16 +196,15 @@ LOCAL void RFM95_interruptHandler(void) {
|
||||
RFM95.currentPacket.payloadLen = bufLen - RFM95_HEADER_LEN;
|
||||
// Message for us
|
||||
if ((RFM95.currentPacket.header.version >= RFM95_MIN_PACKET_HEADER_VERSION) &&
|
||||
(RFM95_PROMISCUOUS || RFM95.currentPacket.header.recipient == RFM95.address || RFM95.currentPacket.header.recipient == RFM95_BROADCAST_ADDRESS)) {
|
||||
(RFM95_PROMISCUOUS || RFM95.currentPacket.header.recipient == RFM95.address ||
|
||||
RFM95.currentPacket.header.recipient == RFM95_BROADCAST_ADDRESS)) {
|
||||
RFM95.rxBufferValid = true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else if (RFM95.radioMode == RFM95_RADIO_MODE_TX && (irqFlags & RFM95_TX_DONE) ) {
|
||||
} else if (RFM95.radioMode == RFM95_RADIO_MODE_TX && (irqFlags & RFM95_TX_DONE) ) {
|
||||
(void)RFM95_setRadioMode(RFM95_RADIO_MODE_STDBY);
|
||||
}
|
||||
else if (RFM95.radioMode == RFM95_RADIO_MODE_CAD && (irqFlags & RFM95_CAD_DONE) ) {
|
||||
} else if (RFM95.radioMode == RFM95_RADIO_MODE_CAD && (irqFlags & RFM95_CAD_DONE) ) {
|
||||
RFM95.cad = irqFlags & RFM95_CAD_DETECTED;
|
||||
(void)RFM95_setRadioMode(RFM95_RADIO_MODE_STDBY);
|
||||
}
|
||||
@@ -207,7 +213,8 @@ LOCAL void RFM95_interruptHandler(void) {
|
||||
RFM95_writeReg(RFM95_REG_12_IRQ_FLAGS, 0xFF);
|
||||
}
|
||||
|
||||
LOCAL bool RFM95_available(void) {
|
||||
LOCAL bool RFM95_available(void)
|
||||
{
|
||||
if (RFM95.radioMode == RFM95_RADIO_MODE_TX) {
|
||||
return false;
|
||||
}
|
||||
@@ -215,13 +222,15 @@ LOCAL bool RFM95_available(void) {
|
||||
return RFM95.rxBufferValid;
|
||||
}
|
||||
|
||||
LOCAL void RFM95_clearRxBuffer(void) {
|
||||
LOCAL void RFM95_clearRxBuffer(void)
|
||||
{
|
||||
noInterrupts();
|
||||
RFM95.rxBufferValid = false;
|
||||
interrupts();
|
||||
}
|
||||
|
||||
LOCAL uint8_t RFM95_recv(uint8_t* buf) {
|
||||
LOCAL uint8_t RFM95_recv(uint8_t* buf)
|
||||
{
|
||||
if (!RFM95_available()) {
|
||||
return false;
|
||||
}
|
||||
@@ -249,7 +258,8 @@ LOCAL uint8_t RFM95_recv(uint8_t* buf) {
|
||||
return payloadLen;
|
||||
}
|
||||
|
||||
LOCAL bool RFM95_send(rfm95_packet_t &packet) {
|
||||
LOCAL bool RFM95_send(rfm95_packet_t &packet)
|
||||
{
|
||||
const uint8_t finalLen = packet.payloadLen + RFM95_HEADER_LEN;
|
||||
// Make sure we dont interrupt an outgoing message
|
||||
RFM95_waitPacketSent();
|
||||
@@ -271,7 +281,9 @@ LOCAL bool RFM95_send(rfm95_packet_t &packet) {
|
||||
return true;
|
||||
}
|
||||
|
||||
LOCAL bool RFM95_sendFrame(const uint8_t recipient, uint8_t* data, const uint8_t len, const rfm95_flag_t flags) {
|
||||
LOCAL bool RFM95_sendFrame(const uint8_t recipient, uint8_t* data, const uint8_t len,
|
||||
const rfm95_flag_t flags)
|
||||
{
|
||||
rfm95_packet_t packet;
|
||||
packet.header.version = RFM95_PACKET_HEADER_VERSION;
|
||||
packet.header.sender = RFM95.address;
|
||||
@@ -283,14 +295,16 @@ LOCAL bool RFM95_sendFrame(const uint8_t recipient, uint8_t* data, const uint8_t
|
||||
return RFM95_send(packet);
|
||||
}
|
||||
|
||||
LOCAL void RFM95_setFrequency(const float centre) {
|
||||
LOCAL void RFM95_setFrequency(const float centre)
|
||||
{
|
||||
const uint32_t freq = (centre * 1000000.0) / RFM95_FSTEP;
|
||||
RFM95_writeReg(RFM95_REG_06_FRF_MSB, (freq >> 16) & 0xff);
|
||||
RFM95_writeReg(RFM95_REG_07_FRF_MID, (freq >> 8) & 0xff);
|
||||
RFM95_writeReg(RFM95_REG_08_FRF_LSB, freq & 0xff);
|
||||
}
|
||||
|
||||
LOCAL bool RFM95_setTxPower(uint8_t powerLevel) {
|
||||
LOCAL bool RFM95_setTxPower(uint8_t powerLevel)
|
||||
{
|
||||
// RFM95/96/97/98 does not have RFO pins connected to anything. Only PA_BOOST
|
||||
powerLevel = max((uint8_t)RFM95_MIN_POWER_LEVEL_DBM, powerLevel);
|
||||
powerLevel = min((uint8_t)RFM95_MAX_POWER_LEVEL_DBM, powerLevel);
|
||||
@@ -304,8 +318,7 @@ LOCAL bool RFM95_setTxPower(uint8_t powerLevel) {
|
||||
// My measurements show 20dBm is correct
|
||||
RFM95_writeReg(RFM95_REG_4D_PA_DAC, RFM95_PA_DAC_ENABLE);
|
||||
val = powerLevel - 8;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
RFM95_writeReg(RFM95_REG_4D_PA_DAC, RFM95_PA_DAC_DISABLE);
|
||||
val = powerLevel - 5;
|
||||
}
|
||||
@@ -318,27 +331,32 @@ LOCAL bool RFM95_setTxPower(uint8_t powerLevel) {
|
||||
}
|
||||
|
||||
// Sets registers from a canned modem configuration structure
|
||||
LOCAL void RFM95_setModemRegisters(const rfm95_modemConfig_t config) {
|
||||
LOCAL void RFM95_setModemRegisters(const rfm95_modemConfig_t config)
|
||||
{
|
||||
RFM95_writeReg(RFM95_REG_1D_MODEM_CONFIG1, config.reg_1d);
|
||||
RFM95_writeReg(RFM95_REG_1E_MODEM_CONFIG2, config.reg_1e);
|
||||
RFM95_writeReg(RFM95_REG_26_MODEM_CONFIG3, config.reg_26);
|
||||
}
|
||||
|
||||
LOCAL void RFM95_setPreambleLength(const uint16_t preambleLength) {
|
||||
LOCAL void RFM95_setPreambleLength(const uint16_t preambleLength)
|
||||
{
|
||||
RFM95_writeReg(RFM95_REG_20_PREAMBLE_MSB, preambleLength >> 8);
|
||||
RFM95_writeReg(RFM95_REG_21_PREAMBLE_LSB, preambleLength & 0xff);
|
||||
}
|
||||
|
||||
LOCAL void RFM95_setAddress(const uint8_t addr) {
|
||||
LOCAL void RFM95_setAddress(const uint8_t addr)
|
||||
{
|
||||
RFM95.address = addr;
|
||||
}
|
||||
|
||||
LOCAL uint8_t RFM95_getAddress(void) {
|
||||
LOCAL uint8_t RFM95_getAddress(void)
|
||||
{
|
||||
return RFM95.address;
|
||||
}
|
||||
|
||||
|
||||
LOCAL bool RFM95_isChannelActive(void) {
|
||||
LOCAL bool RFM95_isChannelActive(void)
|
||||
{
|
||||
(void)RFM95_setRadioMode(RFM95_RADIO_MODE_CAD);
|
||||
while (RFM95.radioMode == RFM95_RADIO_MODE_CAD) {
|
||||
doYield();
|
||||
@@ -347,7 +365,8 @@ LOCAL bool RFM95_isChannelActive(void) {
|
||||
return RFM95.cad;
|
||||
}
|
||||
|
||||
LOCAL bool RFM95_setRadioMode(const rfm95_radioMode_t newRadioMode) {
|
||||
LOCAL bool RFM95_setRadioMode(const rfm95_radioMode_t newRadioMode)
|
||||
{
|
||||
if (RFM95.radioMode == newRadioMode) {
|
||||
return false;
|
||||
}
|
||||
@@ -355,35 +374,35 @@ LOCAL bool RFM95_setRadioMode(const rfm95_radioMode_t newRadioMode) {
|
||||
|
||||
if (newRadioMode == RFM95_RADIO_MODE_STDBY) {
|
||||
regMode = RFM95_MODE_STDBY;
|
||||
}
|
||||
else if (newRadioMode == RFM95_RADIO_MODE_SLEEP) {
|
||||
} else if (newRadioMode == RFM95_RADIO_MODE_SLEEP) {
|
||||
regMode = RFM95_MODE_SLEEP;
|
||||
}
|
||||
else if (newRadioMode == RFM95_RADIO_MODE_CAD) {
|
||||
} else if (newRadioMode == RFM95_RADIO_MODE_CAD) {
|
||||
regMode = RFM95_MODE_CAD;
|
||||
RFM95_writeReg(RFM95_REG_40_DIO_MAPPING1, 0x80); // Interrupt on CadDone, DIO0
|
||||
}
|
||||
else if (newRadioMode == RFM95_RADIO_MODE_RX) {
|
||||
} else if (newRadioMode == RFM95_RADIO_MODE_RX) {
|
||||
regMode = RFM95_MODE_RXCONTINUOUS;
|
||||
RFM95_writeReg(RFM95_REG_40_DIO_MAPPING1, 0x00); // Interrupt on RxDone, DIO0
|
||||
}
|
||||
else if (newRadioMode == RFM95_RADIO_MODE_TX) {
|
||||
} else if (newRadioMode == RFM95_RADIO_MODE_TX) {
|
||||
regMode = RFM95_MODE_TX;
|
||||
RFM95_writeReg(RFM95_REG_40_DIO_MAPPING1, 0x40); // Interrupt on TxDone, DIO0
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
else return false;
|
||||
RFM95_writeReg(RFM95_REG_01_OP_MODE, regMode);
|
||||
|
||||
RFM95.radioMode = newRadioMode;
|
||||
return true;
|
||||
}
|
||||
|
||||
LOCAL bool RFM95_sleep(void) {
|
||||
LOCAL bool RFM95_sleep(void)
|
||||
{
|
||||
return RFM95_setRadioMode(RFM95_RADIO_MODE_SLEEP);
|
||||
}
|
||||
|
||||
// should be called immediately after reception in case sender wants ACK
|
||||
LOCAL void RFM95_sendACK(const uint8_t recipient, const rfm95_sequenceNumber_t sequenceNumber, const rfm95_RSSI_t RSSI, const rfm95_RSSI_t SNR) {
|
||||
LOCAL void RFM95_sendACK(const uint8_t recipient, const rfm95_sequenceNumber_t sequenceNumber,
|
||||
const rfm95_RSSI_t RSSI, const rfm95_RSSI_t SNR)
|
||||
{
|
||||
RFM95_DEBUG(PSTR("RFM95:SAC:SEND ACK to=%d,RSSI=%d\n"),recipient,RSSI);
|
||||
rfm95_ack_t ACK;
|
||||
ACK.sequenceNumber = sequenceNumber;
|
||||
@@ -395,25 +414,26 @@ LOCAL void RFM95_sendACK(const uint8_t recipient, const rfm95_sequenceNumber_t s
|
||||
(void)RFM95_sendFrame(recipient, (uint8_t*)&ACK, sizeof(rfm95_ack_t), flags);
|
||||
}
|
||||
|
||||
LOCAL bool RFM95_executeATC(const rfm95_RSSI_t currentRSSI, const rfm95_RSSI_t targetRSSI) {
|
||||
LOCAL bool RFM95_executeATC(const rfm95_RSSI_t currentRSSI, const rfm95_RSSI_t targetRSSI)
|
||||
{
|
||||
// allow +-5%
|
||||
if (currentRSSI < (targetRSSI*1.05) && RFM95.powerLevel < RFM95_MAX_POWER_LEVEL_DBM) {
|
||||
// increase transmitter power
|
||||
RFM95.powerLevel++;
|
||||
}
|
||||
else if (currentRSSI > (targetRSSI*0.95) && RFM95.powerLevel > RFM95_MIN_POWER_LEVEL_DBM) {
|
||||
} else if (currentRSSI > (targetRSSI*0.95) && RFM95.powerLevel > RFM95_MIN_POWER_LEVEL_DBM) {
|
||||
// decrease transmitter power
|
||||
RFM95.powerLevel--;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// nothing to adjust
|
||||
return false;
|
||||
}
|
||||
RFM95_DEBUG(PSTR("RFM95:ATC:ADJ TXL,cR=%d,tR=%d,TXL=%d\n"), currentRSSI - RFM95_RSSI_OFFSET, targetRSSI - RFM95_RSSI_OFFSET, RFM95.powerLevel);
|
||||
RFM95_DEBUG(PSTR("RFM95:ATC:ADJ TXL,cR=%d,tR=%d,TXL=%d\n"), currentRSSI - RFM95_RSSI_OFFSET,
|
||||
targetRSSI - RFM95_RSSI_OFFSET, RFM95.powerLevel);
|
||||
return RFM95_setTxPower(RFM95.powerLevel);;
|
||||
}
|
||||
|
||||
LOCAL bool RFM95_sendWithRetry(const uint8_t recipient, const void* buffer, const uint8_t bufferSize, const uint8_t retries, const uint32_t retryWaitTime)
|
||||
LOCAL bool RFM95_sendWithRetry(const uint8_t recipient, const void* buffer,
|
||||
const uint8_t bufferSize, const uint8_t retries, const uint32_t retryWaitTime)
|
||||
{
|
||||
for (uint8_t retry = 0; retry < retries; retry++) {
|
||||
RFM95_DEBUG(PSTR("RFM95:SWR:SEND TO=%d,RETRY=%d\n"), recipient, retry);
|
||||
@@ -431,8 +451,10 @@ LOCAL bool RFM95_sendWithRetry(const uint8_t recipient, const void* buffer, cons
|
||||
const uint8_t sender = RFM95.currentPacket.header.sender;
|
||||
const rfm95_sequenceNumber_t ACKsequenceNumber = RFM95.currentPacket.ACK.sequenceNumber;
|
||||
const rfm95_flag_t flag = RFM95.currentPacket.header.controlFlags;
|
||||
if (sender == recipient && RFM95_getACKReceived(flag) && (ACKsequenceNumber == RFM95.txSequenceNumber - 1)) {
|
||||
RFM95_DEBUG(PSTR("RFM95:SWR:ACK FROM=%d,SEQ=%d,RSSI=%d,SNR=%d\n"),sender,ACKsequenceNumber, RFM95.currentPacket.ACK.RSSI-RFM95_RSSI_OFFSET, (int8_t)RFM95.currentPacket.ACK.SNR / 4);
|
||||
if (sender == recipient && RFM95_getACKReceived(flag) &&
|
||||
(ACKsequenceNumber == RFM95.txSequenceNumber - 1)) {
|
||||
RFM95_DEBUG(PSTR("RFM95:SWR:ACK FROM=%d,SEQ=%d,RSSI=%d,SNR=%d\n"),sender,ACKsequenceNumber,
|
||||
RFM95.currentPacket.ACK.RSSI-RFM95_RSSI_OFFSET, (int8_t)RFM95.currentPacket.ACK.SNR / 4);
|
||||
RFM95_clearRxBuffer();
|
||||
|
||||
// ATC
|
||||
@@ -455,7 +477,8 @@ LOCAL bool RFM95_sendWithRetry(const uint8_t recipient, const void* buffer, cons
|
||||
|
||||
|
||||
// Wait until no channel activity detected or timeout
|
||||
LOCAL bool RFM95_waitCAD(void) {
|
||||
LOCAL bool RFM95_waitCAD(void)
|
||||
{
|
||||
const uint32_t enterMS = hwMillis();
|
||||
while (RFM95_isChannelActive()) {
|
||||
if (hwMillis() - enterMS > RFM95_CAD_TIMEOUT_MS) {
|
||||
@@ -467,23 +490,27 @@ LOCAL bool RFM95_waitCAD(void) {
|
||||
}
|
||||
|
||||
// Wait for any previous transmission to finish
|
||||
LOCAL bool RFM95_waitPacketSent(void) {
|
||||
LOCAL bool RFM95_waitPacketSent(void)
|
||||
{
|
||||
while (RFM95.radioMode == RFM95_RADIO_MODE_TX) {
|
||||
doYield();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
LOCAL int16_t RFM95_getRSSI(void) {
|
||||
LOCAL int16_t RFM95_getRSSI(void)
|
||||
{
|
||||
return (int16_t)(RFM95.currentPacket.RSSI - RFM95_RSSI_OFFSET);
|
||||
}
|
||||
|
||||
LOCAL void RFM95_ATCmode(const bool OnOff, const int16_t targetRSSI) {
|
||||
LOCAL void RFM95_ATCmode(const bool OnOff, const int16_t targetRSSI)
|
||||
{
|
||||
RFM95.ATCenabled = OnOff;
|
||||
RFM95.ATCtargetRSSI = (uint8_t)(targetRSSI + RFM95_RSSI_OFFSET);
|
||||
}
|
||||
|
||||
LOCAL bool RFM95_sanityCheck(void) {
|
||||
LOCAL bool RFM95_sanityCheck(void)
|
||||
{
|
||||
// not implemented yet
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -106,7 +106,8 @@
|
||||
#if defined (ARDUINO) && !defined (__arm__) && !defined (_SPI)
|
||||
#include <SPI.h>
|
||||
#if defined(MY_SOFTSPI)
|
||||
SoftSPI<MY_SOFT_SPI_MISO_PIN, MY_SOFT_SPI_MOSI_PIN, MY_SOFT_SPI_SCK_PIN, MY_RF24_SPI_DATA_MODE> _SPI;
|
||||
SoftSPI<MY_SOFT_SPI_MISO_PIN, MY_SOFT_SPI_MOSI_PIN, MY_SOFT_SPI_SCK_PIN, MY_RF24_SPI_DATA_MODE>
|
||||
_SPI;
|
||||
#else
|
||||
#define _SPI SPI
|
||||
#endif
|
||||
@@ -316,7 +317,8 @@ LOCAL bool RFM95_send(rfm95_packet_t &packet);
|
||||
* @param flags
|
||||
* @return True if frame sent
|
||||
*/
|
||||
LOCAL bool RFM95_sendFrame(const uint8_t recipient, uint8_t* data, const uint8_t len, const rfm95_flag_t flags);
|
||||
LOCAL bool RFM95_sendFrame(const uint8_t recipient, uint8_t* data, const uint8_t len,
|
||||
const rfm95_flag_t flags);
|
||||
/**
|
||||
* @brief RFM95_setPreambleLength
|
||||
* @param preambleLength
|
||||
@@ -350,7 +352,8 @@ LOCAL bool RFM95_isChannelActive(void);
|
||||
* @param RSSI (rfm95_RSSI_t)
|
||||
* @param SNR (rfm95_RSSI_t)
|
||||
*/
|
||||
LOCAL void RFM95_sendACK(const uint8_t recipient, const rfm95_sequenceNumber_t sequenceNumber, const rfm95_RSSI_t RSSI, const rfm95_RSSI_t SNR);
|
||||
LOCAL void RFM95_sendACK(const uint8_t recipient, const rfm95_sequenceNumber_t sequenceNumber,
|
||||
const rfm95_RSSI_t RSSI, const rfm95_RSSI_t SNR);
|
||||
/**
|
||||
* @brief RFM95_sendWithRetry
|
||||
* @param recipient
|
||||
@@ -360,7 +363,9 @@ LOCAL void RFM95_sendACK(const uint8_t recipient, const rfm95_sequenceNumber_t s
|
||||
* @param retryWaitTime
|
||||
* @return True if packet successfully sent
|
||||
*/
|
||||
LOCAL bool RFM95_sendWithRetry(const uint8_t recipient, const void* buffer, const uint8_t bufferSize, const uint8_t retries = RFM95_RETRIES, const uint32_t retryWaitTime = RFM95_RETRY_TIMEOUT_MS);
|
||||
LOCAL bool RFM95_sendWithRetry(const uint8_t recipient, const void* buffer,
|
||||
const uint8_t bufferSize, const uint8_t retries = RFM95_RETRIES,
|
||||
const uint32_t retryWaitTime = RFM95_RETRY_TIMEOUT_MS);
|
||||
/**
|
||||
* @brief RFM95_waitCAD
|
||||
* @return True if no channel activity detected
|
||||
|
||||
+24
-15
@@ -31,11 +31,13 @@ SPIClass SPI = SPIClass();
|
||||
|
||||
uint8_t SPIClass::initialized = 0;
|
||||
|
||||
uint8_t SPIClass::is_initialized() {
|
||||
uint8_t SPIClass::is_initialized()
|
||||
{
|
||||
return initialized;
|
||||
}
|
||||
|
||||
void SPIClass::begin() {
|
||||
void SPIClass::begin()
|
||||
{
|
||||
if (!initialized) {
|
||||
if (!bcm2835_spi_begin()) {
|
||||
logError("You need root privilege to use SPI.\n");
|
||||
@@ -46,7 +48,8 @@ void SPIClass::begin() {
|
||||
initialized++; // reference count
|
||||
}
|
||||
|
||||
void SPIClass::end() {
|
||||
void SPIClass::end()
|
||||
{
|
||||
if (initialized) {
|
||||
initialized--;
|
||||
}
|
||||
@@ -57,47 +60,53 @@ void SPIClass::end() {
|
||||
}
|
||||
}
|
||||
|
||||
void SPIClass::setBitOrder(uint8_t bit_order) {
|
||||
void SPIClass::setBitOrder(uint8_t bit_order)
|
||||
{
|
||||
bcm2835_spi_setBitOrder(bit_order);
|
||||
}
|
||||
|
||||
void SPIClass::setDataMode(uint8_t data_mode) {
|
||||
void SPIClass::setDataMode(uint8_t data_mode)
|
||||
{
|
||||
bcm2835_spi_setDataMode(data_mode);
|
||||
}
|
||||
|
||||
void SPIClass::setClockDivider(uint16_t divider) {
|
||||
void SPIClass::setClockDivider(uint16_t divider)
|
||||
{
|
||||
bcm2835_spi_setClockDivider(divider);
|
||||
}
|
||||
|
||||
void SPIClass::chipSelect(int csn_pin) {
|
||||
void SPIClass::chipSelect(int csn_pin)
|
||||
{
|
||||
if (csn_pin == RPI_GPIO_P1_26) {
|
||||
csn_pin = BCM2835_SPI_CS1;
|
||||
}
|
||||
else if (csn_pin == RPI_GPIO_P1_24) {
|
||||
} else if (csn_pin == RPI_GPIO_P1_24) {
|
||||
csn_pin = BCM2835_SPI_CS0;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
csn_pin = BCM2835_SPI_CS0;
|
||||
}
|
||||
bcm2835_spi_chipSelect(csn_pin);
|
||||
delayMicroseconds(5);
|
||||
}
|
||||
|
||||
void SPIClass::beginTransaction(SPISettings settings) {
|
||||
void SPIClass::beginTransaction(SPISettings settings)
|
||||
{
|
||||
pthread_mutex_lock(&spiMutex);
|
||||
setBitOrder(settings.border);
|
||||
setDataMode(settings.dmode);
|
||||
setClockDivider(settings.cdiv);
|
||||
}
|
||||
|
||||
void SPIClass::endTransaction() {
|
||||
void SPIClass::endTransaction()
|
||||
{
|
||||
pthread_mutex_unlock(&spiMutex);
|
||||
}
|
||||
|
||||
void SPIClass::usingInterrupt(uint8_t interruptNumber) {
|
||||
void SPIClass::usingInterrupt(uint8_t interruptNumber)
|
||||
{
|
||||
(void)interruptNumber;
|
||||
}
|
||||
|
||||
void SPIClass::notUsingInterrupt(uint8_t interruptNumber) {
|
||||
void SPIClass::notUsingInterrupt(uint8_t interruptNumber)
|
||||
{
|
||||
(void)interruptNumber;
|
||||
}
|
||||
|
||||
+16
-8
@@ -45,7 +45,8 @@
|
||||
/**
|
||||
* SPISettings class
|
||||
*/
|
||||
class SPISettings {
|
||||
class SPISettings
|
||||
{
|
||||
|
||||
public:
|
||||
/**
|
||||
@@ -53,7 +54,8 @@ public:
|
||||
*
|
||||
* Default clock speed is 8Mhz.
|
||||
*/
|
||||
SPISettings() {
|
||||
SPISettings()
|
||||
{
|
||||
init(BCM2835_SPI_CLOCK_DIVIDER_32, BCM2835_SPI_BIT_ORDER_MSBFIRST, BCM2835_SPI_MODE0);
|
||||
}
|
||||
/**
|
||||
@@ -63,7 +65,8 @@ public:
|
||||
* @param bitOrder SPI bit order.
|
||||
* @param dataMode SPI data mode.
|
||||
*/
|
||||
SPISettings(uint32_t clock, uint8_t bitOrder, uint8_t dataMode) {
|
||||
SPISettings(uint32_t clock, uint8_t bitOrder, uint8_t dataMode)
|
||||
{
|
||||
uint16_t divider;
|
||||
|
||||
switch (clock) {
|
||||
@@ -105,7 +108,8 @@ private:
|
||||
* @param bitOrder SPI bit order.
|
||||
* @param dataMode SPI data mode.
|
||||
*/
|
||||
void init(uint16_t divider, uint8_t bitOrder, uint8_t dataMode) {
|
||||
void init(uint16_t divider, uint8_t bitOrder, uint8_t dataMode)
|
||||
{
|
||||
cdiv = divider;
|
||||
border = bitOrder;
|
||||
dmode = dataMode;
|
||||
@@ -117,7 +121,8 @@ private:
|
||||
/**
|
||||
* SPIClass class
|
||||
*/
|
||||
class SPIClass {
|
||||
class SPIClass
|
||||
{
|
||||
|
||||
private:
|
||||
static uint8_t initialized; //!< @brief SPI initialized flag.
|
||||
@@ -207,15 +212,18 @@ public:
|
||||
static void notUsingInterrupt(uint8_t interruptNumber);
|
||||
};
|
||||
|
||||
uint8_t SPIClass::transfer(uint8_t data) {
|
||||
uint8_t SPIClass::transfer(uint8_t data)
|
||||
{
|
||||
return bcm2835_spi_transfer(data);
|
||||
}
|
||||
|
||||
void SPIClass::transfernb(char* tbuf, char* rbuf, uint32_t len) {
|
||||
void SPIClass::transfernb(char* tbuf, char* rbuf, uint32_t len)
|
||||
{
|
||||
bcm2835_spi_transfernb( tbuf, rbuf, len);
|
||||
}
|
||||
|
||||
void SPIClass::transfern(char* buf, uint32_t len) {
|
||||
void SPIClass::transfern(char* buf, uint32_t len)
|
||||
{
|
||||
transfernb(buf, buf, len);
|
||||
}
|
||||
|
||||
|
||||
+18
-5
@@ -31,7 +31,8 @@
|
||||
|
||||
#define BUFFER_LENGTH 32
|
||||
|
||||
class TwoWire : public Stream {
|
||||
class TwoWire : public Stream
|
||||
{
|
||||
|
||||
private:
|
||||
static uint8_t rxBuffer[];
|
||||
@@ -67,10 +68,22 @@ public:
|
||||
int peek();
|
||||
void flush();
|
||||
|
||||
inline size_t write(unsigned long n) { return write((uint8_t)n); }
|
||||
inline size_t write(long n) { return write((uint8_t)n); }
|
||||
inline size_t write(unsigned int n) { return write((uint8_t)n); }
|
||||
inline size_t write(int n) { return write((uint8_t)n); }
|
||||
inline size_t write(unsigned long n)
|
||||
{
|
||||
return write((uint8_t)n);
|
||||
}
|
||||
inline size_t write(long n)
|
||||
{
|
||||
return write((uint8_t)n);
|
||||
}
|
||||
inline size_t write(unsigned int n)
|
||||
{
|
||||
return write((uint8_t)n);
|
||||
}
|
||||
inline size_t write(int n)
|
||||
{
|
||||
return write((uint8_t)n);
|
||||
}
|
||||
using Print::write;
|
||||
};
|
||||
|
||||
|
||||
+135
-160
@@ -77,8 +77,7 @@ static int i2c_byte_wait_us = 0;
|
||||
/* Function to return the pointers to the hardware register bases */
|
||||
uint32_t* bcm2835_regbase(uint8_t regbase)
|
||||
{
|
||||
switch (regbase)
|
||||
{
|
||||
switch (regbase) {
|
||||
case BCM2835_REGBASE_ST:
|
||||
return (uint32_t *)bcm2835_st;
|
||||
case BCM2835_REGBASE_GPIO:
|
||||
@@ -115,13 +114,10 @@ unsigned int bcm2835_version(void)
|
||||
uint32_t bcm2835_peri_read(volatile uint32_t* paddr)
|
||||
{
|
||||
uint32_t ret;
|
||||
if (debug)
|
||||
{
|
||||
if (debug) {
|
||||
printf("bcm2835_peri_read paddr %08X\n", (unsigned) paddr);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
__sync_synchronize();
|
||||
ret = *paddr;
|
||||
__sync_synchronize();
|
||||
@@ -137,13 +133,10 @@ uint32_t bcm2835_peri_read(volatile uint32_t* paddr)
|
||||
*/
|
||||
uint32_t bcm2835_peri_read_nb(volatile uint32_t* paddr)
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
if (debug) {
|
||||
printf("bcm2835_peri_read_nb paddr %08X\n", (unsigned) paddr);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
return *paddr;
|
||||
}
|
||||
}
|
||||
@@ -153,12 +146,9 @@ uint32_t bcm2835_peri_read_nb(volatile uint32_t* paddr)
|
||||
|
||||
void bcm2835_peri_write(volatile uint32_t* paddr, uint32_t value)
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
if (debug) {
|
||||
printf("bcm2835_peri_write paddr %08X, value %08X\n", (unsigned) paddr, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
__sync_synchronize();
|
||||
*paddr = value;
|
||||
__sync_synchronize();
|
||||
@@ -168,13 +158,10 @@ void bcm2835_peri_write(volatile uint32_t* paddr, uint32_t value)
|
||||
/* write to peripheral without the write barrier */
|
||||
void bcm2835_peri_write_nb(volatile uint32_t* paddr, uint32_t value)
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
if (debug) {
|
||||
printf("bcm2835_peri_write_nb paddr %08X, value %08X\n",
|
||||
(unsigned) paddr, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
*paddr = value;
|
||||
}
|
||||
}
|
||||
@@ -449,8 +436,7 @@ void bcm2835_delayMicroseconds(uint64_t micros)
|
||||
struct timespec t1;
|
||||
uint64_t start;
|
||||
|
||||
if (debug)
|
||||
{
|
||||
if (debug) {
|
||||
/* Cant access sytem timers in debug mode */
|
||||
printf("bcm2835_delayMicroseconds %lld\n", micros);
|
||||
return;
|
||||
@@ -461,8 +447,7 @@ void bcm2835_delayMicroseconds(uint64_t micros)
|
||||
*/
|
||||
start = bcm2835_st_read();
|
||||
|
||||
if (micros > 450)
|
||||
{
|
||||
if (micros > 450) {
|
||||
t1.tv_sec = 0;
|
||||
t1.tv_nsec = 1000 * (long)(micros - 200);
|
||||
nanosleep(&t1, NULL);
|
||||
@@ -478,20 +463,22 @@ void bcm2835_delayMicroseconds(uint64_t micros)
|
||||
/* Set the state of an output */
|
||||
void bcm2835_gpio_write(uint8_t pin, uint8_t on)
|
||||
{
|
||||
if (on)
|
||||
if (on) {
|
||||
bcm2835_gpio_set(pin);
|
||||
else
|
||||
} else {
|
||||
bcm2835_gpio_clr(pin);
|
||||
}
|
||||
}
|
||||
|
||||
/* Set the state of a all 32 outputs in the mask to on or off */
|
||||
void bcm2835_gpio_write_multi(uint32_t mask, uint8_t on)
|
||||
{
|
||||
if (on)
|
||||
if (on) {
|
||||
bcm2835_gpio_set_multi(mask);
|
||||
else
|
||||
} else {
|
||||
bcm2835_gpio_clr_multi(mask);
|
||||
}
|
||||
}
|
||||
|
||||
/* Set the state of a all 32 outputs in the mask to the values in value */
|
||||
void bcm2835_gpio_write_mask(uint32_t value, uint32_t mask)
|
||||
@@ -532,8 +519,9 @@ int bcm2835_spi_begin(void)
|
||||
{
|
||||
volatile uint32_t* paddr;
|
||||
|
||||
if (bcm2835_spi0 == MAP_FAILED)
|
||||
if (bcm2835_spi0 == MAP_FAILED) {
|
||||
return 0; /* bcm2835_init() failed, or not root */
|
||||
}
|
||||
|
||||
/* Set the SPI0 pins to the Alt 0 function to enable SPI0 access on them */
|
||||
bcm2835_gpio_fsel(RPI_GPIO_P1_26, BCM2835_GPIO_FSEL_ALT0); /* CE1 */
|
||||
@@ -642,17 +630,14 @@ void bcm2835_spi_transfernb(char* tbuf, char* rbuf, uint32_t len)
|
||||
bcm2835_peri_set_bits(paddr, BCM2835_SPI0_CS_TA, BCM2835_SPI0_CS_TA);
|
||||
|
||||
/* Use the FIFO's to reduce the interbyte times */
|
||||
while((TXCnt < len)||(RXCnt < len))
|
||||
{
|
||||
while((TXCnt < len)||(RXCnt < len)) {
|
||||
/* TX fifo not full, so add some more bytes */
|
||||
while(((bcm2835_peri_read(paddr) & BCM2835_SPI0_CS_TXD))&&(TXCnt < len ))
|
||||
{
|
||||
while(((bcm2835_peri_read(paddr) & BCM2835_SPI0_CS_TXD))&&(TXCnt < len )) {
|
||||
bcm2835_peri_write_nb(fifo, tbuf[TXCnt]);
|
||||
TXCnt++;
|
||||
}
|
||||
/* Rx fifo not empty, so get the next received bytes */
|
||||
while(((bcm2835_peri_read(paddr) & BCM2835_SPI0_CS_RXD))&&( RXCnt < len ))
|
||||
{
|
||||
while(((bcm2835_peri_read(paddr) & BCM2835_SPI0_CS_RXD))&&( RXCnt < len )) {
|
||||
rbuf[RXCnt] = bcm2835_peri_read_nb(fifo);
|
||||
RXCnt++;
|
||||
}
|
||||
@@ -684,8 +669,7 @@ void bcm2835_spi_writenb(char* tbuf, uint32_t len)
|
||||
/* Set TA = 1 */
|
||||
bcm2835_peri_set_bits(paddr, BCM2835_SPI0_CS_TA, BCM2835_SPI0_CS_TA);
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
for (i = 0; i < len; i++) {
|
||||
/* Maybe wait for TXD */
|
||||
while (!(bcm2835_peri_read(paddr) & BCM2835_SPI0_CS_TXD))
|
||||
;
|
||||
@@ -694,14 +678,16 @@ void bcm2835_spi_writenb(char* tbuf, uint32_t len)
|
||||
bcm2835_peri_write_nb(fifo, tbuf[i]);
|
||||
|
||||
/* Read from FIFO to prevent stalling */
|
||||
while (bcm2835_peri_read(paddr) & BCM2835_SPI0_CS_RXD)
|
||||
while (bcm2835_peri_read(paddr) & BCM2835_SPI0_CS_RXD) {
|
||||
(void) bcm2835_peri_read_nb(fifo);
|
||||
}
|
||||
}
|
||||
|
||||
/* Wait for DONE to be set */
|
||||
while (!(bcm2835_peri_read_nb(paddr) & BCM2835_SPI0_CS_DONE)) {
|
||||
while (bcm2835_peri_read(paddr) & BCM2835_SPI0_CS_RXD)
|
||||
while (bcm2835_peri_read(paddr) & BCM2835_SPI0_CS_RXD) {
|
||||
(void) bcm2835_peri_read_nb(fifo);
|
||||
}
|
||||
};
|
||||
|
||||
/* Set TA = 0, and also set the barrier */
|
||||
@@ -736,8 +722,9 @@ int bcm2835_i2c_begin(void)
|
||||
uint16_t cdiv;
|
||||
|
||||
if ( bcm2835_bsc0 == MAP_FAILED
|
||||
|| bcm2835_bsc1 == MAP_FAILED)
|
||||
|| bcm2835_bsc1 == MAP_FAILED) {
|
||||
return 0; /* bcm2835_init() failed, or not root */
|
||||
}
|
||||
|
||||
#ifdef I2C_V1
|
||||
volatile uint32_t* paddr = bcm2835_bsc0 + BCM2835_BSC_DIV/4;
|
||||
@@ -840,8 +827,7 @@ uint8_t bcm2835_i2c_write(const char * buf, uint32_t len)
|
||||
/* Set Data Length */
|
||||
bcm2835_peri_write(dlen, len);
|
||||
/* pre populate FIFO with max buffer */
|
||||
while( remaining && ( i < BCM2835_BSC_FIFO_SIZE ) )
|
||||
{
|
||||
while( remaining && ( i < BCM2835_BSC_FIFO_SIZE ) ) {
|
||||
bcm2835_peri_write_nb(fifo, buf[i]);
|
||||
i++;
|
||||
remaining--;
|
||||
@@ -851,10 +837,8 @@ uint8_t bcm2835_i2c_write(const char * buf, uint32_t len)
|
||||
bcm2835_peri_write(control, BCM2835_BSC_C_I2CEN | BCM2835_BSC_C_ST);
|
||||
|
||||
/* Transfer is over when BCM2835_BSC_S_DONE */
|
||||
while(!(bcm2835_peri_read(status) & BCM2835_BSC_S_DONE ))
|
||||
{
|
||||
while ( remaining && (bcm2835_peri_read(status) & BCM2835_BSC_S_TXD ))
|
||||
{
|
||||
while(!(bcm2835_peri_read(status) & BCM2835_BSC_S_DONE )) {
|
||||
while ( remaining && (bcm2835_peri_read(status) & BCM2835_BSC_S_TXD )) {
|
||||
/* Write to FIFO */
|
||||
bcm2835_peri_write(fifo, buf[i]);
|
||||
i++;
|
||||
@@ -863,20 +847,17 @@ uint8_t bcm2835_i2c_write(const char * buf, uint32_t len)
|
||||
}
|
||||
|
||||
/* Received a NACK */
|
||||
if (bcm2835_peri_read(status) & BCM2835_BSC_S_ERR)
|
||||
{
|
||||
if (bcm2835_peri_read(status) & BCM2835_BSC_S_ERR) {
|
||||
reason = BCM2835_I2C_REASON_ERROR_NACK;
|
||||
}
|
||||
|
||||
/* Received Clock Stretch Timeout */
|
||||
else if (bcm2835_peri_read(status) & BCM2835_BSC_S_CLKT)
|
||||
{
|
||||
else if (bcm2835_peri_read(status) & BCM2835_BSC_S_CLKT) {
|
||||
reason = BCM2835_I2C_REASON_ERROR_CLKT;
|
||||
}
|
||||
|
||||
/* Not all data is sent */
|
||||
else if (remaining)
|
||||
{
|
||||
else if (remaining) {
|
||||
reason = BCM2835_I2C_REASON_ERROR_DATA;
|
||||
}
|
||||
|
||||
@@ -914,11 +895,9 @@ uint8_t bcm2835_i2c_read(char* buf, uint32_t len)
|
||||
bcm2835_peri_write_nb(control, BCM2835_BSC_C_I2CEN | BCM2835_BSC_C_ST | BCM2835_BSC_C_READ);
|
||||
|
||||
/* wait for transfer to complete */
|
||||
while (!(bcm2835_peri_read_nb(status) & BCM2835_BSC_S_DONE))
|
||||
{
|
||||
while (!(bcm2835_peri_read_nb(status) & BCM2835_BSC_S_DONE)) {
|
||||
/* we must empty the FIFO as it is populated and not use any delay */
|
||||
while (bcm2835_peri_read_nb(status) & BCM2835_BSC_S_RXD)
|
||||
{
|
||||
while (bcm2835_peri_read_nb(status) & BCM2835_BSC_S_RXD) {
|
||||
/* Read from FIFO, no barrier */
|
||||
buf[i] = bcm2835_peri_read_nb(fifo);
|
||||
i++;
|
||||
@@ -927,8 +906,7 @@ uint8_t bcm2835_i2c_read(char* buf, uint32_t len)
|
||||
}
|
||||
|
||||
/* transfer has finished - grab any remaining stuff in FIFO */
|
||||
while (remaining && (bcm2835_peri_read_nb(status) & BCM2835_BSC_S_RXD))
|
||||
{
|
||||
while (remaining && (bcm2835_peri_read_nb(status) & BCM2835_BSC_S_RXD)) {
|
||||
/* Read from FIFO, no barrier */
|
||||
buf[i] = bcm2835_peri_read_nb(fifo);
|
||||
i++;
|
||||
@@ -936,20 +914,17 @@ uint8_t bcm2835_i2c_read(char* buf, uint32_t len)
|
||||
}
|
||||
|
||||
/* Received a NACK */
|
||||
if (bcm2835_peri_read(status) & BCM2835_BSC_S_ERR)
|
||||
{
|
||||
if (bcm2835_peri_read(status) & BCM2835_BSC_S_ERR) {
|
||||
reason = BCM2835_I2C_REASON_ERROR_NACK;
|
||||
}
|
||||
|
||||
/* Received Clock Stretch Timeout */
|
||||
else if (bcm2835_peri_read(status) & BCM2835_BSC_S_CLKT)
|
||||
{
|
||||
else if (bcm2835_peri_read(status) & BCM2835_BSC_S_CLKT) {
|
||||
reason = BCM2835_I2C_REASON_ERROR_CLKT;
|
||||
}
|
||||
|
||||
/* Not all data is received */
|
||||
else if (remaining)
|
||||
{
|
||||
else if (remaining) {
|
||||
reason = BCM2835_I2C_REASON_ERROR_DATA;
|
||||
}
|
||||
|
||||
@@ -990,12 +965,12 @@ uint8_t bcm2835_i2c_read_register_rs(char* regaddr, char* buf, uint32_t len)
|
||||
bcm2835_peri_write(control, BCM2835_BSC_C_I2CEN | BCM2835_BSC_C_ST);
|
||||
|
||||
/* poll for transfer has started */
|
||||
while ( !( bcm2835_peri_read(status) & BCM2835_BSC_S_TA ) )
|
||||
{
|
||||
while ( !( bcm2835_peri_read(status) & BCM2835_BSC_S_TA ) ) {
|
||||
/* Linux may cause us to miss entire transfer stage */
|
||||
if(bcm2835_peri_read(status) & BCM2835_BSC_S_DONE)
|
||||
if(bcm2835_peri_read(status) & BCM2835_BSC_S_DONE) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Send a repeated start with read bit set in address */
|
||||
bcm2835_peri_write(dlen, len);
|
||||
@@ -1005,11 +980,9 @@ uint8_t bcm2835_i2c_read_register_rs(char* regaddr, char* buf, uint32_t len)
|
||||
bcm2835_delayMicroseconds(i2c_byte_wait_us * 3);
|
||||
|
||||
/* wait for transfer to complete */
|
||||
while (!(bcm2835_peri_read(status) & BCM2835_BSC_S_DONE))
|
||||
{
|
||||
while (!(bcm2835_peri_read(status) & BCM2835_BSC_S_DONE)) {
|
||||
/* we must empty the FIFO as it is populated and not use any delay */
|
||||
while (remaining && bcm2835_peri_read(status) & BCM2835_BSC_S_RXD)
|
||||
{
|
||||
while (remaining && bcm2835_peri_read(status) & BCM2835_BSC_S_RXD) {
|
||||
/* Read from FIFO */
|
||||
buf[i] = bcm2835_peri_read(fifo);
|
||||
i++;
|
||||
@@ -1018,8 +991,7 @@ uint8_t bcm2835_i2c_read_register_rs(char* regaddr, char* buf, uint32_t len)
|
||||
}
|
||||
|
||||
/* transfer has finished - grab any remaining stuff in FIFO */
|
||||
while (remaining && (bcm2835_peri_read(status) & BCM2835_BSC_S_RXD))
|
||||
{
|
||||
while (remaining && (bcm2835_peri_read(status) & BCM2835_BSC_S_RXD)) {
|
||||
/* Read from FIFO */
|
||||
buf[i] = bcm2835_peri_read(fifo);
|
||||
i++;
|
||||
@@ -1027,20 +999,17 @@ uint8_t bcm2835_i2c_read_register_rs(char* regaddr, char* buf, uint32_t len)
|
||||
}
|
||||
|
||||
/* Received a NACK */
|
||||
if (bcm2835_peri_read(status) & BCM2835_BSC_S_ERR)
|
||||
{
|
||||
if (bcm2835_peri_read(status) & BCM2835_BSC_S_ERR) {
|
||||
reason = BCM2835_I2C_REASON_ERROR_NACK;
|
||||
}
|
||||
|
||||
/* Received Clock Stretch Timeout */
|
||||
else if (bcm2835_peri_read(status) & BCM2835_BSC_S_CLKT)
|
||||
{
|
||||
else if (bcm2835_peri_read(status) & BCM2835_BSC_S_CLKT) {
|
||||
reason = BCM2835_I2C_REASON_ERROR_CLKT;
|
||||
}
|
||||
|
||||
/* Not all data is sent */
|
||||
else if (remaining)
|
||||
{
|
||||
else if (remaining) {
|
||||
reason = BCM2835_I2C_REASON_ERROR_DATA;
|
||||
}
|
||||
|
||||
@@ -1080,8 +1049,7 @@ uint8_t bcm2835_i2c_write_read_rs(char* cmds, uint32_t cmds_len, char* buf, uint
|
||||
bcm2835_peri_write(dlen, cmds_len);
|
||||
|
||||
/* pre populate FIFO with max buffer */
|
||||
while( remaining && ( i < BCM2835_BSC_FIFO_SIZE ) )
|
||||
{
|
||||
while( remaining && ( i < BCM2835_BSC_FIFO_SIZE ) ) {
|
||||
bcm2835_peri_write_nb(fifo, cmds[i]);
|
||||
i++;
|
||||
remaining--;
|
||||
@@ -1091,12 +1059,12 @@ uint8_t bcm2835_i2c_write_read_rs(char* cmds, uint32_t cmds_len, char* buf, uint
|
||||
bcm2835_peri_write(control, BCM2835_BSC_C_I2CEN | BCM2835_BSC_C_ST);
|
||||
|
||||
/* poll for transfer has started (way to do repeated start, from BCM2835 datasheet) */
|
||||
while ( !( bcm2835_peri_read(status) & BCM2835_BSC_S_TA ) )
|
||||
{
|
||||
while ( !( bcm2835_peri_read(status) & BCM2835_BSC_S_TA ) ) {
|
||||
/* Linux may cause us to miss entire transfer stage */
|
||||
if(bcm2835_peri_read_nb(status) & BCM2835_BSC_S_DONE)
|
||||
if(bcm2835_peri_read_nb(status) & BCM2835_BSC_S_DONE) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
remaining = buf_len;
|
||||
i = 0;
|
||||
@@ -1109,11 +1077,9 @@ uint8_t bcm2835_i2c_write_read_rs(char* cmds, uint32_t cmds_len, char* buf, uint
|
||||
bcm2835_delayMicroseconds(i2c_byte_wait_us * (cmds_len + 1));
|
||||
|
||||
/* wait for transfer to complete */
|
||||
while (!(bcm2835_peri_read_nb(status) & BCM2835_BSC_S_DONE))
|
||||
{
|
||||
while (!(bcm2835_peri_read_nb(status) & BCM2835_BSC_S_DONE)) {
|
||||
/* we must empty the FIFO as it is populated and not use any delay */
|
||||
while (remaining && bcm2835_peri_read(status) & BCM2835_BSC_S_RXD)
|
||||
{
|
||||
while (remaining && bcm2835_peri_read(status) & BCM2835_BSC_S_RXD) {
|
||||
/* Read from FIFO, no barrier */
|
||||
buf[i] = bcm2835_peri_read_nb(fifo);
|
||||
i++;
|
||||
@@ -1122,8 +1088,7 @@ uint8_t bcm2835_i2c_write_read_rs(char* cmds, uint32_t cmds_len, char* buf, uint
|
||||
}
|
||||
|
||||
/* transfer has finished - grab any remaining stuff in FIFO */
|
||||
while (remaining && (bcm2835_peri_read(status) & BCM2835_BSC_S_RXD))
|
||||
{
|
||||
while (remaining && (bcm2835_peri_read(status) & BCM2835_BSC_S_RXD)) {
|
||||
/* Read from FIFO */
|
||||
buf[i] = bcm2835_peri_read(fifo);
|
||||
i++;
|
||||
@@ -1131,20 +1096,17 @@ uint8_t bcm2835_i2c_write_read_rs(char* cmds, uint32_t cmds_len, char* buf, uint
|
||||
}
|
||||
|
||||
/* Received a NACK */
|
||||
if (bcm2835_peri_read(status) & BCM2835_BSC_S_ERR)
|
||||
{
|
||||
if (bcm2835_peri_read(status) & BCM2835_BSC_S_ERR) {
|
||||
reason = BCM2835_I2C_REASON_ERROR_NACK;
|
||||
}
|
||||
|
||||
/* Received Clock Stretch Timeout */
|
||||
else if (bcm2835_peri_read(status) & BCM2835_BSC_S_CLKT)
|
||||
{
|
||||
else if (bcm2835_peri_read(status) & BCM2835_BSC_S_CLKT) {
|
||||
reason = BCM2835_I2C_REASON_ERROR_CLKT;
|
||||
}
|
||||
|
||||
/* Not all data is sent */
|
||||
else if (remaining)
|
||||
{
|
||||
else if (remaining) {
|
||||
reason = BCM2835_I2C_REASON_ERROR_DATA;
|
||||
}
|
||||
|
||||
@@ -1169,13 +1131,10 @@ uint64_t bcm2835_st_read(void)
|
||||
st = bcm2835_peri_read(paddr);
|
||||
|
||||
/* Test for overflow */
|
||||
if (st == hi)
|
||||
{
|
||||
if (st == hi) {
|
||||
st <<= 32;
|
||||
st += lo;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
st <<= 32;
|
||||
paddr = bcm2835_st + BCM2835_ST_CLO/4;
|
||||
st += bcm2835_peri_read(paddr);
|
||||
@@ -1197,8 +1156,9 @@ void bcm2835_st_delay(uint64_t offset_micros, uint64_t micros)
|
||||
void bcm2835_pwm_set_clock(uint32_t divisor)
|
||||
{
|
||||
if ( bcm2835_clk == MAP_FAILED
|
||||
|| bcm2835_pwm == MAP_FAILED)
|
||||
|| bcm2835_pwm == MAP_FAILED) {
|
||||
return; /* bcm2835_init() failed or not root */
|
||||
}
|
||||
|
||||
/* From Gerts code */
|
||||
divisor &= 0xfff;
|
||||
@@ -1206,43 +1166,47 @@ void bcm2835_pwm_set_clock(uint32_t divisor)
|
||||
bcm2835_peri_write(bcm2835_clk + BCM2835_PWMCLK_CNTL, BCM2835_PWM_PASSWRD | 0x01);
|
||||
bcm2835_delay(110); /* Prevents clock going slow */
|
||||
/* Wait for the clock to be not busy */
|
||||
while ((bcm2835_peri_read(bcm2835_clk + BCM2835_PWMCLK_CNTL) & 0x80) != 0)
|
||||
while ((bcm2835_peri_read(bcm2835_clk + BCM2835_PWMCLK_CNTL) & 0x80) != 0) {
|
||||
bcm2835_delay(1);
|
||||
}
|
||||
/* set the clock divider and enable PWM clock */
|
||||
bcm2835_peri_write(bcm2835_clk + BCM2835_PWMCLK_DIV, BCM2835_PWM_PASSWRD | (divisor << 12));
|
||||
bcm2835_peri_write(bcm2835_clk + BCM2835_PWMCLK_CNTL, BCM2835_PWM_PASSWRD | 0x11); /* Source=osc and enable */
|
||||
bcm2835_peri_write(bcm2835_clk + BCM2835_PWMCLK_CNTL,
|
||||
BCM2835_PWM_PASSWRD | 0x11); /* Source=osc and enable */
|
||||
}
|
||||
|
||||
void bcm2835_pwm_set_mode(uint8_t channel, uint8_t markspace, uint8_t enabled)
|
||||
{
|
||||
if ( bcm2835_clk == MAP_FAILED
|
||||
|| bcm2835_pwm == MAP_FAILED)
|
||||
|| bcm2835_pwm == MAP_FAILED) {
|
||||
return; /* bcm2835_init() failed or not root */
|
||||
}
|
||||
|
||||
uint32_t control = bcm2835_peri_read(bcm2835_pwm + BCM2835_PWM_CONTROL);
|
||||
|
||||
if (channel == 0)
|
||||
{
|
||||
if (markspace)
|
||||
if (channel == 0) {
|
||||
if (markspace) {
|
||||
control |= BCM2835_PWM0_MS_MODE;
|
||||
else
|
||||
} else {
|
||||
control &= ~BCM2835_PWM0_MS_MODE;
|
||||
if (enabled)
|
||||
}
|
||||
if (enabled) {
|
||||
control |= BCM2835_PWM0_ENABLE;
|
||||
else
|
||||
} else {
|
||||
control &= ~BCM2835_PWM0_ENABLE;
|
||||
}
|
||||
else if (channel == 1)
|
||||
{
|
||||
if (markspace)
|
||||
} else if (channel == 1) {
|
||||
if (markspace) {
|
||||
control |= BCM2835_PWM1_MS_MODE;
|
||||
else
|
||||
} else {
|
||||
control &= ~BCM2835_PWM1_MS_MODE;
|
||||
if (enabled)
|
||||
}
|
||||
if (enabled) {
|
||||
control |= BCM2835_PWM1_ENABLE;
|
||||
else
|
||||
} else {
|
||||
control &= ~BCM2835_PWM1_ENABLE;
|
||||
}
|
||||
}
|
||||
|
||||
/* If you use the barrier here, wierd things happen, and the commands dont work */
|
||||
bcm2835_peri_write_nb(bcm2835_pwm + BCM2835_PWM_CONTROL, control);
|
||||
@@ -1253,26 +1217,30 @@ void bcm2835_pwm_set_mode(uint8_t channel, uint8_t markspace, uint8_t enabled)
|
||||
void bcm2835_pwm_set_range(uint8_t channel, uint32_t range)
|
||||
{
|
||||
if ( bcm2835_clk == MAP_FAILED
|
||||
|| bcm2835_pwm == MAP_FAILED)
|
||||
|| bcm2835_pwm == MAP_FAILED) {
|
||||
return; /* bcm2835_init() failed or not root */
|
||||
}
|
||||
|
||||
if (channel == 0)
|
||||
if (channel == 0) {
|
||||
bcm2835_peri_write_nb(bcm2835_pwm + BCM2835_PWM0_RANGE, range);
|
||||
else if (channel == 1)
|
||||
} else if (channel == 1) {
|
||||
bcm2835_peri_write_nb(bcm2835_pwm + BCM2835_PWM1_RANGE, range);
|
||||
}
|
||||
}
|
||||
|
||||
void bcm2835_pwm_set_data(uint8_t channel, uint32_t data)
|
||||
{
|
||||
if ( bcm2835_clk == MAP_FAILED
|
||||
|| bcm2835_pwm == MAP_FAILED)
|
||||
|| bcm2835_pwm == MAP_FAILED) {
|
||||
return; /* bcm2835_init() failed or not root */
|
||||
}
|
||||
|
||||
if (channel == 0)
|
||||
if (channel == 0) {
|
||||
bcm2835_peri_write_nb(bcm2835_pwm + BCM2835_PWM0_DATA, data);
|
||||
else if (channel == 1)
|
||||
} else if (channel == 1) {
|
||||
bcm2835_peri_write_nb(bcm2835_pwm + BCM2835_PWM1_DATA, data);
|
||||
}
|
||||
}
|
||||
|
||||
/* Allocate page-aligned memory. */
|
||||
void *malloc_aligned(size_t size)
|
||||
@@ -1289,14 +1257,17 @@ void *malloc_aligned(size_t size)
|
||||
static void *mapmem(const char *msg, size_t size, int fd, off_t off)
|
||||
{
|
||||
void *map = mmap(NULL, size, (PROT_READ | PROT_WRITE), MAP_SHARED, fd, off);
|
||||
if (map == MAP_FAILED)
|
||||
if (map == MAP_FAILED) {
|
||||
logError("bcm2835_init: %s mmap failed: %s\n", msg, strerror(errno));
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
static void unmapmem(void **pmem, size_t size)
|
||||
{
|
||||
if (*pmem == MAP_FAILED) return;
|
||||
if (*pmem == MAP_FAILED) {
|
||||
return;
|
||||
}
|
||||
munmap(*pmem, size);
|
||||
*pmem = MAP_FAILED;
|
||||
}
|
||||
@@ -1308,8 +1279,7 @@ int bcm2835_init(void)
|
||||
int ok;
|
||||
FILE *fp;
|
||||
|
||||
if (debug)
|
||||
{
|
||||
if (debug) {
|
||||
bcm2835_peripherals = (uint32_t*)BCM2835_PERI_BASE;
|
||||
|
||||
bcm2835_pads = bcm2835_peripherals + BCM2835_GPIO_PADS/4;
|
||||
@@ -1326,15 +1296,16 @@ int bcm2835_init(void)
|
||||
/* Figure out the base and size of the peripheral address block
|
||||
// using the device-tree. Required for RPi2, optional for RPi 1
|
||||
*/
|
||||
if ((fp = fopen(BMC2835_RPI2_DT_FILENAME , "rb")))
|
||||
{
|
||||
if ((fp = fopen(BMC2835_RPI2_DT_FILENAME , "rb"))) {
|
||||
unsigned char buf[4];
|
||||
fseek(fp, BMC2835_RPI2_DT_PERI_BASE_ADDRESS_OFFSET, SEEK_SET);
|
||||
if (fread(buf, 1, sizeof(buf), fp) == sizeof(buf))
|
||||
if (fread(buf, 1, sizeof(buf), fp) == sizeof(buf)) {
|
||||
bcm2835_peripherals_base = (uint32_t *)(buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3] << 0);
|
||||
}
|
||||
fseek(fp, BMC2835_RPI2_DT_PERI_SIZE_OFFSET, SEEK_SET);
|
||||
if (fread(buf, 1, sizeof(buf), fp) == sizeof(buf))
|
||||
if (fread(buf, 1, sizeof(buf), fp) == sizeof(buf)) {
|
||||
bcm2835_peripherals_size = (buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3] << 0);
|
||||
}
|
||||
fclose(fp);
|
||||
}
|
||||
/* else we are prob on RPi 1 with BCM2835, and use the hardwired defaults */
|
||||
@@ -1346,19 +1317,20 @@ int bcm2835_init(void)
|
||||
*/
|
||||
memfd = -1;
|
||||
ok = 0;
|
||||
if (geteuid() == 0)
|
||||
{
|
||||
if (geteuid() == 0) {
|
||||
/* Open the master /dev/mem device */
|
||||
if ((memfd = open("/dev/mem", O_RDWR | O_SYNC) ) < 0)
|
||||
{
|
||||
if ((memfd = open("/dev/mem", O_RDWR | O_SYNC) ) < 0) {
|
||||
logError("bcm2835_init: Unable to open /dev/mem: %s\n",
|
||||
strerror(errno)) ;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Base of the peripherals block is mapped to VM */
|
||||
bcm2835_peripherals = mapmem("gpio", bcm2835_peripherals_size, memfd, (uint32_t)bcm2835_peripherals_base);
|
||||
if (bcm2835_peripherals == MAP_FAILED) goto exit;
|
||||
bcm2835_peripherals = mapmem("gpio", bcm2835_peripherals_size, memfd,
|
||||
(uint32_t)bcm2835_peripherals_base);
|
||||
if (bcm2835_peripherals == MAP_FAILED) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Now compute the base addresses of various peripherals,
|
||||
// which are at fixed offsets within the mapped peripherals block
|
||||
@@ -1374,13 +1346,10 @@ int bcm2835_init(void)
|
||||
bcm2835_st = bcm2835_peripherals + BCM2835_ST_BASE/4;
|
||||
|
||||
ok = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
/* Not root, try /dev/gpiomem */
|
||||
/* Open the master /dev/mem device */
|
||||
if ((memfd = open("/dev/gpiomem", O_RDWR | O_SYNC) ) < 0)
|
||||
{
|
||||
if ((memfd = open("/dev/gpiomem", O_RDWR | O_SYNC) ) < 0) {
|
||||
logError("bcm2835_init: Unable to open /dev/gpiomem: %s\n",
|
||||
strerror(errno)) ;
|
||||
goto exit;
|
||||
@@ -1388,18 +1357,23 @@ int bcm2835_init(void)
|
||||
|
||||
/* Base of the peripherals block is mapped to VM */
|
||||
bcm2835_peripherals_base = 0;
|
||||
bcm2835_peripherals = mapmem("gpio", bcm2835_peripherals_size, memfd, (uint32_t)bcm2835_peripherals_base);
|
||||
if (bcm2835_peripherals == MAP_FAILED) goto exit;
|
||||
bcm2835_peripherals = mapmem("gpio", bcm2835_peripherals_size, memfd,
|
||||
(uint32_t)bcm2835_peripherals_base);
|
||||
if (bcm2835_peripherals == MAP_FAILED) {
|
||||
goto exit;
|
||||
}
|
||||
bcm2835_gpio = bcm2835_peripherals;
|
||||
ok = 1;
|
||||
}
|
||||
|
||||
exit:
|
||||
if (memfd >= 0)
|
||||
if (memfd >= 0) {
|
||||
close(memfd);
|
||||
}
|
||||
|
||||
if (!ok)
|
||||
if (!ok) {
|
||||
bcm2835_close();
|
||||
}
|
||||
|
||||
return ok;
|
||||
}
|
||||
@@ -1407,7 +1381,9 @@ exit:
|
||||
/* Close this library and deallocate everything */
|
||||
int bcm2835_close(void)
|
||||
{
|
||||
if (debug) return 1; /* Success */
|
||||
if (debug) {
|
||||
return 1; /* Success */
|
||||
}
|
||||
|
||||
unmapmem((void**) &bcm2835_peripherals, bcm2835_peripherals_size);
|
||||
bcm2835_peripherals = MAP_FAILED;
|
||||
@@ -1431,8 +1407,9 @@ int main(int argc, char **argv)
|
||||
/* Be non-destructive */
|
||||
bcm2835_set_debug(1);
|
||||
|
||||
if (!bcm2835_init())
|
||||
if (!bcm2835_init()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Configure some GPIO pins fo some testing
|
||||
// Set RPI pin P1-11 to be an output
|
||||
@@ -1445,12 +1422,12 @@ int main(int argc, char **argv)
|
||||
/* And a low detect enable */
|
||||
bcm2835_gpio_len(RPI_GPIO_P1_15);
|
||||
/* and input hysteresis disabled on GPIOs 0 to 27 */
|
||||
bcm2835_gpio_set_pad(BCM2835_PAD_GROUP_GPIO_0_27, BCM2835_PAD_SLEW_RATE_UNLIMITED|BCM2835_PAD_DRIVE_8mA);
|
||||
bcm2835_gpio_set_pad(BCM2835_PAD_GROUP_GPIO_0_27,
|
||||
BCM2835_PAD_SLEW_RATE_UNLIMITED|BCM2835_PAD_DRIVE_8mA);
|
||||
|
||||
#if 1
|
||||
/* Blink */
|
||||
while (1)
|
||||
{
|
||||
while (1) {
|
||||
/* Turn it on */
|
||||
bcm2835_gpio_write(RPI_GPIO_P1_11, HIGH);
|
||||
|
||||
@@ -1467,8 +1444,7 @@ int main(int argc, char **argv)
|
||||
|
||||
#if 0
|
||||
/* Read input */
|
||||
while (1)
|
||||
{
|
||||
while (1) {
|
||||
/* Read some data */
|
||||
uint8_t value = bcm2835_gpio_lev(RPI_GPIO_P1_15);
|
||||
printf("read from pin 15: %d\n", value);
|
||||
@@ -1482,10 +1458,8 @@ int main(int argc, char **argv)
|
||||
/* Look for a low event detection
|
||||
// eds will be set whenever pin 15 goes low
|
||||
*/
|
||||
while (1)
|
||||
{
|
||||
if (bcm2835_gpio_eds(RPI_GPIO_P1_15))
|
||||
{
|
||||
while (1) {
|
||||
if (bcm2835_gpio_eds(RPI_GPIO_P1_15)) {
|
||||
/* Now clear the eds flag by setting it to 1 */
|
||||
bcm2835_gpio_set_eds(RPI_GPIO_P1_15);
|
||||
printf("low event detect for pin 15\n");
|
||||
@@ -1496,8 +1470,9 @@ int main(int argc, char **argv)
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!bcm2835_close())
|
||||
if (!bcm2835_close()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
+14
-25
@@ -577,8 +577,7 @@ extern volatile uint32_t *bcm2835_bsc1;
|
||||
/*! \brief bcm2835RegisterBase
|
||||
Register bases for bcm2835_regbase()
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
typedef enum {
|
||||
BCM2835_REGBASE_ST = 1, /*!< Base of the ST (System Timer) registers. */
|
||||
BCM2835_REGBASE_GPIO = 2, /*!< Base of the GPIO registers. */
|
||||
BCM2835_REGBASE_PWM = 3, /*!< Base of the PWM registers. */
|
||||
@@ -635,8 +634,7 @@ typedef enum
|
||||
/*! \brief bcm2835PortFunction
|
||||
Port function select modes for bcm2835_gpio_fsel()
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
typedef enum {
|
||||
BCM2835_GPIO_FSEL_INPT = 0x00, /*!< Input 0b000 */
|
||||
BCM2835_GPIO_FSEL_OUTP = 0x01, /*!< Output 0b001 */
|
||||
BCM2835_GPIO_FSEL_ALT0 = 0x04, /*!< Alternate function 0 0b100 */
|
||||
@@ -651,8 +649,7 @@ typedef enum
|
||||
/*! \brief bcm2835PUDControl
|
||||
Pullup/Pulldown defines for bcm2835_gpio_pud()
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
typedef enum {
|
||||
BCM2835_GPIO_PUD_OFF = 0x00, /*!< Off ? disable pull-up/down 0b00 */
|
||||
BCM2835_GPIO_PUD_DOWN = 0x01, /*!< Enable Pull Down control 0b01 */
|
||||
BCM2835_GPIO_PUD_UP = 0x02 /*!< Enable Pull Up control 0b10 */
|
||||
@@ -679,8 +676,7 @@ typedef enum
|
||||
/*! \brief bcm2835PadGroup
|
||||
Pad group specification for bcm2835_gpio_pad()
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
typedef enum {
|
||||
BCM2835_PAD_GROUP_GPIO_0_27 = 0, /*!< Pad group for GPIO pads 0 to 27 */
|
||||
BCM2835_PAD_GROUP_GPIO_28_45 = 1, /*!< Pad group for GPIO pads 28 to 45 */
|
||||
BCM2835_PAD_GROUP_GPIO_46_53 = 2 /*!< Pad group for GPIO pads 46 to 53 */
|
||||
@@ -700,8 +696,7 @@ typedef enum
|
||||
If you are using the RPi Compute Module, just use the GPIO number: there is no need to use one of these
|
||||
symbolic names
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
typedef enum {
|
||||
RPI_GPIO_P1_03 = 0, /*!< Version 1, Pin P1-03 */
|
||||
RPI_GPIO_P1_05 = 1, /*!< Version 1, Pin P1-05 */
|
||||
RPI_GPIO_P1_07 = 4, /*!< Version 1, Pin P1-07 */
|
||||
@@ -825,8 +820,7 @@ typedef enum
|
||||
/*! \brief bcm2835SPIBitOrder SPI Bit order
|
||||
Specifies the SPI data bit ordering for bcm2835_spi_setBitOrder()
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
typedef enum {
|
||||
BCM2835_SPI_BIT_ORDER_LSBFIRST = 0, /*!< LSB First */
|
||||
BCM2835_SPI_BIT_ORDER_MSBFIRST = 1 /*!< MSB First */
|
||||
} bcm2835SPIBitOrder;
|
||||
@@ -834,8 +828,7 @@ typedef enum
|
||||
/*! \brief SPI Data mode
|
||||
Specify the SPI data mode to be passed to bcm2835_spi_setDataMode()
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
typedef enum {
|
||||
BCM2835_SPI_MODE0 = 0, /*!< CPOL = 0, CPHA = 0 */
|
||||
BCM2835_SPI_MODE1 = 1, /*!< CPOL = 0, CPHA = 1 */
|
||||
BCM2835_SPI_MODE2 = 2, /*!< CPOL = 1, CPHA = 0 */
|
||||
@@ -845,8 +838,7 @@ typedef enum
|
||||
/*! \brief bcm2835SPIChipSelect
|
||||
Specify the SPI chip select pin(s)
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
typedef enum {
|
||||
BCM2835_SPI_CS0 = 0, /*!< Chip Select 0 */
|
||||
BCM2835_SPI_CS1 = 1, /*!< Chip Select 1 */
|
||||
BCM2835_SPI_CS2 = 2, /*!< Chip Select 2 (ie pins CS1 and CS2 are asserted) */
|
||||
@@ -860,8 +852,7 @@ typedef enum
|
||||
It is reported that (contrary to the documentation) any even divider may used.
|
||||
The frequencies shown for each divider have been confirmed by measurement.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
typedef enum {
|
||||
BCM2835_SPI_CLOCK_DIVIDER_65536 = 0, /*!< 65536 = 262.144us = 3.814697260kHz */
|
||||
BCM2835_SPI_CLOCK_DIVIDER_32768 = 32768, /*!< 32768 = 131.072us = 7.629394531kHz */
|
||||
BCM2835_SPI_CLOCK_DIVIDER_16384 = 16384, /*!< 16384 = 65.536us = 15.25878906kHz */
|
||||
@@ -922,8 +913,7 @@ typedef enum
|
||||
Specifies the divider used to generate the I2C clock from the system clock.
|
||||
Clock divided is based on nominal base clock rate of 250MHz
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
typedef enum {
|
||||
BCM2835_I2C_CLOCK_DIVIDER_2500 = 2500, /*!< 2500 = 10us = 100 kHz */
|
||||
BCM2835_I2C_CLOCK_DIVIDER_626 = 626, /*!< 622 = 2.504us = 399.3610 kHz */
|
||||
BCM2835_I2C_CLOCK_DIVIDER_150 = 150, /*!< 150 = 60ns = 1.666 MHz (default at reset) */
|
||||
@@ -933,8 +923,7 @@ typedef enum
|
||||
/*! \brief bcm2835I2CReasonCodes
|
||||
Specifies the reason codes for the bcm2835_i2c_write and bcm2835_i2c_read functions.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
typedef enum {
|
||||
BCM2835_I2C_REASON_OK = 0x00, /*!< Success */
|
||||
BCM2835_I2C_REASON_ERROR_NACK = 0x01, /*!< Received a NACK */
|
||||
BCM2835_I2C_REASON_ERROR_CLKT = 0x02, /*!< Received Clock Stretch Timeout */
|
||||
@@ -994,8 +983,7 @@ typedef enum
|
||||
Clock divided is based on nominal PWM base clock rate of 19.2MHz
|
||||
The frequencies shown for each divider have been confirmed by measurement
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
typedef enum {
|
||||
BCM2835_PWM_CLOCK_DIVIDER_2048 = 2048, /*!< 2048 = 9.375kHz */
|
||||
BCM2835_PWM_CLOCK_DIVIDER_1024 = 1024, /*!< 1024 = 18.75kHz */
|
||||
BCM2835_PWM_CLOCK_DIVIDER_512 = 512, /*!< 512 = 37.5kHz */
|
||||
@@ -1578,7 +1566,8 @@ extern "C" {
|
||||
\param[in] buf_len Number of bytes to receive in the buf buffer.
|
||||
\return reason see \ref bcm2835I2CReasonCodes
|
||||
*/
|
||||
extern uint8_t bcm2835_i2c_write_read_rs(char* cmds, uint32_t cmds_len, char* buf, uint32_t buf_len);
|
||||
extern uint8_t bcm2835_i2c_write_read_rs(char* cmds, uint32_t cmds_len, char* buf,
|
||||
uint32_t buf_len);
|
||||
|
||||
/*! @} */
|
||||
|
||||
|
||||
+96
-31
@@ -35,8 +35,9 @@ int get_rpi_info(rpi_info *info)
|
||||
int found = 0;
|
||||
int len;
|
||||
|
||||
if ((fp = fopen("/proc/cpuinfo", "r")) == NULL)
|
||||
if ((fp = fopen("/proc/cpuinfo", "r")) == NULL) {
|
||||
return -1;
|
||||
}
|
||||
while(!feof(fp)) {
|
||||
fgets(buffer, sizeof(buffer), fp);
|
||||
sscanf(buffer, "Hardware : %s", hardware);
|
||||
@@ -51,48 +52,111 @@ int get_rpi_info(rpi_info *info)
|
||||
}
|
||||
fclose(fp);
|
||||
|
||||
if (!found)
|
||||
if (!found) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((len = strlen(revision)) == 0)
|
||||
if ((len = strlen(revision)) == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (len >= 6 && strtol((char[]){revision[len-6],0}, NULL, 16) & 8) {
|
||||
if (len >= 6 && strtol((char[]) {
|
||||
revision[len-6],0
|
||||
}, NULL, 16) & 8) {
|
||||
// new scheme
|
||||
//info->rev = revision[len-1]-'0';
|
||||
strcpy(info->revision, revision);
|
||||
switch (revision[len-2]) {
|
||||
case '0': info->type = "Model A"; info->p1_revision = 2; break;
|
||||
case '1': info->type = "Model B"; info->p1_revision = 2; break;
|
||||
case '2': info->type = "Model A+"; info->p1_revision = 3; break;
|
||||
case '3': info->type = "Model B+"; info->p1_revision = 3; break;
|
||||
case '4': info->type = "Pi 2 Model B"; info->p1_revision = 3; break;
|
||||
case '5': info->type = "Alpha"; info->p1_revision = 3; break;
|
||||
case '6': info->type = "Compute"; info->p1_revision = 0; break;
|
||||
case '8': info->type = "Pi 3 Model B"; info->p1_revision = 3; break;
|
||||
case '9': info->type = "Zero"; info->p1_revision = 3; break;
|
||||
default : info->type = "Unknown"; info->p1_revision = 3; break;
|
||||
case '0':
|
||||
info->type = "Model A";
|
||||
info->p1_revision = 2;
|
||||
break;
|
||||
case '1':
|
||||
info->type = "Model B";
|
||||
info->p1_revision = 2;
|
||||
break;
|
||||
case '2':
|
||||
info->type = "Model A+";
|
||||
info->p1_revision = 3;
|
||||
break;
|
||||
case '3':
|
||||
info->type = "Model B+";
|
||||
info->p1_revision = 3;
|
||||
break;
|
||||
case '4':
|
||||
info->type = "Pi 2 Model B";
|
||||
info->p1_revision = 3;
|
||||
break;
|
||||
case '5':
|
||||
info->type = "Alpha";
|
||||
info->p1_revision = 3;
|
||||
break;
|
||||
case '6':
|
||||
info->type = "Compute";
|
||||
info->p1_revision = 0;
|
||||
break;
|
||||
case '8':
|
||||
info->type = "Pi 3 Model B";
|
||||
info->p1_revision = 3;
|
||||
break;
|
||||
case '9':
|
||||
info->type = "Zero";
|
||||
info->p1_revision = 3;
|
||||
break;
|
||||
default :
|
||||
info->type = "Unknown";
|
||||
info->p1_revision = 3;
|
||||
break;
|
||||
}
|
||||
switch (revision[len-4]) {
|
||||
case '0': info->processor = "BCM2835"; break;
|
||||
case '1': info->processor = "BCM2836"; break;
|
||||
case '2': info->processor = "BCM2837"; break;
|
||||
default : info->processor = "Unknown"; break;
|
||||
case '0':
|
||||
info->processor = "BCM2835";
|
||||
break;
|
||||
case '1':
|
||||
info->processor = "BCM2836";
|
||||
break;
|
||||
case '2':
|
||||
info->processor = "BCM2837";
|
||||
break;
|
||||
default :
|
||||
info->processor = "Unknown";
|
||||
break;
|
||||
}
|
||||
switch (revision[len-5]) {
|
||||
case '0': info->manufacturer = "Sony"; break;
|
||||
case '1': info->manufacturer = "Egoman"; break;
|
||||
case '2': info->manufacturer = "Embest"; break;
|
||||
case '4': info->manufacturer = "Embest"; break;
|
||||
default : info->manufacturer = "Unknown"; break;
|
||||
case '0':
|
||||
info->manufacturer = "Sony";
|
||||
break;
|
||||
case '1':
|
||||
info->manufacturer = "Egoman";
|
||||
break;
|
||||
case '2':
|
||||
info->manufacturer = "Embest";
|
||||
break;
|
||||
case '4':
|
||||
info->manufacturer = "Embest";
|
||||
break;
|
||||
default :
|
||||
info->manufacturer = "Unknown";
|
||||
break;
|
||||
}
|
||||
switch (strtol((char[]){revision[len-6],0}, NULL, 16) & 7) {
|
||||
case 0: info->ram = "256M"; break;
|
||||
case 1: info->ram = "512M"; break;
|
||||
case 2: info->ram = "1024M"; break;
|
||||
default: info->ram = "Unknown"; break;
|
||||
switch (strtol((char[]) {
|
||||
revision[len-6],0
|
||||
}, NULL, 16) & 7) {
|
||||
case 0:
|
||||
info->ram = "256M";
|
||||
break;
|
||||
case 1:
|
||||
info->ram = "512M";
|
||||
break;
|
||||
case 2:
|
||||
info->ram = "1024M";
|
||||
break;
|
||||
default:
|
||||
info->ram = "Unknown";
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
// old scheme
|
||||
info->ram = "Unknown";
|
||||
info->manufacturer = "Unknown";
|
||||
@@ -101,10 +165,11 @@ int get_rpi_info(rpi_info *info)
|
||||
strcpy(info->revision, revision);
|
||||
|
||||
// get last four characters (ignore preceeding 1000 for overvolt)
|
||||
if (len > 4)
|
||||
if (len > 4) {
|
||||
rev = (char *)&revision+len-4;
|
||||
else
|
||||
} else {
|
||||
rev = revision;
|
||||
}
|
||||
|
||||
if ((strcmp(rev, "0002") == 0) ||
|
||||
(strcmp(rev, "0003") == 0)) {
|
||||
|
||||
@@ -28,8 +28,7 @@ SOFTWARE.
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
typedef struct {
|
||||
int p1_revision;
|
||||
char *ram;
|
||||
char *manufacturer;
|
||||
|
||||
@@ -39,10 +39,11 @@ int piHiPri (const int pri)
|
||||
|
||||
memset (&sched, 0, sizeof(sched)) ;
|
||||
|
||||
if (pri > sched_get_priority_max (SCHED_RR))
|
||||
if (pri > sched_get_priority_max (SCHED_RR)) {
|
||||
sched.sched_priority = sched_get_priority_max (SCHED_RR) ;
|
||||
else
|
||||
} else {
|
||||
sched.sched_priority = pri ;
|
||||
}
|
||||
|
||||
return sched_setscheduler (0, SCHED_RR, &sched) ;
|
||||
}
|
||||
|
||||
+35
-17
@@ -55,8 +55,7 @@ static pthread_t *threadIds[64] = {NULL};
|
||||
|
||||
// sysFds:
|
||||
// Map a file descriptor from the /sys/class/gpio/gpioX/value
|
||||
static int sysFds[64] =
|
||||
{
|
||||
static int sysFds[64] = {
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
@@ -95,7 +94,8 @@ int get_gpio_number(uint8_t physPin, uint8_t *gpio)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *interruptHandler(void *args) {
|
||||
void *interruptHandler(void *args)
|
||||
{
|
||||
int fd, ret;
|
||||
struct pollfd polls;
|
||||
char c;
|
||||
@@ -142,7 +142,8 @@ void *interruptHandler(void *args) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void rpi_util::pinMode(uint8_t physPin, uint8_t mode) {
|
||||
void rpi_util::pinMode(uint8_t physPin, uint8_t mode)
|
||||
{
|
||||
uint8_t gpioPin;
|
||||
|
||||
if (get_gpio_number(physPin, &gpioPin)) {
|
||||
@@ -158,7 +159,8 @@ void rpi_util::pinMode(uint8_t physPin, uint8_t mode) {
|
||||
}
|
||||
}
|
||||
|
||||
void rpi_util::digitalWrite(uint8_t physPin, uint8_t value) {
|
||||
void rpi_util::digitalWrite(uint8_t physPin, uint8_t value)
|
||||
{
|
||||
uint8_t gpioPin;
|
||||
|
||||
if (get_gpio_number(physPin, &gpioPin)) {
|
||||
@@ -178,7 +180,8 @@ void rpi_util::digitalWrite(uint8_t physPin, uint8_t value) {
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t rpi_util::digitalRead(uint8_t physPin) {
|
||||
uint8_t rpi_util::digitalRead(uint8_t physPin)
|
||||
{
|
||||
uint8_t gpioPin;
|
||||
|
||||
if (get_gpio_number(physPin, &gpioPin)) {
|
||||
@@ -194,7 +197,8 @@ uint8_t rpi_util::digitalRead(uint8_t physPin) {
|
||||
}
|
||||
}
|
||||
|
||||
void rpi_util::attachInterrupt(uint8_t physPin, void (*func)(), uint8_t mode) {
|
||||
void rpi_util::attachInterrupt(uint8_t physPin, void (*func)(), uint8_t mode)
|
||||
{
|
||||
FILE *fd;
|
||||
char fName[40];
|
||||
char c;
|
||||
@@ -228,7 +232,8 @@ void rpi_util::attachInterrupt(uint8_t physPin, void (*func)(), uint8_t mode) {
|
||||
|
||||
snprintf(fName, sizeof(fName), "/sys/class/gpio/gpio%d/direction", gpioPin) ;
|
||||
if ((fd = fopen (fName, "w")) == NULL) {
|
||||
fprintf (stderr, "attachInterrupt: Unable to open GPIO direction interface for pin %d: %s\n", physPin, strerror(errno));
|
||||
fprintf (stderr, "attachInterrupt: Unable to open GPIO direction interface for pin %d: %s\n",
|
||||
physPin, strerror(errno));
|
||||
exit(1) ;
|
||||
}
|
||||
fprintf(fd, "in\n") ;
|
||||
@@ -236,14 +241,23 @@ void rpi_util::attachInterrupt(uint8_t physPin, void (*func)(), uint8_t mode) {
|
||||
|
||||
snprintf(fName, sizeof(fName), "/sys/class/gpio/gpio%d/edge", gpioPin) ;
|
||||
if ((fd = fopen(fName, "w")) == NULL) {
|
||||
fprintf (stderr, "attachInterrupt: Unable to open GPIO edge interface for pin %d: %s\n", physPin, strerror(errno));
|
||||
fprintf (stderr, "attachInterrupt: Unable to open GPIO edge interface for pin %d: %s\n", physPin,
|
||||
strerror(errno));
|
||||
exit(1) ;
|
||||
}
|
||||
switch (mode) {
|
||||
case CHANGE: fprintf(fd, "both\n"); break;
|
||||
case FALLING: fprintf(fd, "falling\n"); break;
|
||||
case RISING: fprintf(fd, "rising\n"); break;
|
||||
case NONE: fprintf(fd, "none\n"); break;
|
||||
case CHANGE:
|
||||
fprintf(fd, "both\n");
|
||||
break;
|
||||
case FALLING:
|
||||
fprintf(fd, "falling\n");
|
||||
break;
|
||||
case RISING:
|
||||
fprintf(fd, "rising\n");
|
||||
break;
|
||||
case NONE:
|
||||
fprintf(fd, "none\n");
|
||||
break;
|
||||
default:
|
||||
logError("attachInterrupt: Invalid mode\n");
|
||||
fclose(fd);
|
||||
@@ -275,7 +289,8 @@ void rpi_util::attachInterrupt(uint8_t physPin, void (*func)(), uint8_t mode) {
|
||||
pthread_create(threadIds[gpioPin], NULL, interruptHandler, (void *)threadArgs);
|
||||
}
|
||||
|
||||
void rpi_util::detachInterrupt(uint8_t physPin) {
|
||||
void rpi_util::detachInterrupt(uint8_t physPin)
|
||||
{
|
||||
uint8_t gpioPin;
|
||||
|
||||
if (get_gpio_number(physPin, &gpioPin)) {
|
||||
@@ -305,18 +320,21 @@ void rpi_util::detachInterrupt(uint8_t physPin) {
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
uint8_t rpi_util::digitalPinToInterrupt(uint8_t physPin) {
|
||||
uint8_t rpi_util::digitalPinToInterrupt(uint8_t physPin)
|
||||
{
|
||||
// No need to convert the pin to gpio, we do it in attachInterrupt().
|
||||
return physPin;
|
||||
}
|
||||
|
||||
void rpi_util::interrupts() {
|
||||
void rpi_util::interrupts()
|
||||
{
|
||||
pthread_mutex_lock(&intMutex);
|
||||
interruptsEnabled = true;
|
||||
pthread_mutex_unlock(&intMutex);
|
||||
}
|
||||
|
||||
void rpi_util::noInterrupts() {
|
||||
void rpi_util::noInterrupts()
|
||||
{
|
||||
pthread_mutex_lock(&intMutex);
|
||||
interruptsEnabled = false;
|
||||
pthread_mutex_unlock(&intMutex);
|
||||
|
||||
@@ -29,7 +29,8 @@ const int pin_to_gpio_rev1[41] = {-1, -1, -1, 0, -1, 1, -1, 4, 14, -1, 15, 17, 1
|
||||
const int pin_to_gpio_rev2[41] = {-1, -1, -1, 2, -1, 3, -1, 4, 14, -1, 15, 17, 18, 27, -1, 22, 23, -1, 24, 10, -1, 9, 25, 11, 8, -1, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 };
|
||||
const int pin_to_gpio_rev3[41] = {-1, -1, -1, 2, -1, 3, -1, 4, 14, -1, 15, 17, 18, 27, -1, 22, 23, -1, 24, 10, -1, 9, 25, 11, 8, -1, 7, -1, -1, 5, -1, 6, 12, 13, -1, 19, 16, 26, 20, -1, 21 };
|
||||
|
||||
namespace rpi_util {
|
||||
namespace rpi_util
|
||||
{
|
||||
|
||||
typedef enum {
|
||||
LSBFIRST = BCM2835_SPI_BIT_ORDER_LSBFIRST,
|
||||
|
||||
@@ -47,13 +47,15 @@ uint8_t SPIFlash::UNIQUEID[8];
|
||||
/// get this from the datasheet of your flash chip
|
||||
/// Example for Atmel-Adesto 4Mbit AT25DF041A: 0x1F44 (page 27: http://www.adestotech.com/sites/default/files/datasheets/doc3668.pdf)
|
||||
/// Example for Winbond 4Mbit W25X40CL: 0xEF30 (page 14: http://www.winbond.com/NR/rdonlyres/6E25084C-0BFE-4B25-903D-AE10221A0929/0/W25X40CL.pdf)
|
||||
SPIFlash::SPIFlash(uint8_t slaveSelectPin, uint16_t jedecID) {
|
||||
SPIFlash::SPIFlash(uint8_t slaveSelectPin, uint16_t jedecID)
|
||||
{
|
||||
_slaveSelectPin = slaveSelectPin;
|
||||
_jedecID = jedecID;
|
||||
}
|
||||
|
||||
/// Select the flash chip
|
||||
void SPIFlash::select() {
|
||||
void SPIFlash::select()
|
||||
{
|
||||
//save current SPI settings
|
||||
#ifndef SPI_HAS_TRANSACTION
|
||||
noInterrupts();
|
||||
@@ -69,14 +71,16 @@ void SPIFlash::select() {
|
||||
// set FLASH SPI settings
|
||||
SPI.setDataMode(SPI_MODE0);
|
||||
SPI.setBitOrder(MSBFIRST);
|
||||
SPI.setClockDivider(SPI_CLOCK_DIV4); //decided to slow down from DIV2 after SPI stalling in some instances, especially visible on mega1284p when RFM69 and FLASH chip both present
|
||||
SPI.setClockDivider(
|
||||
SPI_CLOCK_DIV4); //decided to slow down from DIV2 after SPI stalling in some instances, especially visible on mega1284p when RFM69 and FLASH chip both present
|
||||
SPI.begin();
|
||||
#endif
|
||||
hwDigitalWrite(_slaveSelectPin, LOW);
|
||||
}
|
||||
|
||||
/// UNselect the flash chip
|
||||
void SPIFlash::unselect() {
|
||||
void SPIFlash::unselect()
|
||||
{
|
||||
hwDigitalWrite(_slaveSelectPin, HIGH);
|
||||
//restore SPI settings to what they were before talking to the FLASH chip
|
||||
#ifdef SPI_HAS_TRANSACTION
|
||||
@@ -150,7 +154,8 @@ uint8_t* SPIFlash::readUniqueId()
|
||||
}
|
||||
|
||||
/// read 1 byte from flash memory
|
||||
uint8_t SPIFlash::readByte(uint32_t addr) {
|
||||
uint8_t SPIFlash::readByte(uint32_t addr)
|
||||
{
|
||||
command(SPIFLASH_ARRAYREADLOWFREQ);
|
||||
SPI.transfer(addr >> 16);
|
||||
SPI.transfer(addr >> 8);
|
||||
@@ -161,7 +166,8 @@ uint8_t SPIFlash::readByte(uint32_t addr) {
|
||||
}
|
||||
|
||||
/// read unlimited # of bytes
|
||||
void SPIFlash::readBytes(uint32_t addr, void* buf, uint16_t len) {
|
||||
void SPIFlash::readBytes(uint32_t addr, void* buf, uint16_t len)
|
||||
{
|
||||
command(SPIFLASH_ARRAYREAD);
|
||||
SPI.transfer(addr >> 16);
|
||||
SPI.transfer(addr >> 8);
|
||||
@@ -174,13 +180,13 @@ void SPIFlash::readBytes(uint32_t addr, void* buf, uint16_t len) {
|
||||
}
|
||||
|
||||
/// Send a command to the flash chip, pass TRUE for isWrite when its a write command
|
||||
void SPIFlash::command(uint8_t cmd, boolean isWrite){
|
||||
void SPIFlash::command(uint8_t cmd, boolean isWrite)
|
||||
{
|
||||
#if defined(__AVR_ATmega32U4__) // Arduino Leonardo, MoteinoLeo
|
||||
DDRB |= B00000001; // Make sure the SS pin (PB0 - used by RFM12B on MoteinoLeo R1) is set as output HIGH!
|
||||
PORTB |= B00000001;
|
||||
#endif
|
||||
if (isWrite)
|
||||
{
|
||||
if (isWrite) {
|
||||
command(SPIFLASH_WRITEENABLE); // Write Enable
|
||||
unselect();
|
||||
}
|
||||
@@ -221,7 +227,8 @@ uint8_t SPIFlash::readStatus()
|
||||
/// Write 1 byte to flash memory
|
||||
/// WARNING: you can only write to previously erased memory locations (see datasheet)
|
||||
/// use the block erase commands to first clear memory (write 0xFFs)
|
||||
void SPIFlash::writeByte(uint32_t addr, uint8_t byt) {
|
||||
void SPIFlash::writeByte(uint32_t addr, uint8_t byt)
|
||||
{
|
||||
command(SPIFLASH_BYTEPAGEPROGRAM, true); // Byte/Page Program
|
||||
SPI.transfer(addr >> 16);
|
||||
SPI.transfer(addr >> 8);
|
||||
@@ -235,7 +242,8 @@ void SPIFlash::writeByte(uint32_t addr, uint8_t byt) {
|
||||
/// use the block erase commands to first clear memory (write 0xFFs)
|
||||
/// This version handles both page alignment and data blocks larger than 256 bytes.
|
||||
/// See documentation of #MY_SPIFLASH_SST25TYPE define for more information
|
||||
void SPIFlash::writeBytes(uint32_t addr, const void* buf, uint16_t len) {
|
||||
void SPIFlash::writeBytes(uint32_t addr, const void* buf, uint16_t len)
|
||||
{
|
||||
#ifdef MY_SPIFLASH_SST25TYPE
|
||||
//SST25 Type of Flash does not support Page Programming but AAI Word Programming
|
||||
uint16_t i=0;
|
||||
@@ -285,8 +293,7 @@ void SPIFlash::writeBytes(uint32_t addr, const void* buf, uint16_t len) {
|
||||
uint16_t n;
|
||||
uint16_t maxBytes = 256-(addr%256); // force the first set of bytes to stay within the first page
|
||||
uint16_t offset = 0;
|
||||
while (len>0)
|
||||
{
|
||||
while (len>0) {
|
||||
n = (len<=maxBytes) ? len : maxBytes;
|
||||
command(SPIFLASH_BYTEPAGEPROGRAM, true); // Byte/Page Program
|
||||
SPI.transfer(addr >> 16);
|
||||
@@ -312,13 +319,15 @@ void SPIFlash::writeBytes(uint32_t addr, const void* buf, uint16_t len) {
|
||||
/// other things and later check if the chip is done with busy()
|
||||
/// note that any command will first wait for chip to become available using busy()
|
||||
/// so no need to do that twice
|
||||
void SPIFlash::chipErase() {
|
||||
void SPIFlash::chipErase()
|
||||
{
|
||||
command(SPIFLASH_CHIPERASE, true);
|
||||
unselect();
|
||||
}
|
||||
|
||||
/// erase a 4Kbyte block
|
||||
void SPIFlash::blockErase4K(uint32_t addr) {
|
||||
void SPIFlash::blockErase4K(uint32_t addr)
|
||||
{
|
||||
command(SPIFLASH_BLOCKERASE_4K, true); // Block Erase
|
||||
SPI.transfer(addr >> 16);
|
||||
SPI.transfer(addr >> 8);
|
||||
@@ -327,7 +336,8 @@ void SPIFlash::blockErase4K(uint32_t addr) {
|
||||
}
|
||||
|
||||
/// erase a 32Kbyte block
|
||||
void SPIFlash::blockErase32K(uint32_t addr) {
|
||||
void SPIFlash::blockErase32K(uint32_t addr)
|
||||
{
|
||||
command(SPIFLASH_BLOCKERASE_32K, true); // Block Erase
|
||||
SPI.transfer(addr >> 16);
|
||||
SPI.transfer(addr >> 8);
|
||||
@@ -335,17 +345,20 @@ void SPIFlash::blockErase32K(uint32_t addr) {
|
||||
unselect();
|
||||
}
|
||||
|
||||
void SPIFlash::sleep() {
|
||||
void SPIFlash::sleep()
|
||||
{
|
||||
command(SPIFLASH_SLEEP);
|
||||
unselect();
|
||||
}
|
||||
|
||||
void SPIFlash::wakeup() {
|
||||
void SPIFlash::wakeup()
|
||||
{
|
||||
command(SPIFLASH_WAKE);
|
||||
unselect();
|
||||
}
|
||||
|
||||
/// cleanup
|
||||
void SPIFlash::end() {
|
||||
void SPIFlash::end()
|
||||
{
|
||||
SPI.end();
|
||||
}
|
||||
|
||||
@@ -112,17 +112,20 @@
|
||||
#endif
|
||||
|
||||
/** SPIFlash class */
|
||||
class SPIFlash {
|
||||
class SPIFlash
|
||||
{
|
||||
public:
|
||||
static uint8_t UNIQUEID[8]; //!< Storage for unique identifier
|
||||
SPIFlash(uint8_t slaveSelectPin, uint16_t jedecID=0); //!< Constructor
|
||||
boolean initialize(); //!< setup SPI, read device ID etc...
|
||||
void command(uint8_t cmd, boolean isWrite=false); //!< Send a command to the flash chip, pass TRUE for isWrite when its a write command
|
||||
void command(uint8_t cmd, boolean isWrite=
|
||||
false); //!< Send a command to the flash chip, pass TRUE for isWrite when its a write command
|
||||
uint8_t readStatus(); //!< return the STATUS register
|
||||
uint8_t readByte(uint32_t addr); //!< read 1 byte from flash memory
|
||||
void readBytes(uint32_t addr, void* buf, uint16_t len); //!< read unlimited # of bytes
|
||||
void writeByte(uint32_t addr, uint8_t byt); //!< Write 1 byte to flash memory
|
||||
void writeBytes(uint32_t addr, const void* buf, uint16_t len); //!< write multiple bytes to flash memory (up to 64K), if define SPIFLASH_SST25TYPE is set AAI Word Programming will be used
|
||||
void writeBytes(uint32_t addr, const void* buf,
|
||||
uint16_t len); //!< write multiple bytes to flash memory (up to 64K), if define SPIFLASH_SST25TYPE is set AAI Word Programming will be used
|
||||
boolean busy(); //!< check if the chip is busy erasing/writing
|
||||
void chipErase(); //!< erase entire flash memory array
|
||||
void blockErase4K(uint32_t address); //!< erase a 4Kbyte block
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user