Restructure HAL files (arch) (#820)

This commit is contained in:
Olivier
2017-04-17 20:33:08 +02:00
committed by Henrik Ekblad
parent b4b5eb52e8
commit 26c237adad
16 changed files with 26 additions and 28 deletions
+143
View File
@@ -0,0 +1,143 @@
/*
* The MySensors Arduino library handles the wireless radio link and protocol
* between your home built sensors/actuators and HA controller of choice.
* The sensors forms a self healing radio network with optional repeaters. Each
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
* network topology allowing messages to be routed to nodes.
*
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
* Copyright (C) 2013-2017 Sensnology AB
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
*
* Documentation: http://www.mysensors.org
* Support Forum: http://forum.mysensors.org
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*/
/**
* @file MyHw.h
*
* MySensors hardware abstraction layer
*/
#ifndef MyHw_h
#define MyHw_h
// Implement these as functions or macros
/*
#define hwInit() MY_SERIALDEVICE.begin(BAUD_RATE)
#define hwWatchdogReset() wdt_reset()
#define hwReboot() wdt_enable(WDTO_15MS); while (1)
#define hwMillis() millis()
#define hwDigitalWrite(__pin, __value)
#define hwDigitalRead(__pin)
#define hwPinMode(__pin, __value)
void hwReadConfigBlock(void* buf, void* adr, size_t length);
void hwWriteConfigBlock(void* buf, void* adr, size_t length);
void hwWriteConfig(int adr, uint8_t value);
uint8_t hwReadConfig(int adr);
*/
/**
* Sleep for a defined time, using minimum power.
* @param ms Time to sleep, in [ms].
* @return Nonsense, please ignore.
*/
typedef uint8_t unique_id_t[16];
/**
* Sleep for a defined time, using minimum power.
* @param ms Time to sleep, in [ms].
* @return -1.
*/
int8_t hwSleep(unsigned long ms);
/**
* Sleep for a defined time, using minimum power, or until woken by interrupt.
* @param interrupt Interrupt number, which can wake the mcu from sleep.
* @param mode Interrupt mode, as passed to attachInterrupt.
* @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 interrupt, uint8_t mode, unsigned long ms);
/**
* Sleep for a defined time, using minimum power, or until woken by one of the interrupts.
* @param interrupt1 Interrupt1 number, which can wake the mcu from sleep.
* @param mode1 Interrupt1 mode, as passed to attachInterrupt.
* @param interrupt2 Interrupt2 number, which can wake the mcu from sleep.
* @param mode2 Interrupt2 mode, as passed to attachInterrupt.
* @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);
/**
* Retrieve unique ID
* @param uniqueID uniqueID
* @return True if unique ID successfully retrieved
*/
bool hwUniqueID(unique_id_t* uniqueID);
/**
* CPU voltage
* @return CPU voltage in mV
*/
uint16_t hwCPUVoltage();
/**
* CPU frequency
* @return CPU frequency in 1/10Mhz
*/
uint16_t hwCPUFrequency();
/**
* Free memory
* @return free memory in bytes
*/
uint16_t hwFreeMem();
#if defined(DEBUG_OUTPUT_ENABLED)
void hwDebugPrint(const char *fmt, ... );
#endif
/**
* @def MY_CRITICAL_SECTION
* @brief Creates a block of code that is guaranteed to be executed atomically.
* Upon entering the block all interrupts are disabled, and re-enabled upon
* exiting the block from any exit path.
* A typical example that requires atomic access is a 16 (or more) bit variable
* that is shared between the main execution path and an ISR, on an 8-bit
* platform (e.g AVR):
* @code
* volatile uint16_t val = 0;
*
* void interrupHandler()
* {
* val = ~val;
* }
*
* void loop()
* {
* uint16_t copy_val;
* MY_CRITICAL_SECTION
* {
* copy_val = val;
* }
* }
* @endcode
* All code within the MY_CRITICAL_SECTION block will be protected from being
* interrupted during execution.
*/
#ifdef DOXYGEN
#define MY_CRITICAL_SECTION
#endif /* DOXYGEN */
#endif // #ifdef MyHw_h
+295
View File
@@ -0,0 +1,295 @@
/**
* The MySensors Arduino library handles the wireless radio link and protocol
* between your home built sensors/actuators and HA controller of choice.
* The sensors forms a self healing radio network with optional repeaters. Each
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
* network topology allowing messages to be routed to nodes.
*
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
* Copyright (C) 2013-2017 Sensnology AB
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
*
* Documentation: http://www.mysensors.org
* Support Forum: http://forum.mysensors.org
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*/
#include "MyHwAVR.h"
bool hwInit(void)
{
#if !defined(MY_DISABLED_SERIAL)
MY_SERIALDEVICE.begin(MY_BAUD_RATE);
#endif
return true;
}
#define WDTO_SLEEP_FOREVER (0xFFu)
#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.
void wakeUp1()
{
// Disable sleep. When an interrupt occurs after attachInterrupt,
// but before sleeping the CPU would not wake up.
// Ref: http://playground.arduino.cc/Learning/ArduinoSleepCode
sleep_disable();
detachInterrupt(_wakeUp1Interrupt);
// First interrupt occurred will be reported only
if (INVALID_INTERRUPT_NUM == _wokeUpByInterrupt) {
_wokeUpByInterrupt = _wakeUp1Interrupt;
}
}
void wakeUp2()
{
sleep_disable();
detachInterrupt(_wakeUp2Interrupt);
// First interrupt occurred will be reported only
if (INVALID_INTERRUPT_NUM == _wokeUpByInterrupt) {
_wokeUpByInterrupt = _wakeUp2Interrupt;
}
}
inline bool interruptWakeUp()
{
return _wokeUpByInterrupt != INVALID_INTERRUPT_NUM;
}
void clearPendingInterrupt(const uint8_t interrupt)
{
EIFR = _BV(interrupt);
}
// Watchdog Timer interrupt service routine. This routine is required
// to allow automatic WDIF and WDIE bit clearance in hardware.
ISR (WDT_vect)
{
}
void hwPowerDown(const uint8_t wdto)
{
// Let serial prints finish (debug, log etc)
#ifndef MY_DISABLED_SERIAL
MY_SERIALDEVICE.flush();
#endif
// disable ADC for power saving
ADCSRA &= ~(1 << ADEN);
// save WDT settings
uint8_t WDTsave = WDTCSR;
if (wdto != WDTO_SLEEP_FOREVER) {
wdt_enable(wdto);
// enable WDT interrupt before system reset
WDTCSR |= (1 << WDCE) | (1 << WDIE);
} else {
// if sleeping forever, disable WDT
wdt_disable();
}
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
cli();
sleep_enable();
#if defined __AVR_ATmega328P__
sleep_bod_disable();
#endif
// Enable interrupts & sleep until WDT or ext. interrupt
sei();
// Directly sleep CPU, to prevent race conditions!
// Ref: chapter 7.7 of ATMega328P datasheet
sleep_cpu();
sleep_disable();
// restore previous WDT settings
cli();
wdt_reset();
// enable WDT changes
WDTCSR |= (1 << WDCE) | (1 << WDE);
// restore saved WDT settings
WDTCSR = WDTsave;
sei();
// enable ADC
ADCSRA |= (1 << ADEN);
}
void hwInternalSleep(unsigned long ms)
{
// Sleeping with watchdog only supports multiples of 16ms.
// Round up to next multiple of 16ms, to assure we sleep at least the
// requested amount of time. Sleep of 0ms will not sleep at all!
ms += 15u;
while (!interruptWakeUp() && ms >= 16) {
for (uint8_t period = 9u; ; --period) {
const uint16_t comparatorMS = 1 << (period + 4);
if ( ms >= comparatorMS) {
hwPowerDown(period); // 8192ms => 9, 16ms => 0
ms -= comparatorMS;
break;
}
}
}
}
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)
{
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)
{
// ATMega328P supports following modes to wake from sleep: LOW, CHANGE, RISING, FALLING
// Datasheet states only LOW can be used with INT0/1 to wake from sleep, which is incorrect.
// Ref: http://gammon.com.au/interrupts
// 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();
// attach interrupts
_wakeUp1Interrupt = interrupt1;
_wakeUp2Interrupt = interrupt2;
// Attach external interrupt handlers, and clear any pending interrupt flag
// to prevent waking immediately again.
// Ref: https://forum.arduino.cc/index.php?topic=59217.0
if (interrupt1 != INVALID_INTERRUPT_NUM) {
clearPendingInterrupt(interrupt1);
attachInterrupt(interrupt1, wakeUp1, mode1);
}
if (interrupt2 != INVALID_INTERRUPT_NUM) {
clearPendingInterrupt(interrupt2);
attachInterrupt(interrupt2, wakeUp2, mode2);
}
if (ms > 0u) {
// sleep for defined time
hwInternalSleep(ms);
} else {
// sleep until ext interrupt triggered
hwPowerDown(WDTO_SLEEP_FOREVER);
}
// Assure any interrupts attached, will get detached when they did not occur.
if (interrupt1 != INVALID_INTERRUPT_NUM) {
detachInterrupt(interrupt1);
}
if (interrupt2 != INVALID_INTERRUPT_NUM) {
detachInterrupt(interrupt2);
}
// Return what woke the mcu.
// Default: no interrupt triggered, timer wake up
int8_t ret = MY_WAKE_UP_BY_TIMER;
if (interruptWakeUp()) {
ret = static_cast<int8_t>(_wokeUpByInterrupt);
}
// Clear woke-up-by-interrupt flag, so next sleeps won't return immediately.
_wokeUpByInterrupt = INVALID_INTERRUPT_NUM;
return ret;
}
bool hwUniqueID(unique_id_t* uniqueID)
{
// not implemented yet
(void)uniqueID;
return false;
}
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));
#elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
ADMUX = (_BV(MUX5) | _BV(MUX0));
#elif defined (__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
ADMUX = (_BV(MUX3) | _BV(MUX2));
#else
ADMUX = (_BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1));
#endif
// Vref settle
delay(70);
// Do conversion
ADCSRA |= _BV(ADSC);
while (bit_is_set(ADCSRA,ADSC)) {};
// return Vcc in mV
return (1125300UL) / ADC;
}
uint16_t hwCPUFrequency()
{
cli();
// setup timer1
TIFR1 = 0xFF;
TCNT1 = 0;
TCCR1A = 0;
TCCR1C = 0;
// save WDT settings
uint8_t WDTsave = WDTCSR;
wdt_enable(WDTO_500MS);
// enable WDT interrupt mode => first timeout WDIF, 2nd timeout reset
WDTCSR |= (1 << WDIE);
wdt_reset();
// start timer1 with 1024 prescaling
TCCR1B = _BV(CS12) | _BV(CS10);
// wait until wdt interrupt
while (bit_is_clear(WDTCSR,WDIF)) {};
// stop timer
TCCR1B = 0;
// restore WDT settings
wdt_reset();
WDTCSR |= (1 << WDCE) | (1 << WDE);
WDTCSR = WDTsave;
sei();
// return frequency in 1/10MHz (accuracy +- 10%)
return TCNT1 * 2048UL / 100000UL;
}
uint16_t hwFreeMem()
{
extern int __heap_start, *__brkval;
int v;
return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
}
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)
snprintf_P(fmtBuffer, sizeof(fmtBuffer), PSTR("0;255;%d;0;%d;%lu "),
C_INTERNAL, I_LOG_MESSAGE, hwMillis());
MY_SERIALDEVICE.print(fmtBuffer);
#else
// prepend timestamp
MY_SERIALDEVICE.print(hwMillis());
MY_SERIALDEVICE.print(F(" "));
#endif
va_list args;
va_start (args, fmt );
#ifdef MY_GATEWAY_FEATURE
// Truncate message if this is gateway node
vsnprintf_P(fmtBuffer, sizeof(fmtBuffer), fmt, args);
fmtBuffer[sizeof(fmtBuffer) - 2] = '\n';
fmtBuffer[sizeof(fmtBuffer) - 1] = '\0';
#else
vsnprintf_P(fmtBuffer, sizeof(fmtBuffer), fmt, args);
#endif
va_end (args);
MY_SERIALDEVICE.print(fmtBuffer);
MY_SERIALDEVICE.flush();
}
+63
View File
@@ -0,0 +1,63 @@
/*
* The MySensors Arduino library handles the wireless radio link and protocol
* between your home built sensors/actuators and HA controller of choice.
* The sensors forms a self healing radio network with optional repeaters. Each
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
* network topology allowing messages to be routed to nodes.
*
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
* Copyright (C) 2013-2017 Sensnology AB
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
*
* Documentation: http://www.mysensors.org
* Support Forum: http://forum.mysensors.org
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*/
#ifndef MyHwAVR_h
#define MyHwAVR_h
#include "MyHw.h"
#include <avr/eeprom.h>
#include <avr/pgmspace.h>
#include <avr/sleep.h>
#include <avr/power.h>
#include <avr/interrupt.h>
#include <avr/wdt.h>
#include <util/atomic.h>
#ifdef __cplusplus
#include <Arduino.h>
#endif
#ifndef MY_SERIALDEVICE
#define MY_SERIALDEVICE Serial
#endif
// Define these as macros to save valuable space
#define hwDigitalWrite(__pin, __value) digitalWriteFast(__pin, __value)
#define hwDigitalRead(__pin) digitalReadFast(__pin)
#define hwPinMode(__pin, __value) pinModeFast(__pin, __value)
bool hwInit(void);
#define hwWatchdogReset() wdt_reset()
#define hwReboot() wdt_enable(WDTO_15MS); while (1)
#define hwMillis() millis()
#define hwRandomNumberInit() randomSeed(analogRead(MY_SIGNING_SOFT_RANDOMSEED_PIN))
#define hwReadConfig(__pos) eeprom_read_byte((uint8_t*)(__pos))
#define hwWriteConfig(__pos, __val) eeprom_update_byte((uint8_t*)(__pos), (__val))
#define hwReadConfigBlock(__buf, __pos, __length) eeprom_read_block((void*)(__buf), (void*)(__pos), (__length))
#define hwWriteConfigBlock(__buf, __pos, __length) eeprom_update_block((void*)(__buf), (void*)(__pos), (__length))
void hwInternalSleep(unsigned long ms);
#ifndef DOXYGEN
#define MY_CRITICAL_SECTION ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
#endif /* DOXYGEN */
#endif
+161
View File
@@ -0,0 +1,161 @@
/**
* The MySensors Arduino library handles the wireless radio link and protocol
* between your home built sensors/actuators and HA controller of choice.
* The sensors forms a self healing radio network with optional repeaters. Each
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
* network topology allowing messages to be routed to nodes.
*
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
* Copyright (C) 2013-2017 Sensnology AB
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
*
* Documentation: http://www.mysensors.org
* Support Forum: http://forum.mysensors.org
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*/
#include "MyHwESP8266.h"
#include <EEPROM.h>
bool hwInit(void)
{
#if !defined(MY_DISABLED_SERIAL)
MY_SERIALDEVICE.begin(MY_BAUD_RATE, SERIAL_8N1, MY_ESP8266_SERIAL_MODE, 1);
MY_SERIALDEVICE.setDebugOutput(true);
#endif
EEPROM.begin(EEPROM_size);
return true;
}
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) {
*dst++ = EEPROM.read(pos++);
}
}
void hwWriteConfigBlock(void* buf, void* addr, size_t length)
{
uint8_t* src = static_cast<uint8_t*>(buf);
int pos = reinterpret_cast<int>(addr);
while (length-- > 0) {
EEPROM.write(pos++, *src++);
}
// see implementation, commit only executed if diff
EEPROM.commit();
}
uint8_t hwReadConfig(const int addr)
{
uint8_t value;
hwReadConfigBlock(&value, reinterpret_cast<void*>(addr), 1);
return value;
}
void hwWriteConfig(const int addr, uint8_t value)
{
hwWriteConfigBlock(&value, reinterpret_cast<void*>(addr), 1);
}
bool hwUniqueID(unique_id_t *uniqueID)
{
// padding
memset((uint8_t*)uniqueID, 0x0A, sizeof(unique_id_t));
uint32_t val = ESP.getChipId();
(void)memcpy((uint8_t*)uniqueID, &val, 4);
val = ESP.getFlashChipId();
(void)memcpy((uint8_t*)uniqueID + 4, &val, 4);
return true;
}
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)
{
// TODO: Not supported!
(void)interrupt;
(void)mode;
(void)ms;
return MY_SLEEP_NOT_POSSIBLE;
}
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;
(void)interrupt2;
(void)mode2;
(void)ms;
return MY_SLEEP_NOT_POSSIBLE;
}
#if defined(MY_SPECIAL_DEBUG)
// settings for getVcc()
ADC_MODE(ADC_VCC);
#else
// [default] settings for analogRead(A0)
ADC_MODE(ADC_TOUT);
#endif
uint16_t hwCPUVoltage()
{
#if defined(MY_SPECIAL_DEBUG)
// in mV, requires ADC_VCC set
return ESP.getVcc();
#else
// not possible
return FUNCTION_NOT_SUPPORTED;
#endif
}
uint16_t hwCPUFrequency()
{
// in 1/10Mhz
return ESP.getCpuFreqMHz()*10;
}
uint16_t hwFreeMem()
{
return ESP.getFreeHeap();
}
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)
snprintf_P(fmtBuffer, sizeof(fmtBuffer), PSTR("0;255;%d;0;%d;%lu "), C_INTERNAL, I_LOG_MESSAGE,
hwMillis());
MY_SERIALDEVICE.print(fmtBuffer);
#else
// prepend timestamp
MY_SERIALDEVICE.print(hwMillis());
MY_SERIALDEVICE.print(" ");
#endif
va_list args;
va_start (args, fmt );
#ifdef MY_GATEWAY_FEATURE
// Truncate message if this is gateway node
vsnprintf_P(fmtBuffer, sizeof(fmtBuffer), fmt, args);
fmtBuffer[sizeof(fmtBuffer) - 2] = '\n';
fmtBuffer[sizeof(fmtBuffer) - 1] = '\0';
#else
vsnprintf_P(fmtBuffer, sizeof(fmtBuffer), fmt, args);
#endif
va_end (args);
MY_SERIALDEVICE.print(fmtBuffer);
MY_SERIALDEVICE.flush();
}
+65
View File
@@ -0,0 +1,65 @@
/*
* The MySensors Arduino library handles the wireless radio link and protocol
* between your home built sensors/actuators and HA controller of choice.
* The sensors forms a self healing radio network with optional repeaters. Each
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
* network topology allowing messages to be routed to nodes.
*
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
* Copyright (C) 2013-2017 Sensnology AB
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
*
* Documentation: http://www.mysensors.org
* Support Forum: http://forum.mysensors.org
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*/
#ifndef MyHwESP8266_h
#define MyHwESP8266_h
#include "MyHw.h"
#ifdef __cplusplus
#include <Arduino.h>
#endif
#ifndef MY_SERIALDEVICE
#define MY_SERIALDEVICE Serial
#endif
#define min(a,b) ((a)<(b)?(a):(b))
#define max(a,b) ((a)>(b)?(a):(b))
#define EEPROM_size (1024)
// Define these as macros to save valuable space
#define hwDigitalWrite(__pin, __value) digitalWrite(__pin, __value)
#define hwDigitalRead(__pin) digitalRead(__pin)
#define hwPinMode(__pin, __value) pinMode(__pin, __value)
#define hwWatchdogReset() wdt_reset()
#define hwReboot() ESP.restart()
#define hwMillis() millis()
#define hwRandomNumberInit() randomSeed(RANDOM_REG32)
bool hwInit(void);
void hwReadConfigBlock(void* buf, void* adr, size_t length);
void hwWriteConfigBlock(void* buf, void* adr, size_t length);
void hwWriteConfig(const int addr, uint8_t value);
uint8_t hwReadConfig(const int addr);
/**
* Restore interrupt state.
* Helper function for MY_CRITICAL_SECTION.
*/
static __inline__ void __psRestore(const uint32_t *__s)
{
xt_wsr_ps( *__s );
}
#ifndef DOXYGEN
#define MY_CRITICAL_SECTION for ( uint32_t __psSaved __attribute__((__cleanup__(__psRestore))) = xt_rsil(15), __ToDo = 1; __ToDo ; __ToDo = 0 )
#endif /* DOXYGEN */
#endif // #ifdef ARDUINO_ARCH_ESP8266
+150
View File
@@ -0,0 +1,150 @@
/**
* The MySensors Arduino library handles the wireless radio link and protocol
* between your home built sensors/actuators and HA controller of choice.
* The sensors forms a self healing radio network with optional repeaters. Each
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
* network topology allowing messages to be routed to nodes.
*
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
* Copyright (C) 2013-2017 Sensnology AB
* Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors
*
* Documentation: http://www.mysensors.org
* Support Forum: http://forum.mysensors.org
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*/
#include "MyHwLinuxGeneric.h"
#include <stdarg.h>
#include <time.h>
#include "SoftEeprom.h"
#include "log.h"
static SoftEeprom eeprom = SoftEeprom(MY_LINUX_CONFIG_FILE, 1024); // ATMega328 has 1024 bytes
bool hwInit(void)
{
MY_SERIALDEVICE.begin(MY_BAUD_RATE);
#ifdef MY_GATEWAY_SERIAL
#ifdef MY_LINUX_SERIAL_GROUPNAME
if (!MY_SERIALDEVICE.setGroupPerm(MY_LINUX_SERIAL_GROUPNAME)) {
logError("Unable to change permission for serial port device.\n");
exit(1);
}
#endif
#endif
return true;
}
void hwReadConfigBlock(void* buf, void* addr, size_t length)
{
eeprom.readBlock(buf, addr, length);
}
void hwWriteConfigBlock(void* buf, void* addr, size_t length)
{
eeprom.writeBlock(buf, addr, length);
}
uint8_t hwReadConfig(int addr)
{
return eeprom.readByte(addr);
}
void hwWriteConfig(int addr, uint8_t value)
{
eeprom.writeByte(addr, value);
}
void hwRandomNumberInit()
{
randomSeed(time(NULL));
}
unsigned long hwMillis()
{
return millis();
}
bool hwUniqueID(unique_id_t *uniqueID)
{
// not implemented yet
(void)uniqueID;
return false;
}
// Not supported!
int8_t hwSleep(unsigned long ms)
{
(void)ms;
return MY_SLEEP_NOT_POSSIBLE;
}
// Not supported!
int8_t hwSleep(uint8_t interrupt, uint8_t mode, unsigned long ms)
{
(void)interrupt;
(void)mode;
(void)ms;
return MY_SLEEP_NOT_POSSIBLE;
}
// Not supported!
int8_t hwSleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2,
unsigned long ms)
{
(void)interrupt1;
(void)mode1;
(void)interrupt2;
(void)mode2;
(void)ms;
return MY_SLEEP_NOT_POSSIBLE;
}
uint16_t hwCPUVoltage()
{
// TODO: Not supported!
return FUNCTION_NOT_SUPPORTED;
}
uint16_t hwCPUFrequency()
{
// TODO: Not supported!
return FUNCTION_NOT_SUPPORTED;
}
uint16_t hwFreeMem()
{
// TODO: Not supported!
return FUNCTION_NOT_SUPPORTED;
}
void hwDigitalWrite(uint8_t pin, uint8_t value)
{
digitalWrite(pin, value);
}
int hwDigitalRead(uint8_t pin)
{
return digitalRead(pin);
}
void hwPinMode(uint8_t pin, uint8_t mode)
{
pinMode(pin, mode);
}
void hwDebugPrint(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
vlogDebug(fmt, args);
va_end(args);
}
+96
View File
@@ -0,0 +1,96 @@
/*
* The MySensors Arduino library handles the wireless radio link and protocol
* between your home built sensors/actuators and HA controller of choice.
* The sensors forms a self healing radio network with optional repeaters. Each
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
* network topology allowing messages to be routed to nodes.
*
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
* Copyright (C) 2013-2017 Sensnology AB
* Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors
*
* Documentation: http://www.mysensors.org
* Support Forum: http://forum.mysensors.org
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*/
#ifndef MyHwLinuxGeneric_h
#define MyHwLinuxGeneric_h
#include <cstdlib>
#include <pthread.h>
#include "MyHw.h"
#include "SerialPort.h"
#include "SerialSimulator.h"
#ifdef MY_GATEWAY_SERIAL
#ifdef MY_LINUX_IS_SERIAL_PTY
SerialPort Serial = SerialPort(MY_LINUX_SERIAL_PTY, true);
#else
SerialPort Serial = SerialPort(MY_LINUX_SERIAL_PORT);
#endif
#else
SerialSimulator Serial = SerialSimulator();
#endif
#ifndef MY_SERIALDEVICE
#define MY_SERIALDEVICE Serial
#endif
// Define these as macros (do nothing)
#define hwWatchdogReset()
#define hwReboot()
inline void hwDigitalWrite(uint8_t, uint8_t);
inline int hwDigitalRead(uint8_t);
inline void hwPinMode(uint8_t, uint8_t);
bool hwInit(void);
inline void hwReadConfigBlock(void* buf, void* addr, size_t length);
inline void hwWriteConfigBlock(void* buf, void* addr, size_t length);
inline uint8_t hwReadConfig(int addr);
inline void hwWriteConfig(int addr, uint8_t value);
inline void hwRandomNumberInit();
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)
{
pthread_mutex_unlock(&hw_mutex);
(void)__s;
}
static __inline__ void __hwLock()
{
pthread_mutex_lock(&hw_mutex);
}
#endif
#if defined(DOXYGEN)
#define ATOMIC_BLOCK_CLEANUP
#elif defined(MY_RF24_IRQ_PIN)
#define ATOMIC_BLOCK_CLEANUP uint8_t __atomic_loop \
__attribute__((__cleanup__( __hwUnlock ))) = 1
#else
#define ATOMIC_BLOCK_CLEANUP
#endif /* DOXYGEN */
#if defined(DOXYGEN)
#define ATOMIC_BLOCK
#elif defined(MY_RF24_IRQ_PIN)
#define ATOMIC_BLOCK for ( ATOMIC_BLOCK_CLEANUP, __hwLock(); \
__atomic_loop ; __atomic_loop = 0 )
#else
#define ATOMIC_BLOCK
#endif /* DOXYGEN */
#ifndef DOXYGEN
#define MY_CRITICAL_SECTION ATOMIC_BLOCK
#endif /* DOXYGEN */
#endif
+210
View File
@@ -0,0 +1,210 @@
/**
* The MySensors Arduino library handles the wireless radio link and protocol
* between your home built sensors/actuators and HA controller of choice.
* The sensors forms a self healing radio network with optional repeaters. Each
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
* network topology allowing messages to be routed to nodes.
*
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
* Copyright (C) 2013-2017 Sensnology AB
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
*
* Documentation: http://www.mysensors.org
* Support Forum: http://forum.mysensors.org
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*/
#include "MyHwSAMD.h"
/*
int8_t pinIntTrigger = 0;
void wakeUp() //place to send the interrupts
{
pinIntTrigger = 1;
}
void wakeUp2() //place to send the second interrupts
{
pinIntTrigger = 2;
}
// Watchdog Timer interrupt service routine. This routine is required
// to allow automatic WDIF and WDIE bit clearance in hardware.
ISR (WDT_vect)
{
// WDIE & WDIF is cleared in hardware upon entering this ISR
wdt_disable();
}
*/
void hwReadConfigBlock(void* buf, void* adr, size_t length)
{
uint8_t* dst = static_cast<uint8_t*>(buf);
const int offs = reinterpret_cast<int>(adr);
(void)eep.read(offs, dst, length);
}
void hwWriteConfigBlock(void* buf, void* adr, size_t length)
{
uint8_t* src = static_cast<uint8_t*>(buf);
const int offs = reinterpret_cast<int>(adr);
// use update() instead of write() to reduce e2p wear off
(void)eep.update(offs, src, length);
}
uint8_t hwReadConfig(int adr)
{
return eep.read(adr);
}
void hwWriteConfig(int adr, uint8_t value)
{
(void)eep.update(adr, value);
}
bool hwInit(void)
{
MY_SERIALDEVICE.begin(MY_BAUD_RATE);
#if defined(MY_GATEWAY_SERIAL)
while (!MY_SERIALDEVICE) {}
#endif
const uint8_t eepInit = eep.begin(MY_EXT_EEPROM_TWI_CLOCK);
#if defined(SENSEBENDER_GW_SAMD_V1)
// check connection to external EEPROM - only sensebender GW
return eepInit==0;
#else
(void)eepInit;
return true;
#endif
}
void hwWatchdogReset(void)
{
// TODO: Not supported!
}
void hwReboot(void)
{
NVIC_SystemReset();
while (true);
}
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)
{
// TODO: Not supported!
(void)interrupt;
(void)mode;
(void)ms;
return MY_SLEEP_NOT_POSSIBLE;
}
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;
(void)interrupt2;
(void)mode2;
(void)ms;
return MY_SLEEP_NOT_POSSIBLE;
}
bool hwUniqueID(unique_id_t *uniqueID)
{
(void)memcpy((uint8_t*)uniqueID, (uint32_t *)0x0080A00C, 4);
(void)memcpy((uint8_t*)uniqueID + 4, (uint32_t *)0x0080A040, 12);
return true;
}
uint16_t hwCPUVoltage()
{
// disable ADC
while (ADC->STATUS.bit.SYNCBUSY);
ADC->CTRLA.bit.ENABLE = 0x00;
// internal 1V reference (default)
analogReference(AR_INTERNAL1V0);
// 12 bit resolution (default)
analogWriteResolution(12);
// MUXp 0x1B = SCALEDIOVCC/4 => connected to Vcc
ADC->INPUTCTRL.bit.MUXPOS = 0x1B ;
// enable ADC
while (ADC->STATUS.bit.SYNCBUSY);
ADC->CTRLA.bit.ENABLE = 0x01;
// start conversion
while (ADC->STATUS.bit.SYNCBUSY);
ADC->SWTRIG.bit.START = 1;
// clear the Data Ready flag
ADC->INTFLAG.bit.RESRDY = 1;
// start conversion again, since The first conversion after the reference is changed must not be used.
while (ADC->STATUS.bit.SYNCBUSY);
ADC->SWTRIG.bit.START = 1;
// waiting for conversion to complete
while (!ADC->INTFLAG.bit.RESRDY);
const uint32_t valueRead = ADC->RESULT.reg;
// disable ADC
while (ADC->STATUS.bit.SYNCBUSY);
ADC->CTRLA.bit.ENABLE = 0x00;
return valueRead * 4;
}
uint16_t hwCPUFrequency()
{
// TODO: currently reporting compile time frequency (in 1/10MHz)
return F_CPU / 100000UL;
}
uint16_t hwFreeMem()
{
// TODO: Not supported!
return FUNCTION_NOT_SUPPORTED;
}
void hwDebugPrint(const char *fmt, ... )
{
if (MY_SERIALDEVICE) {
char fmtBuffer[MY_SERIAL_OUTPUT_SIZE];
#ifdef MY_GATEWAY_FEATURE
// prepend debug message to be handled correctly by controller (C_INTERNAL, I_LOG_MESSAGE)
snprintf(fmtBuffer, sizeof(fmtBuffer), PSTR("0;255;%d;0;%d;%lu "), C_INTERNAL, I_LOG_MESSAGE,
hwMillis());
MY_SERIALDEVICE.print(fmtBuffer);
#else
// prepend timestamp
MY_SERIALDEVICE.print(hwMillis());
MY_SERIALDEVICE.print(" ");
#endif
va_list args;
va_start (args, fmt );
#ifdef MY_GATEWAY_FEATURE
// Truncate message if this is gateway node
vsnprintf(fmtBuffer, sizeof(fmtBuffer), fmt, args);
fmtBuffer[sizeof(fmtBuffer) - 2] = '\n';
fmtBuffer[sizeof(fmtBuffer) - 1] = '\0';
#else
vsnprintf(fmtBuffer, sizeof(fmtBuffer), fmt, args);
#endif
va_end (args);
MY_SERIALDEVICE.print(fmtBuffer);
// MY_SERIALDEVICE.flush();
}
}
+86
View File
@@ -0,0 +1,86 @@
/*
* The MySensors Arduino library handles the wireless radio link and protocol
* between your home built sensors/actuators and HA controller of choice.
* The sensors forms a self healing radio network with optional repeaters. Each
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
* network topology allowing messages to be routed to nodes.
*
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
* Copyright (C) 2013-2017 Sensnology AB
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
*
* Documentation: http://www.mysensors.org
* Support Forum: http://forum.mysensors.org
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*/
#ifndef MyHwSAMD_h
#define MyHwSAMD_h
#include "MyHw.h"
#ifdef __cplusplus
#include <Arduino.h>
#endif
#include <avr/dtostrf.h>
// defines for sensebender gw variant.h
#define MY_EXT_EEPROM_I2C_ADDRESS (0x50u)
#define MY_EXT_EEPROM_SIZE (kbits_512)
#define MY_EXT_EEPROM_PAGE_SIZE (32u)
#define MY_EXT_EEPROM_TWI_CLOCK (twiClock100kHz) // can be set to 400kHz with precaution if other i2c devices on bus
extEEPROM eep(MY_EXT_EEPROM_SIZE, 1, MY_EXT_EEPROM_PAGE_SIZE,
MY_EXT_EEPROM_I2C_ADDRESS); //device size, number of devices, page size
#define min(a,b) ((a)<(b)?(a):(b))
#define max(a,b) ((a)>(b)?(a):(b))
#define snprintf_P(s, f, ...) snprintf((s), (f), __VA_ARGS__)
// Define these as macros to save valuable space
#define hwDigitalWrite(__pin, __value) digitalWrite(__pin, __value)
#define hwDigitalRead(__pin) digitalRead(__pin)
#define hwPinMode(__pin, __value) pinMode(__pin, __value)
#define hwMillis() millis()
#define hwRandomNumberInit() randomSeed(analogRead(MY_SIGNING_SOFT_RANDOMSEED_PIN))
bool hwInit(void);
void hwWatchdogReset(void);
void hwReboot(void);
void hwReadConfigBlock(void* buf, void* adr, size_t length);
void hwWriteConfigBlock(void* buf, void* adr, size_t length);
void hwWriteConfig(int adr, uint8_t value);
uint8_t hwReadConfig(int adr);
#ifndef MY_SERIALDEVICE
#define MY_SERIALDEVICE SerialUSB
#endif
/**
* Disable all interrupts.
* Helper function for MY_CRITICAL_SECTION.
*/
static __inline__ uint8_t __disableIntsRetVal(void)
{
__disable_irq();
return 1;
}
/**
* Restore priority mask register.
* Helper function for MY_CRITICAL_SECTION.
*/
static __inline__ void __priMaskRestore(const uint32_t *priMask)
{
__set_PRIMASK(*priMask);
}
#ifndef DOXYGEN
#define MY_CRITICAL_SECTION for ( uint32_t __savePriMask __attribute__((__cleanup__(__priMaskRestore))) = __get_PRIMASK(), __ToDo = __disableIntsRetVal(); __ToDo ; __ToDo = 0 )
#endif /* DOXYGEN */
#endif // #ifdef ARDUINO_ARCH_SAMD
+176
View File
@@ -0,0 +1,176 @@
/**
* The MySensors Arduino library handles the wireless radio link and protocol
* between your home built sensors/actuators and HA controller of choice.
* The sensors forms a self healing radio network with optional repeaters. Each
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
* network topology allowing messages to be routed to nodes.
*
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
* Copyright (C) 2013-2017 Sensnology AB
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
*
* Documentation: http://www.mysensors.org
* Support Forum: http://forum.mysensors.org
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*/
#include "MyHwSTM32F1.h"
#include <EEPROM.h>
/*
* Pinout STM32F103C8 dev board:
* http://wiki.stm32duino.com/images/a/ae/Bluepillpinout.gif
*
* Wiring RFM69 radio / SPI1
* --------------------------------------------------
* CLK PA5
* MISO PA6
* MOSI PA7
* CSN PA4
* CE NA
* IRQ PA3 (default)
*
* Wiring RF24 radio / SPI1
* --------------------------------------------------
* CLK PA5
* MISO PA6
* MOSI PA7
* CSN PA4
* CE PB0 (default)
* IRQ NA
*
*/
bool hwInit(void)
{
#if !defined(MY_DISABLED_SERIAL)
MY_SERIALDEVICE.begin(MY_BAUD_RATE);
#endif
if (EEPROM.init() == EEPROM_OK) {
uint16 cnt;
EEPROM.count(&cnt);
if(cnt>=EEPROM.maxcount()) {
// tmp, WIP: format eeprom if full
EEPROM.format();
}
return true;
}
return false;
}
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) {
*dst++ = EEPROM.read(pos++);
}
}
void hwWriteConfigBlock(void* buf, void* addr, size_t length)
{
uint8_t* src = static_cast<uint8_t*>(buf);
int pos = reinterpret_cast<int>(addr);
while (length-- > 0) {
EEPROM.write(pos++, *src++);
}
}
uint8_t hwReadConfig(const int addr)
{
uint8_t value;
hwReadConfigBlock(&value, reinterpret_cast<void*>(addr), 1);
return value;
}
void hwWriteConfig(const int addr, uint8_t value)
{
hwWriteConfigBlock(&value, reinterpret_cast<void*>(addr), 1);
}
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)
{
// TODO: Not supported!
(void)interrupt;
(void)mode;
(void)ms;
return MY_SLEEP_NOT_POSSIBLE;
}
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;
(void)interrupt2;
(void)mode2;
(void)ms;
return MY_SLEEP_NOT_POSSIBLE;
}
bool hwUniqueID(unique_id_t* uniqueID)
{
(void)memcpy((uint8_t*)uniqueID, (uint32_t*)0x1FFFF7E0, 16);
return true;
}
uint16_t hwCPUVoltage()
{
adc_reg_map *regs = ADC1->regs;
regs->CR2 |= ADC_CR2_TSVREFE; // enable VREFINT and temp sensor
regs->SMPR1 = ADC_SMPR1_SMP17; // sample rate for VREFINT ADC channel
return 1200 * 4096 / adc_read(ADC1, 17);
}
uint16_t hwCPUFrequency()
{
return F_CPU/100000UL;
}
uint16_t hwFreeMem()
{
//Not yet implemented
return 0;
}
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)
snprintf_P(fmtBuffer, sizeof(fmtBuffer), PSTR("0;255;%d;0;%d;%lu "), C_INTERNAL, I_LOG_MESSAGE,
hwMillis());
MY_SERIALDEVICE.print(fmtBuffer);
#else
// prepend timestamp
MY_SERIALDEVICE.print(hwMillis());
MY_SERIALDEVICE.print(" ");
#endif
va_list args;
va_start(args, fmt);
#ifdef MY_GATEWAY_FEATURE
// Truncate message if this is gateway node
vsnprintf_P(fmtBuffer, sizeof(fmtBuffer), fmt, args);
fmtBuffer[sizeof(fmtBuffer) - 2] = '\n';
fmtBuffer[sizeof(fmtBuffer) - 1] = '\0';
#else
vsnprintf_P(fmtBuffer, sizeof(fmtBuffer), fmt, args);
#endif
va_end(args);
MY_SERIALDEVICE.print(fmtBuffer);
// Disable flush since current STM32duino implementation performs a reset
// instead of an actual flush
//MY_SERIALDEVICE.flush();
}
+69
View File
@@ -0,0 +1,69 @@
/*
* The MySensors Arduino library handles the wireless radio link and protocol
* between your home built sensors/actuators and HA controller of choice.
* The sensors forms a self healing radio network with optional repeaters. Each
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
* network topology allowing messages to be routed to nodes.
*
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
* Copyright (C) 2013-2017 Sensnology AB
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
*
* Documentation: http://www.mysensors.org
* Support Forum: http://forum.mysensors.org
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*/
#ifndef MyHwSTM32F1_h
#define MyHwSTM32F1_h
#include "MyHw.h"
#include <libmaple/iwdg.h>
#include <itoa.h>
#ifdef __cplusplus
#include <Arduino.h>
#endif
// mapping
#define snprintf_P snprintf
#define vsnprintf_P vsnprintf
// emulated EEPROM (experimental)
#define EEPROM_PAGE_SIZE (uint16_t)1024
#define EEPROM_SIZE (uint16_t)2048
#define EEPROM_START_ADDRESS ((uint32_t)(0x8000000 + 128 * EEPROM_PAGE_SIZE - 2 * EEPROM_PAGE_SIZE))
#ifndef MY_SERIALDEVICE
#define MY_SERIALDEVICE Serial
#endif
// Define these as macros to save valuable space
#define hwDigitalWrite(__pin, __value) digitalWrite(__pin, __value)
#define hwDigitalRead(__pin) digitalRead(__pin)
#define hwPinMode(__pin, __value) pinMode(__pin, __value)
#define hwWatchdogReset() iwdg_feed()
#define hwReboot() nvic_sys_reset()
#define hwMillis() millis()
void (*serialEventRun)() = NULL;
bool hwInit(void);
void hwReadConfigBlock(void* buf, void* adr, size_t length);
void hwWriteConfigBlock(void* buf, void* adr, size_t length);
void hwWriteConfig(const int addr, uint8_t value);
uint8_t hwReadConfig(const int addr);
#define hwRandomNumberInit() randomSeed(analogRead(MY_SIGNING_SOFT_RANDOMSEED_PIN))
#ifndef DOXYGEN
#define MY_CRITICAL_SECTION
#endif /* DOXYGEN */
#endif
+46
View File
@@ -0,0 +1,46 @@
/*
* The MySensors Arduino library handles the wireless radio link and protocol
* between your home built sensors/actuators and HA controller of choice.
* The sensors forms a self healing radio network with optional repeaters. Each
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
* network topology allowing messages to be routed to nodes.
*
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
* Copyright (C) 2013-2017 Sensnology AB
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
*
* Documentation: http://www.mysensors.org
* Support Forum: http://forum.mysensors.org
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*/
// Initialize library and handle sketch functions like we want to
extern "C" void __libc_init_array(void);
int main(void)
{
init();
#if defined(USBCON)
#if defined(ARDUINO_ARCH_SAMD)
__libc_init_array();
USBDevice.init();
#endif
USBDevice.attach();
#endif
_begin(); // Startup MySensors library
for(;;) {
_process(); // Process incoming data
if (loop) {
loop(); // Call sketch loop
}
if (serialEventRun) {
serialEventRun();
}
}
return 0;
}
+177
View File
@@ -0,0 +1,177 @@
/**
* The MySensors Arduino library handles the wireless radio link and protocol
* between your home built sensors/actuators and HA controller of choice.
* The sensors forms a self healing radio network with optional repeaters. Each
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
* network topology allowing messages to be routed to nodes.
*
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
* Copyright (C) 2013-2017 Sensnology AB
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
*
* Documentation: http://www.mysensors.org
* Support Forum: http://forum.mysensors.org
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*/
//This may be used to change user task stack size:
//#define CONT_STACKSIZE 4096
#include "Schedule.h"
extern "C" {
#include "ets_sys.h"
#include "os_type.h"
#include "osapi.h"
#include "mem.h"
#include "user_interface.h"
#include "cont.h"
}
#include <core_version.h>
#define LOOP_TASK_PRIORITY 1
#define LOOP_QUEUE_SIZE 1
#define OPTIMISTIC_YIELD_TIME_US 16000
struct rst_info resetInfo;
extern "C" {
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;
#else
NULL;
#endif
} // extern "C"
int atexit(void(*func)())
{
(void)func;
return 0;
}
extern "C" void ets_update_cpu_frequency(int freqmhz);
void initVariant() __attribute__((weak));
void initVariant()
{
}
void preloop_update_frequency() __attribute__((weak));
void preloop_update_frequency()
{
#if defined(F_CPU) && (F_CPU == 160000000L)
REG_SET_BIT(0x3ff00014, BIT(0));
ets_update_cpu_frequency(160);
#endif
}
extern void(*__init_array_start)(void);
extern void(*__init_array_end)(void);
cont_t g_cont __attribute__((aligned(16)));
static os_event_t g_loop_queue[LOOP_QUEUE_SIZE];
static uint32_t g_micros_at_task_start;
extern "C" void esp_yield()
{
if (cont_can_yield(&g_cont)) {
cont_yield(&g_cont);
}
}
extern "C" void esp_schedule()
{
ets_post(LOOP_TASK_PRIORITY, 0, 0);
}
extern "C" void __yield()
{
if (cont_can_yield(&g_cont)) {
esp_schedule();
esp_yield();
} 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) {
yield();
}
}
static void loop_wrapper()
{
static bool setup_done = false;
preloop_update_frequency();
if (!setup_done) {
_begin(); // Startup MySensors library
setup_done = true;
}
_process(); // Process incoming data
loop();
run_scheduled_functions();
esp_schedule();
}
static void loop_task(os_event_t *events)
{
(void)events;
g_micros_at_task_start = system_get_time();
cont_run(&g_cont, &loop_wrapper);
if (cont_check(&g_cont) != 0) {
panic();
}
}
static void do_global_ctors(void)
{
void(**p)(void) = &__init_array_end;
while (p != &__init_array_start) {
(*--p)();
}
}
extern "C" void __gdb_init() {}
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()
{
system_set_os_print(1);
gdb_init();
do_global_ctors();
esp_schedule();
}
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));
uart_div_modify(0, UART_CLK_FREQ / (115200));
init();
initVariant();
cont_init(&g_cont);
ets_task(loop_task,
LOOP_TASK_PRIORITY, g_loop_queue,
LOOP_QUEUE_SIZE);
system_init_done_cb(&init_done);
}
+450
View File
@@ -0,0 +1,450 @@
/**
* The MySensors Arduino library handles the wireless radio link and protocol
* between your home built sensors/actuators and HA controller of choice.
* The sensors forms a self healing radio network with optional repeaters. Each
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
* network topology allowing messages to be routed to nodes.
*
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
* Copyright (C) 2013-2017 Sensnology AB
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
*
* Documentation: http://www.mysensors.org
* Support Forum: http://forum.mysensors.org
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*/
// Initialize library and handle sketch functions like we want to
#include <stdio.h>
#include <csignal>
#include <cstdlib>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <syslog.h>
#include <errno.h>
#include <getopt.h>
#include "log.h"
#include "MySensorsCore.h"
void handle_sigint(int sig)
{
if (sig == SIGINT) {
logNotice("Received SIGINT\n\n");
} else if (sig == SIGTERM) {
logNotice("Received SIGTERM\n\n");
} else {
return;
}
#ifdef MY_RF24_IRQ_PIN
detachInterrupt(MY_RF24_IRQ_PIN);
#endif
#if defined(MY_GATEWAY_SERIAL)
MY_SERIALDEVICE.end();
#endif
closelog();
exit(EXIT_SUCCESS);
}
static int daemonize(void)
{
pid_t pid, sid;
/* Fork off the parent process */
pid = fork();
if (pid < 0) {
logError("fork: %s\n", strerror(errno));
return -1;
}
/* If we got a good PID, then we can exit the parent process. */
if (pid > 0) {
exit(EXIT_SUCCESS);
}
/* At this point we are executing as the child process */
/* Change the file mode mask */
umask(0);
/* Create a new SID for the child process */
sid = setsid();
if (sid < 0) {
logError("setsid: %s\n", strerror(errno));
return -1;
}
/* Change the current working directory. This prevents the current
directory from being locked; hence not being able to remove it. */
if ((chdir("/")) < 0) {
logError("chdir(\"/\"): %s\n", strerror(errno));
return -1;
}
if (freopen( "/dev/null", "r", stdin) == NULL) {
logError("freopen: %s\n", strerror(errno));
}
if (freopen( "/dev/null", "r", stdout) == NULL) {
logError("freopen: %s\n", strerror(errno));
}
if (freopen( "/dev/null", "r", stderr) == NULL) {
logError("freopen: %s\n", strerror(errno));
}
return 0;
}
void print_usage()
{
printf("Usage: mysgw [options]\n\n" \
"Options:\n" \
" -h, --help Display a short summary of all program options.\n" \
" -d, --debug Enable debug.\n" \
" -b, --background Run as a background process.\n"
" --gen-soft-hmac-key Generate and print a soft hmac key.\n"
" --gen-soft-serial-key Generate and print a soft serial key.\n"
" --gen-aes-key Generate and print an aes encryption key.\n"
" --print-soft-hmac-key Print the soft hmac key from the config file.\n"
" --print-soft-serial-key Print the soft serial key from the config file.\n"
" --print-aes-key Print the aes encryption key from the config file.\n"
" --set-soft-hmac-key Write a soft hmac key to the config file.\n"
" --set-soft-serial-key Write a soft serial key to the config file.\n"
" --set-aes-key Write an aes encryption key to the config file.\n");
}
void print_soft_sign_hmac_key(uint8_t *key_ptr = NULL)
{
uint8_t key[32];
if (key_ptr == NULL) {
hwReadConfigBlock(&key, reinterpret_cast<void*>EEPROM_SIGNING_SOFT_HMAC_KEY_ADDRESS, 32);
key_ptr = key;
}
printf("SOFT_HMAC_KEY | ");
for (int i = 0; i < 32; i++) {
printf("%02X", key_ptr[i]);
}
printf("\n\n");
printf("The next line is intended to be used in SecurityPersonalizer.ino:\n");
printf("#define MY_SOFT_HMAC_KEY ");
for (int i=0; i<32; i++) {
printf("%#02X", key_ptr[i]);
if (i < 31) {
printf(",");
}
}
printf("\n\n");
}
void generate_soft_sign_hmac_key()
{
uint8_t key[32];
for (int i = 0; i < 32; i++) {
key[i] = random(256) ^ micros();
unsigned long enter = hwMillis();
while (hwMillis() - enter < (unsigned long)2);
}
print_soft_sign_hmac_key(key);
printf("To use this key, run mysgw with:\n"
" --set-soft-hmac-key=");
for (int i = 0; i < 32; i++) {
printf("%02X", key[i]);
}
printf("\n");
}
void set_soft_sign_hmac_key(char *key_str)
{
uint8_t key[32];
if (strlen(key_str) != 64) {
printf("invalid key!\n");
} else {
for (int i = 0; i < 64; ++i) {
int n;
char c = key_str[i];
if (c <= '9') {
n = c - '0';
} else if (c >= 'a') {
n = c - 'a' + 10;
} else {
n = c - 'A' + 10;
}
if ((i & 0x1) == 0) {
key[i/2] = n * 16;
} else {
key[i/2] += n;
}
}
hwWriteConfigBlock(&key, reinterpret_cast<void*>EEPROM_SIGNING_SOFT_HMAC_KEY_ADDRESS, 32);
print_soft_sign_hmac_key();
}
}
void print_soft_sign_serial_key(uint8_t *key_ptr = NULL)
{
uint8_t key[9];
if (key_ptr == NULL) {
hwReadConfigBlock(&key, reinterpret_cast<void*>EEPROM_SIGNING_SOFT_SERIAL_ADDRESS, 9);
key_ptr = key;
}
printf("SOFT_SERIAL | ");
for (int i = 0; i < 9; i++) {
printf("%02X", key_ptr[i]);
}
printf("\n\n");
printf("The next line is intended to be used in SecurityPersonalizer.ino:\n");
printf("#define MY_SOFT_SERIAL ");
for (int i=0; i<9; i++) {
printf("%#02X", key_ptr[i]);
if (i < 8) {
printf(",");
}
}
printf("\n\n");
}
void generate_soft_sign_serial_key()
{
uint8_t key[9];
for (int i = 0; i < 9; i++) {
key[i] = random(256) ^ micros();
unsigned long enter = hwMillis();
while (hwMillis() - enter < (unsigned long)2);
}
print_soft_sign_serial_key(key);
printf("To use this key, run mysgw with:\n"
" --set-soft-serial-key=");
for (int i = 0; i < 9; i++) {
printf("%02X", key[i]);
}
printf("\n");
}
void set_soft_sign_serial_key(char *key_str)
{
uint8_t key[9];
if (strlen(key_str) != 18) {
printf("invalid key!\n");
} else {
for (int i = 0; i < 18; ++i) {
int n;
char c = key_str[i];
if (c <= '9') {
n = c - '0';
} else if (c >= 'a') {
n = c - 'a' + 10;
} else {
n = c - 'A' + 10;
}
if ((i & 0x1) == 0) {
key[i/2] = n * 16;
} else {
key[i/2] += n;
}
}
hwWriteConfigBlock(&key, reinterpret_cast<void*>EEPROM_SIGNING_SOFT_SERIAL_ADDRESS, 9);
print_soft_sign_serial_key();
}
}
void print_aes_key(uint8_t *key_ptr = NULL)
{
uint8_t key[16];
if (key_ptr == NULL) {
hwReadConfigBlock(&key, reinterpret_cast<void*>EEPROM_RF_ENCRYPTION_AES_KEY_ADDRESS, 16);
key_ptr = key;
}
printf("AES_KEY | ");
for (int i = 0; i < 16; i++) {
printf("%02X", key_ptr[i]);
}
printf("\n\n");
printf("The next line is intended to be used in SecurityPersonalizer.ino:\n");
printf("#define MY_AES_KEY ");
for (int i=0; i<16; i++) {
printf("%#02X", key_ptr[i]);
if (i < 15) {
printf(",");
}
}
printf("\n\n");
}
void generate_aes_key()
{
uint8_t key[16];
for (int i = 0; i < 16; i++) {
key[i] = random(256) ^ micros();
unsigned long enter = hwMillis();
while (hwMillis() - enter < (unsigned long)2);
}
print_aes_key(key);
printf("To use this key, run mysgw with:\n"
" --set-aes-key=");
for (int i = 0; i < 16; i++) {
printf("%02X", key[i]);
}
printf("\n");
}
void set_aes_key(char *key_str)
{
uint8_t key[16];
if (strlen(key_str) != 32) {
printf("invalid key!\n");
} else {
for (int i = 0; i < 32; ++i) {
int n;
char c = key_str[i];
if (c <= '9') {
n = c - '0';
} else if (c >= 'a') {
n = c - 'a' + 10;
} else {
n = c - 'A' + 10;
}
if ((i & 0x1) == 0) {
key[i/2] = n * 16;
} else {
key[i/2] += n;
}
}
hwWriteConfigBlock(&key, reinterpret_cast<void*>EEPROM_RF_ENCRYPTION_AES_KEY_ADDRESS, 16);
print_aes_key();
}
}
int main(int argc, char *argv[])
{
int opt, log_opts, debug = 0, foreground = 1;
char *key = NULL;
/* register the signal handler */
signal(SIGINT, handle_sigint);
signal(SIGTERM, handle_sigint);
hwRandomNumberInit();
static struct option long_options[] = {
{"help", no_argument, 0, 'h'},
{"debug", no_argument, 0, 'd'},
{"background", no_argument, 0, 'b'},
{"gen-soft-hmac-key", no_argument, 0, 'A'},
{"gen-soft-serial-key", no_argument, 0, 'B'},
{"gen-aes-key", no_argument, 0, 'C'},
{"print-soft-hmac-key", no_argument, 0, 'D'},
{"print-soft-serial-key", no_argument, 0, 'E'},
{"print-aes-key", no_argument, 0, 'F'},
{"set-soft-hmac-key", required_argument, 0, 'G'},
{"set-soft-serial-key", required_argument, 0, 'H'},
{"set-aes-key", required_argument, 0, 'I'},
{0, 0, 0, 0}
};
int long_index = 0;
while ((opt = getopt_long(argc, argv,"hdbABCDEFGHI", long_options, &long_index )) != -1) {
switch (opt) {
case 'h':
print_usage();
exit(EXIT_SUCCESS);
case 'd':
debug = 1;
break;
case 'b':
foreground = 0;
break;
case 'A':
generate_soft_sign_hmac_key();
exit(EXIT_SUCCESS);
case 'B':
generate_soft_sign_serial_key();
exit(EXIT_SUCCESS);
case 'C':
generate_aes_key();
exit(EXIT_SUCCESS);
case 'D':
print_soft_sign_hmac_key();
exit(EXIT_SUCCESS);
case 'E':
print_soft_sign_serial_key();
exit(EXIT_SUCCESS);
case 'F':
print_aes_key();
exit(EXIT_SUCCESS);
case 'G':
key = strdup(optarg);
set_soft_sign_hmac_key(key);
exit(EXIT_SUCCESS);
case 'H':
key = strdup(optarg);
set_soft_sign_serial_key(key);
exit(EXIT_SUCCESS);
case 'I':
key = strdup(optarg);
set_aes_key(key);
exit(EXIT_SUCCESS);
default:
print_usage();
exit(EXIT_SUCCESS);
}
}
log_opts = LOG_CONS;
if (foreground && isatty(STDIN_FILENO)) {
// Also print syslog to stderror
log_opts |= LOG_PERROR;
}
if (!debug) {
// Ignore debug type messages
setlogmask(LOG_UPTO (LOG_INFO));
}
logOpen(log_opts, LOG_USER);
if (!foreground && !debug) {
if (daemonize() != 0) {
exit(EXIT_FAILURE);
}
}
logInfo("Starting gateway...\n");
logInfo("Protocol version - %s\n", MYSENSORS_LIBRARY_VERSION);
_begin(); // Startup MySensors library
for (;;) {
_process(); // Process incoming data
if (loop) {
loop(); // Call sketch loop
}
}
return 0;
}
+45
View File
@@ -0,0 +1,45 @@
/**
* The MySensors Arduino library handles the wireless radio link and protocol
* between your home built sensors/actuators and HA controller of choice.
* The sensors forms a self healing radio network with optional repeaters. Each
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
* network topology allowing messages to be routed to nodes.
*
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
* Copyright (C) 2013-2017 Sensnology AB
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
*
* Documentation: http://www.mysensors.org
* Support Forum: http://forum.mysensors.org
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*/
// Initialize library and handle sketch functions like we want to
extern "C" void __libc_init_array(void);
// Force init to be called *first*, i.e. before static object allocation.
// Otherwise, statically allocated objects that need libmaple may fail.
__attribute__(( constructor (101))) void premain()
{
init();
}
int main(void)
{
_begin();
for(;;) {
_process();
if (loop) {
loop();
}
if (serialEventRun) {
serialEventRun();
}
}
return 0;
}