MySensors 2.1.1 release (#752)
* Bump version to 2.2.0-beta (#713) * OTA: Add incoming FW block check (#718) * Linux: Add support for SPIDEV (#734) RPi and Linux refactor. Add GPIO Sysfs for GPIO operations. Update configure script. Fix some cppcheck warnings. Add serial emulation that prints to stdout. Fix some file headers. * Fix getControllerConfig() (#737) * Rename MyHwATmega328 to MyHwAVR (#738) * AVR: Restrict fast pin function use (#739) * Fix signing presentation bug (#740) * Consolidate open PRs for bugfix release (#741) * Revert "Bump version to 2.2.0-beta" (#744) * Merge Master into Dev (#745) * Fix spi flash error when compiling in Arduino IDE 1.6.6 * Bump minor version * Fixed "invalid suffix on literal" warning * Fix addressing bug in _doSign bitfield * Make sure nodes not supporting signing informs GW A node that does not support signing, still needs to inform the gateway about this to make sure the gateway carries a valid signing requirement table when a node Id that was requiering signing stops doing this. This fixes #286. * Prevent SecureActuator from accepting ACKs as commands As ACKs are not currently signed, allowing ACKs as commands is a considerable security hole for this sketch. This is now resolved. * Backport of bugfix (#259) in repeaters when forwarding signed messages * Bumped version to 1.5.2 * Corrected doSign variable name (was _doSign) * Bumped version to 1.5.3 * Add NULL termination to payloads Messages addressed to "this" node, will have a null char appended to the payload after message verification is done, because some "getters" assume the message being a string. * MySensors 2.1.1 release
This commit is contained in:
@@ -34,6 +34,22 @@ GATEWAY_OBJECTS+=$(patsubst %.c,$(BUILDDIR)/%.o,$(RPI_C_SOURCES)) $(patsubst %.c
|
||||
INCLUDES+=-I./drivers/RPi
|
||||
endif
|
||||
|
||||
ifeq ($(SPI_DRIVER), BCM)
|
||||
SPI_DRIVER_C_SOURCES=$(wildcard drivers/BCM/*.c)
|
||||
SPI_DRIVER_CPP_SOURCES=$(wildcard drivers/BCM/*.cpp)
|
||||
GATEWAY_OBJECTS+=$(patsubst %.c,$(BUILDDIR)/%.o,$(SPI_DRIVER_C_SOURCES)) $(patsubst %.cpp,$(BUILDDIR)/%.o,$(SPI_DRIVER_CPP_SOURCES))
|
||||
|
||||
INCLUDES+=-I./drivers/BCM
|
||||
endif
|
||||
|
||||
ifeq ($(SPI_DRIVER), SPIDEV)
|
||||
SPI_DRIVER_C_SOURCES=$(wildcard drivers/SPIDEV/*.c)
|
||||
SPI_DRIVER_CPP_SOURCES=$(wildcard drivers/SPIDEV/*.cpp)
|
||||
GATEWAY_OBJECTS+=$(patsubst %.c,$(BUILDDIR)/%.o,$(SPI_DRIVER_C_SOURCES)) $(patsubst %.cpp,$(BUILDDIR)/%.o,$(SPI_DRIVER_CPP_SOURCES))
|
||||
|
||||
INCLUDES+=-I./drivers/SPIDEV
|
||||
endif
|
||||
|
||||
# Gets include flags for library
|
||||
get_library_includes = $(if $(and $(wildcard $(1)/src), $(wildcard $(1)/library.properties)), \
|
||||
-I$(1)/src, \
|
||||
|
||||
+3
-3
@@ -903,12 +903,12 @@
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @def MY_IS_SERIAL_PTY
|
||||
* @def MY_LINUX_IS_SERIAL_PTY
|
||||
* @brief Set serial as a pseudo terminal.
|
||||
*
|
||||
* Enable this if you need to connect to a controller running on the same device.
|
||||
*/
|
||||
//#define MY_IS_SERIAL_PTY
|
||||
//#define MY_LINUX_IS_SERIAL_PTY
|
||||
|
||||
/**
|
||||
* @def MY_LINUX_SERIAL_PTY
|
||||
@@ -956,7 +956,7 @@
|
||||
#define MY_NODE_LOCK_FEATURE
|
||||
#define MY_REPEATER_FEATURE
|
||||
#define MY_LINUX_SERIAL_GROUPNAME
|
||||
#define MY_IS_SERIAL_PTY
|
||||
#define MY_LINUX_IS_SERIAL_PTY
|
||||
#define MY_RFM95_ATC_MODE_DISABLED
|
||||
#define MY_RFM95_RST_PIN
|
||||
#endif
|
||||
|
||||
+2
-6
@@ -62,16 +62,12 @@
|
||||
#include "core/MyHwESP8266.cpp"
|
||||
#elif defined(ARDUINO_ARCH_AVR)
|
||||
#include "drivers/AVR/DigitalWriteFast/digitalWriteFast.h"
|
||||
#include "core/MyHwATMega328.cpp"
|
||||
#include "core/MyHwAVR.cpp"
|
||||
#elif defined(ARDUINO_ARCH_SAMD)
|
||||
#include "core/MyHwSAMD.cpp"
|
||||
#elif defined(__linux__)
|
||||
#ifdef LINUX_ARCH_RASPBERRYPI
|
||||
#include "core/MyHwRPi.cpp"
|
||||
#else
|
||||
#include "core/MyHwLinuxGeneric.cpp"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// LEDS
|
||||
#if !defined(MY_DEFAULT_ERR_LED_PIN) && defined(MY_HW_ERR_LED_PIN)
|
||||
@@ -254,7 +250,7 @@ MY_DEFAULT_RX_LED_PIN in your sketch instead to enable LEDs
|
||||
#include "drivers/AVR/DigitalIO/DigitalIO.h"
|
||||
#endif
|
||||
|
||||
#if defined(MY_RADIO_NRF24) && defined(__linux__) && !defined(LINUX_ARCH_RASPBERRYPI)
|
||||
#if defined(MY_RADIO_NRF24) && defined(__linux__) && !(defined(LINUX_SPI_BCM) || defined(LINUX_SPI_SPIDEV))
|
||||
#error No support for nRF24 radio on this platform
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
MySensors Library v2.1.0
|
||||
MySensors Library v2.1.1
|
||||
|
||||
Please visit www.mysensors.org for more information
|
||||
|
||||
|
||||
@@ -11,6 +11,11 @@ Options:
|
||||
Help:
|
||||
-h, --help print this message
|
||||
|
||||
SPI driver options:
|
||||
--spi-driver=[BCM|SPIDEV]
|
||||
--spi-spidev-device=<DEVICE>
|
||||
Device path. [/dev/spidev0.0]
|
||||
|
||||
Building options:
|
||||
--soc=[BCM2835|BCM2836|AM33XX|A10|A13|A20|H3]
|
||||
SoC type to be used. [configure autodetected]
|
||||
@@ -58,6 +63,8 @@ MySensors options:
|
||||
--my-rf24-channel=<0-125> RF channel for the sensor net, 0-125. [76]
|
||||
--my-rf24-pa-level=[RF24_PA_MAX|RF24_PA_LOW]
|
||||
RF24 PA level. [RF24_PA_MAX]
|
||||
--my-rf24-ce-pin=<PIN> Pin number to use for rf24 Chip-Enable.
|
||||
--my-rf24-cs-pin=<PIN> Pin number to use for rf24 Chip-Select.
|
||||
--my-rf24-irq-pin=<PIN> Pin number connected to nRF24L01 IRQ pin.
|
||||
--my-rf24-encryption-enabled
|
||||
Enables RF24 encryption.
|
||||
@@ -209,7 +216,7 @@ function gcc_cpu_flags {
|
||||
flags="-march=armv7-a -mtune=cortex-a7 -mfpu=neon-vfpv4 -mfloat-abi=hard"
|
||||
;;
|
||||
H3)
|
||||
flags="-march=armv8-a -mtune=cortex-a53 -mfpu=neon-vfpv4 -mfloat-abi=hard"
|
||||
flags="-march=armv7-a -mtune=cortex-a7 -mfpu=neon-vfpv4 -mfloat-abi=hard"
|
||||
;;
|
||||
*)
|
||||
flags=""
|
||||
@@ -224,7 +231,7 @@ transport_type=nrf24
|
||||
signing=none
|
||||
signing_request_signatures=false
|
||||
|
||||
params="SOC CFLAGS CXXFLAGS CPPFLAGS LDFLAGS PREFIX CC CXX ARDUINO_LIB_DIR BUILDDIR BINDIR GATEWAY_DIR INIT_SYSTEM"
|
||||
params="SOC CFLAGS CXXFLAGS CPPFLAGS LDFLAGS PREFIX CC CXX ARDUINO_LIB_DIR BUILDDIR BINDIR GATEWAY_DIR INIT_SYSTEM SPI_DRIVER"
|
||||
|
||||
for opt do
|
||||
if [ "$opt" = "-h" ] || [ "$opt" = "--help" ]; then
|
||||
@@ -233,6 +240,12 @@ for opt do
|
||||
fi
|
||||
optarg="${opt#*=}"
|
||||
case "$opt" in
|
||||
--spi-driver=*)
|
||||
SPI_DRIVER="$optarg"
|
||||
;;
|
||||
--spi-spidev-device=*)
|
||||
CPPFLAGS="-DSPI_SPIDEV_DEVICE=\\\"${optarg}\\\" $CPPFLAGS"
|
||||
;;
|
||||
--soc=*)
|
||||
SOC="$optarg"
|
||||
;;
|
||||
@@ -308,7 +321,7 @@ for opt do
|
||||
CPPFLAGS="-DMY_BAUD_RATE=${optarg} $CPPFLAGS"
|
||||
;;
|
||||
--my-serial-is-pty*)
|
||||
CPPFLAGS="-DMY_IS_SERIAL_PTY $CPPFLAGS"
|
||||
CPPFLAGS="-DMY_LINUX_IS_SERIAL_PTY $CPPFLAGS"
|
||||
;;
|
||||
--my-serial-pty=*)
|
||||
CPPFLAGS="-DMY_LINUX_SERIAL_PTY=\\\"${optarg}\\\" $CPPFLAGS"
|
||||
@@ -322,6 +335,12 @@ for opt do
|
||||
--my-rf24-pa-level=*)
|
||||
CPPFLAGS="-DMY_RF24_PA_LEVEL=${optarg} $CPPFLAGS"
|
||||
;;
|
||||
--my-rf24-ce-pin=*)
|
||||
CPPFLAGS="-DMY_RF24_CE_PIN=${optarg} $CPPFLAGS"
|
||||
;;
|
||||
--my-rf24-cs-pin=*)
|
||||
CPPFLAGS="-DMY_RF24_CS_PIN=${optarg} $CPPFLAGS"
|
||||
;;
|
||||
--my-controller-url-address=*)
|
||||
CPPFLAGS="-DMY_CONTROLLER_URL_ADDRESS=\\\"${optarg}\\\" $CPPFLAGS"
|
||||
;;
|
||||
@@ -406,7 +425,7 @@ if [ -z "${SOC}" ]; then
|
||||
SOC=${info[0]}
|
||||
TYPE=${info[1]}
|
||||
CPU=${info[2]}
|
||||
echo "[OK] machine detected: SoC=${SOC}, Type=${TYPE}, CPU=${CPU}."
|
||||
echo " [OK] machine detected: SoC=${SOC}, Type=${TYPE}, CPU=${CPU}."
|
||||
fi
|
||||
|
||||
if [ -z "${CPUFLAGS}" ]; then
|
||||
@@ -415,6 +434,40 @@ fi
|
||||
|
||||
if [[ $SOC == "BCM2835" || $SOC == "BCM2836" ]]; then
|
||||
CPPFLAGS="-DLINUX_ARCH_RASPBERRYPI $CPPFLAGS"
|
||||
else
|
||||
echo "[SECTION] Checking GPIO Sysfs."
|
||||
if [[ $(eval 'ls /sys/class/gpio/export 2>/dev/null') ]]; then
|
||||
echo " [OK] /sys/class/gpio/export found"
|
||||
else
|
||||
echo " [WARNING] /sys/class/gpio/export not found."
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -z "${SPI_DRIVER}" ]; then
|
||||
echo "[SECTION] Detecting SPI driver."
|
||||
if [[ $SOC == "BCM2835" || $SOC == "BCM2836" ]]; then
|
||||
SPI_DRIVER=BCM
|
||||
elif [[ $(eval 'ls /dev/spidev* 2>/dev/null') ]]; then
|
||||
SPI_DRIVER=SPIDEV
|
||||
fi
|
||||
if [ -n "${SPI_DRIVER}" ]; then
|
||||
echo " [OK] SPI driver detected:${SPI_DRIVER}."
|
||||
else
|
||||
echo " [WARNING] No supported SPI driver detected."
|
||||
fi
|
||||
fi
|
||||
if [ -n "${SPI_DRIVER}" ]; then
|
||||
case ${SPI_DRIVER} in
|
||||
BCM)
|
||||
CPPFLAGS="-DLINUX_SPI_BCM $CPPFLAGS"
|
||||
;;
|
||||
SPIDEV)
|
||||
CPPFLAGS="-DLINUX_SPI_SPIDEV $CPPFLAGS"
|
||||
;;
|
||||
*)
|
||||
die "Unsupported SPI driver: ${SPI_DRIVER}." 1
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
if [[ ${debug} == "enable" ]]; then
|
||||
@@ -431,9 +484,7 @@ elif [[ ${gateway_type} == "serial" ]]; then
|
||||
elif [[ ${gateway_type} == "mqtt" ]]; then
|
||||
CPPFLAGS="-DMY_GATEWAY_LINUX -DMY_GATEWAY_MQTT_CLIENT $CPPFLAGS"
|
||||
else
|
||||
echo "Invalid gateway type."
|
||||
echo "Aborting."
|
||||
exit 1
|
||||
die "Invalid gateway type." 2
|
||||
fi
|
||||
|
||||
if [[ ${transport_type} == "none" ]]; then
|
||||
@@ -446,9 +497,7 @@ elif [[ ${transport_type} == "rs485" ]]; then
|
||||
elif [[ ${transport_type} == "rfm95" ]]; then
|
||||
CPPFLAGS="-DMY_RADIO_RFM95 $CPPFLAGS"
|
||||
else
|
||||
echo "Invalid transport type."
|
||||
echo "Aborting."
|
||||
exit 1
|
||||
die "Invalid transport type." 3
|
||||
fi
|
||||
|
||||
if [[ ${signing} == "none" ]]; then
|
||||
@@ -460,24 +509,23 @@ elif [[ ${signing} == "software" ]]; then
|
||||
CPPFLAGS="-DMY_SIGNING_REQUEST_SIGNATURES $CPPFLAGS"
|
||||
fi
|
||||
else
|
||||
echo "Invalid message signing option."
|
||||
echo "Aborting."
|
||||
exit 1
|
||||
die "Invalid message signing option." 4
|
||||
fi
|
||||
|
||||
LDFLAGS="-pthread $LDFLAGS"
|
||||
CPPFLAGS="$CPUFLAGS $CPPFLAGS"
|
||||
|
||||
echo "[SECTION] Detecting init system."
|
||||
if [ "${NO_INIT}" ]; then
|
||||
echo "[OK] no init system chosen."
|
||||
echo " [OK] no init system chosen."
|
||||
elif [ -x /usr/bin/systemctl ] || [ -x /bin/systemctl ]; then
|
||||
INIT_SYSTEM=systemd
|
||||
echo "[OK] init system detected: systemd"
|
||||
echo " [OK] init system detected: systemd."
|
||||
elif [ -f /etc/init.d/cron ] && [ ! -h /etc/init.d/cron ]; then
|
||||
INIT_SYSTEM=sysvinit
|
||||
echo "[OK] init system detected: sysvinit"
|
||||
echo " [OK] init system detected: sysvinit."
|
||||
else
|
||||
echo "[FAILED] unknown init system"
|
||||
echo " [FAILED] unknown init system."
|
||||
fi
|
||||
|
||||
echo "[SECTION] Saving configuration."
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
#ifdef ARDUINO_ARCH_AVR
|
||||
|
||||
#include "MyHwATMega328.h"
|
||||
#include "MyHwAVR.h"
|
||||
|
||||
#define INVALID_INTERRUPT_NUM (0xFFu)
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#ifndef MyHwATMega328_h
|
||||
#define MyHwATMega328_h
|
||||
#ifndef MyHwAVR_h
|
||||
#define MyHwAVR_h
|
||||
|
||||
#include "MyHw.h"
|
||||
#include <avr/eeprom.h>
|
||||
@@ -58,12 +58,10 @@
|
||||
|
||||
|
||||
// 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)
|
||||
|
||||
|
||||
#if defined(MY_DISABLED_SERIAL)
|
||||
#define hwInit()
|
||||
#else
|
||||
@@ -28,8 +28,8 @@ static SoftEeprom eeprom = SoftEeprom(MY_LINUX_CONFIG_FILE, 1024); // ATMega328
|
||||
|
||||
void hwInit()
|
||||
{
|
||||
#ifdef MY_GATEWAY_SERIAL
|
||||
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");
|
||||
@@ -120,6 +120,21 @@ uint16_t hwFreeMem()
|
||||
}
|
||||
#endif
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
#ifdef MY_DEBUG
|
||||
void hwDebugPrint(const char *fmt, ...)
|
||||
{
|
||||
|
||||
@@ -24,12 +24,17 @@
|
||||
#include <pthread.h>
|
||||
#include "MyHw.h"
|
||||
#include "SerialPort.h"
|
||||
#include "SerialSimulator.h"
|
||||
|
||||
#ifdef MY_IS_SERIAL_PTY
|
||||
#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
|
||||
@@ -39,9 +44,9 @@ SerialPort Serial = SerialPort(MY_LINUX_SERIAL_PORT);
|
||||
#define hwWatchdogReset()
|
||||
#define hwReboot()
|
||||
|
||||
#define hwDigitalWrite(__pin, __value) _Pragma("GCC error \"Not supported on linux-generic\"")
|
||||
#define hwDigitalRead(__pin) _Pragma("GCC error \"Not supported on linux-generic\"")
|
||||
#define hwPinMode(__pin, __value) _Pragma("GCC error \"Not supported on linux-generic\"")
|
||||
inline void hwDigitalWrite(uint8_t, uint8_t);
|
||||
inline int hwDigitalRead(uint8_t);
|
||||
inline void hwPinMode(uint8_t, uint8_t);
|
||||
|
||||
void hwInit();
|
||||
inline void hwReadConfigBlock(void* buf, void* addr, size_t length);
|
||||
|
||||
@@ -1,146 +0,0 @@
|
||||
/**
|
||||
* 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-2016 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 "MyHwRPi.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <time.h>
|
||||
#include "SoftEeprom.h"
|
||||
|
||||
static SoftEeprom eeprom = SoftEeprom(MY_LINUX_CONFIG_FILE, 1024); // ATMega328 has 1024 bytes
|
||||
|
||||
void hwInit()
|
||||
{
|
||||
#ifdef MY_GATEWAY_SERIAL
|
||||
MY_SERIALDEVICE.begin(MY_BAUD_RATE);
|
||||
#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
|
||||
}
|
||||
|
||||
void hwReadConfigBlock(void* buf, void* adr, size_t length)
|
||||
{
|
||||
eeprom.readBlock(buf, adr, length);
|
||||
}
|
||||
|
||||
void hwWriteConfigBlock(void* buf, void* adr, size_t length)
|
||||
{
|
||||
eeprom.writeBlock(buf, adr, length);
|
||||
}
|
||||
|
||||
uint8_t hwReadConfig(int adr)
|
||||
{
|
||||
return eeprom.readByte(adr);
|
||||
}
|
||||
|
||||
void hwWriteConfig(int adr, uint8_t value)
|
||||
{
|
||||
eeprom.writeByte(adr, value);
|
||||
}
|
||||
|
||||
void hwRandomNumberInit()
|
||||
{
|
||||
randomSeed(time(NULL));
|
||||
}
|
||||
|
||||
unsigned long hwMillis()
|
||||
{
|
||||
return millis();
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
#if defined(MY_DEBUG) || defined(MY_SPECIAL_DEBUG)
|
||||
uint16_t hwCPUVoltage()
|
||||
{
|
||||
// TODO: Not supported!
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16_t hwCPUFrequency()
|
||||
{
|
||||
// TODO: Not supported!
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16_t hwFreeMem()
|
||||
{
|
||||
// TODO: Not supported!
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef MY_DEBUG
|
||||
void hwDebugPrint(const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
va_start(args, fmt);
|
||||
vlogDebug(fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
#endif
|
||||
|
||||
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);
|
||||
}
|
||||
@@ -44,6 +44,7 @@ typedef enum {
|
||||
INDICATION_WAKEUP, //!< Node just woke from sleep.
|
||||
INDICATION_FW_UPDATE_START, //!< Start of OTA firmware update process.
|
||||
INDICATION_FW_UPDATE_RX, //!< Received a piece of firmware data.
|
||||
INDICATION_FW_UPDATE_RX_ERR, //!< Received wrong piece of firmware data.
|
||||
|
||||
INDICATION_ERR_START = 100,
|
||||
INDICATION_ERR_TX, //!< Failed to transmit message.
|
||||
|
||||
+15
-15
@@ -50,7 +50,7 @@ void handle_sigint(int sig)
|
||||
|
||||
closelog();
|
||||
|
||||
exit(0);
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
static int daemonize(void)
|
||||
@@ -167,12 +167,12 @@ void generate_soft_sign_hmac_key()
|
||||
void set_soft_sign_hmac_key(char *key_str)
|
||||
{
|
||||
uint8_t key[32];
|
||||
int n;
|
||||
|
||||
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';
|
||||
@@ -242,12 +242,12 @@ void generate_soft_sign_serial_key()
|
||||
void set_soft_sign_serial_key(char *key_str)
|
||||
{
|
||||
uint8_t key[9];
|
||||
int n;
|
||||
|
||||
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';
|
||||
@@ -317,12 +317,12 @@ void generate_aes_key()
|
||||
void set_aes_key(char *key_str)
|
||||
{
|
||||
uint8_t key[16];
|
||||
int n;
|
||||
|
||||
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';
|
||||
@@ -375,7 +375,7 @@ int main(int argc, char *argv[])
|
||||
switch (opt) {
|
||||
case 'h':
|
||||
print_usage();
|
||||
exit(0);
|
||||
exit(EXIT_SUCCESS);
|
||||
case 'd':
|
||||
debug = 1;
|
||||
break;
|
||||
@@ -384,37 +384,37 @@ int main(int argc, char *argv[])
|
||||
break;
|
||||
case 'A':
|
||||
generate_soft_sign_hmac_key();
|
||||
exit(0);
|
||||
exit(EXIT_SUCCESS);
|
||||
case 'B':
|
||||
generate_soft_sign_serial_key();
|
||||
exit(0);
|
||||
exit(EXIT_SUCCESS);
|
||||
case 'C':
|
||||
generate_aes_key();
|
||||
exit(0);
|
||||
exit(EXIT_SUCCESS);
|
||||
case 'D':
|
||||
print_soft_sign_hmac_key();
|
||||
exit(0);
|
||||
exit(EXIT_SUCCESS);
|
||||
case 'E':
|
||||
print_soft_sign_serial_key();
|
||||
exit(0);
|
||||
exit(EXIT_SUCCESS);
|
||||
case 'F':
|
||||
print_aes_key();
|
||||
exit(0);
|
||||
exit(EXIT_SUCCESS);
|
||||
case 'G':
|
||||
key = strdup(optarg);
|
||||
set_soft_sign_hmac_key(key);
|
||||
exit(0);
|
||||
exit(EXIT_SUCCESS);
|
||||
case 'H':
|
||||
key = strdup(optarg);
|
||||
set_soft_sign_serial_key(key);
|
||||
exit(0);
|
||||
exit(EXIT_SUCCESS);
|
||||
case 'I':
|
||||
key = strdup(optarg);
|
||||
set_aes_key(key);
|
||||
exit(0);
|
||||
exit(EXIT_SUCCESS);
|
||||
default:
|
||||
print_usage();
|
||||
exit(0);
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -93,19 +93,26 @@ bool firmwareOTAUpdateProcess(void)
|
||||
OTA_DEBUG(PSTR("OTA:FWP:UPDATE SKIPPED\n")); // FW update skipped, no newer version available
|
||||
} else if (_msg.type == ST_FIRMWARE_RESPONSE) {
|
||||
if (_firmwareUpdateOngoing) {
|
||||
// Save block to flash
|
||||
setIndication(INDICATION_FW_UPDATE_RX);
|
||||
OTA_DEBUG(PSTR("OTA:FWP:RECV B=%04X\n"), _firmwareBlock); // received FW block
|
||||
// extract FW block
|
||||
replyFirmwareBlock_t *firmwareResponse = (replyFirmwareBlock_t *)_msg.data;
|
||||
// write to flash
|
||||
|
||||
OTA_DEBUG(PSTR("OTA:FWP:RECV B=%04X\n"), firmwareResponse->block); // received FW block
|
||||
if (firmwareResponse->block != _firmwareBlock - 1) {
|
||||
OTA_DEBUG(PSTR("!OTA:FWP:WRONG FWB\n")); // received FW block
|
||||
// wrong firmware block received
|
||||
setIndication(INDICATION_FW_UPDATE_RX_ERR);
|
||||
// no further processing required
|
||||
return true;
|
||||
}
|
||||
setIndication(INDICATION_FW_UPDATE_RX);
|
||||
// Save block to flash
|
||||
_flash.writeBytes( ((_firmwareBlock - 1) * FIRMWARE_BLOCK_SIZE) + FIRMWARE_START_OFFSET,
|
||||
firmwareResponse->data, FIRMWARE_BLOCK_SIZE);
|
||||
// wait until flash written
|
||||
while (_flash.busy()) {}
|
||||
_firmwareBlock--;
|
||||
if (!_firmwareBlock) {
|
||||
// We're finished! Do a checksum and reboot.
|
||||
// We're done! Do a checksum and reboot.
|
||||
OTA_DEBUG(PSTR("OTA:FWP:FW END\n")); // received FW block
|
||||
_firmwareUpdateOngoing = false;
|
||||
if (transportIsValidFirmware()) {
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
* |!| OTA | FWP | FLASH INIT FAIL | Failed to initialise flash
|
||||
* | | OTA | FWP | UPDATE SKIPPED | FW update skipped, no newer version available
|
||||
* | | OTA | FWP | RECV B=%04X | Received FW block (B)
|
||||
* |!| OTA | FWP | WRONG FWB | Wrong FW block received
|
||||
* | | OTA | FWP | FW END | FW received, proceed to CRC verification
|
||||
* | | OTA | FWP | CRC OK | FW CRC verification OK
|
||||
* |!| OTA | FWP | CRC FAIL | FW CRC verification failed
|
||||
|
||||
@@ -262,7 +262,7 @@ uint8_t getDistanceGW(void)
|
||||
return result;
|
||||
}
|
||||
|
||||
controllerConfig_t getConfig(void)
|
||||
controllerConfig_t getControllerConfig(void)
|
||||
{
|
||||
return _coreConfig.controllerConfig;
|
||||
}
|
||||
|
||||
+21
-18
@@ -337,7 +337,8 @@ static bool skipSign(MyMessage &msg)
|
||||
msg.type == I_FIND_PARENT_REQUEST || msg.type == I_FIND_PARENT_RESPONSE ||
|
||||
msg.type == I_HEARTBEAT_REQUEST || msg.type == I_HEARTBEAT_RESPONSE ||
|
||||
msg.type == I_PING || msg.type == I_PONG ||
|
||||
msg.type == I_REGISTRATION_REQUEST )) {
|
||||
msg.type == I_REGISTRATION_REQUEST || msg.type == I_DISCOVER_REQUEST ||
|
||||
msg.type == I_DISCOVER_RESPONSE )) {
|
||||
SIGN_DEBUG(PSTR("Skipping security for command %d type %d\n"), mGetCommand(msg), msg.type);
|
||||
ret = true;
|
||||
} else if (mGetCommand(msg) == C_STREAM &&
|
||||
@@ -366,6 +367,7 @@ static void prepareSigningPresentation(MyMessage &msg, uint8_t destination)
|
||||
// Helper to process presentation mesages
|
||||
static bool signerInternalProcessPresentation(MyMessage &msg)
|
||||
{
|
||||
const uint8_t sender = msg.sender;
|
||||
#if defined(MY_SIGNING_FEATURE)
|
||||
if (msg.data[0] != SIGNING_PRESENTATION_VERSION_1) {
|
||||
SIGN_DEBUG(PSTR("Unsupported signing presentation version (%d)!\n"), msg.data[0]);
|
||||
@@ -374,21 +376,21 @@ static bool signerInternalProcessPresentation(MyMessage &msg)
|
||||
// We only handle version 1 here...
|
||||
if (msg.data[1] & SIGNING_PRESENTATION_REQUIRE_SIGNATURES) {
|
||||
// We received an indicator that the sender require us to sign all messages we send to it
|
||||
SIGN_DEBUG(PSTR("Mark node %d as one that require signed messages\n"), msg.sender);
|
||||
SET_SIGN(msg.sender);
|
||||
SIGN_DEBUG(PSTR("Mark node %d as one that require signed messages\n"), sender);
|
||||
SET_SIGN(sender);
|
||||
} else {
|
||||
// We received an indicator that the sender does not require us to sign all messages we send to it
|
||||
SIGN_DEBUG(PSTR("Mark node %d as one that do not require signed messages\n"), msg.sender);
|
||||
CLEAR_SIGN(msg.sender);
|
||||
SIGN_DEBUG(PSTR("Mark node %d as one that do not require signed messages\n"), sender);
|
||||
CLEAR_SIGN(sender);
|
||||
}
|
||||
if (msg.data[1] & SIGNING_PRESENTATION_REQUIRE_WHITELISTING) {
|
||||
// We received an indicator that the sender require us to salt signatures with serial
|
||||
SIGN_DEBUG(PSTR("Mark node %d as one that require whitelisting\n"), msg.sender);
|
||||
SET_WHITELIST(msg.sender);
|
||||
SIGN_DEBUG(PSTR("Mark node %d as one that require whitelisting\n"), sender);
|
||||
SET_WHITELIST(sender);
|
||||
} else {
|
||||
// We received an indicator that the sender does not require us to sign all messages we send to it
|
||||
SIGN_DEBUG(PSTR("Mark node %d as one that do not require whitelisting\n"), msg.sender);
|
||||
CLEAR_WHITELIST(msg.sender);
|
||||
SIGN_DEBUG(PSTR("Mark node %d as one that do not require whitelisting\n"), sender);
|
||||
CLEAR_WHITELIST(sender);
|
||||
}
|
||||
|
||||
// Save updated tables
|
||||
@@ -400,12 +402,12 @@ static bool signerInternalProcessPresentation(MyMessage &msg)
|
||||
// Inform sender about our preference if we are a gateway, but only require signing if the sender
|
||||
// required signing unless we explicitly configure it to
|
||||
#if defined(MY_GATEWAY_FEATURE)
|
||||
prepareSigningPresentation(msg, msg.sender);
|
||||
prepareSigningPresentation(msg, sender);
|
||||
#if defined(MY_SIGNING_REQUEST_SIGNATURES)
|
||||
#if defined(MY_SIGNING_GW_REQUEST_SIGNATURES_FROM_ALL)
|
||||
msg.data[1] |= SIGNING_PRESENTATION_REQUIRE_SIGNATURES;
|
||||
#else
|
||||
if (DO_SIGN(msg.sender)) {
|
||||
if (DO_SIGN(sender)) {
|
||||
msg.data[1] |= SIGNING_PRESENTATION_REQUIRE_SIGNATURES;
|
||||
}
|
||||
#endif
|
||||
@@ -414,20 +416,20 @@ static bool signerInternalProcessPresentation(MyMessage &msg)
|
||||
#if defined(MY_SIGNING_GW_REQUEST_SIGNATURES_FROM_ALL)
|
||||
msg.data[1] |= SIGNING_PRESENTATION_REQUIRE_WHITELISTING;
|
||||
#else
|
||||
if (DO_WHITELIST(msg.sender)) {
|
||||
if (DO_WHITELIST(sender)) {
|
||||
msg.data[1] |= SIGNING_PRESENTATION_REQUIRE_WHITELISTING;
|
||||
}
|
||||
#endif
|
||||
#endif // MY_SIGNING_NODE_WHITELISTING
|
||||
if (msg.data[1] & SIGNING_PRESENTATION_REQUIRE_SIGNATURES) {
|
||||
SIGN_DEBUG(PSTR("Informing node %d that we require signatures\n"), msg.sender);
|
||||
SIGN_DEBUG(PSTR("Informing node %d that we require signatures\n"), sender);
|
||||
} else {
|
||||
SIGN_DEBUG(PSTR("Informing node %d that we do not require signatures\n"), msg.sender);
|
||||
SIGN_DEBUG(PSTR("Informing node %d that we do not require signatures\n"), sender);
|
||||
}
|
||||
if (msg.data[1] & SIGNING_PRESENTATION_REQUIRE_WHITELISTING) {
|
||||
SIGN_DEBUG(PSTR("Informing node %d that we require whitelisting\n"), msg.sender);
|
||||
SIGN_DEBUG(PSTR("Informing node %d that we require whitelisting\n"), sender);
|
||||
} else {
|
||||
SIGN_DEBUG(PSTR("Informing node %d that we do not require whitelisting\n"), msg.sender);
|
||||
SIGN_DEBUG(PSTR("Informing node %d that we do not require whitelisting\n"), sender);
|
||||
}
|
||||
if (!_sendRoute(msg)) {
|
||||
SIGN_DEBUG(PSTR("Failed to transmit signing presentation!\n"));
|
||||
@@ -437,10 +439,10 @@ static bool signerInternalProcessPresentation(MyMessage &msg)
|
||||
#if defined(MY_GATEWAY_FEATURE)
|
||||
// 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, msg.sender);
|
||||
prepareSigningPresentation(msg, sender);
|
||||
SIGN_DEBUG(
|
||||
PSTR("Informing node %d that we do not require signatures because we do not support it\n"),
|
||||
msg.sender);
|
||||
sender);
|
||||
if (!_sendRoute(msg)) {
|
||||
SIGN_DEBUG(PSTR("Failed to transmit signing presentation!\n"));
|
||||
}
|
||||
@@ -448,6 +450,7 @@ static bool signerInternalProcessPresentation(MyMessage &msg)
|
||||
// If we act as a node and do not have the signing feature then we just silently drop any signing
|
||||
// presentation messages received
|
||||
(void)msg;
|
||||
(void)sender;
|
||||
SIGN_DEBUG(PSTR("Received signing presentation, but signing is not supported (message ignored)\n"));
|
||||
#endif // not MY_GATEWAY_FEATURE
|
||||
#endif // not MY_SIGNING_FEATURE
|
||||
|
||||
+2
-2
@@ -6,7 +6,7 @@
|
||||
* network topology allowing messages to be routed to nodes.
|
||||
*
|
||||
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
|
||||
* Copyright (C) 2013-2015 Sensnology AB
|
||||
* Copyright (C) 2013-2017 Sensnology AB
|
||||
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
|
||||
*
|
||||
* Documentation: http://www.mysensors.org
|
||||
@@ -24,6 +24,6 @@
|
||||
#ifndef Version_h
|
||||
#define Version_h
|
||||
|
||||
#define MYSENSORS_LIBRARY_VERSION "2.1.0"
|
||||
#define MYSENSORS_LIBRARY_VERSION "2.1.1"
|
||||
|
||||
#endif
|
||||
|
||||
@@ -6,67 +6,7 @@
|
||||
#ifndef __digitalWriteFast_h_
|
||||
#define __digitalWriteFast_h_
|
||||
|
||||
#if defined(ARDUINO_AVR_MEGA) || defined(ARDUINO_AVR_MEGA1280) || defined(ARDUINO_AVR_MEGA2560) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega2561__)
|
||||
#define __digitalPinToPortReg(__pin) \
|
||||
(((__pin) >= 22 && (__pin) <= 29) ? &PORTA : \
|
||||
((((__pin) >= 10 && (__pin) <= 13) || ((__pin) >= 50 && (__pin) <= 53)) ? &PORTB : \
|
||||
(((__pin) >= 30 && (__pin) <= 37) ? &PORTC : \
|
||||
((((__pin) >= 18 && (__pin) <= 21) || (__pin) == 38) ? &PORTD : \
|
||||
((((__pin) <= 3) || (__pin) == 5) ? &PORTE : \
|
||||
(((__pin) >= 54 && (__pin) <= 61) ? &PORTF : \
|
||||
((((__pin) >= 39 && (__pin) <= 41) || (__pin) == 4) ? &PORTG : \
|
||||
((((__pin) >= 6 && (__pin) <= 9) || (__pin) == 16 || (__pin) == 17) ? &PORTH : \
|
||||
(((__pin) == 14 || (__pin) == 15) ? &PORTJ : \
|
||||
(((__pin) >= 62 && (__pin) <= 69) ? &PORTK : &PORTL))))))))))
|
||||
#define __digitalPinToDDRReg(__pin) \
|
||||
(((__pin) >= 22 && (__pin) <= 29) ? &DDRA : \
|
||||
((((__pin) >= 10 && (__pin) <= 13) || ((__pin) >= 50 && (__pin) <= 53)) ? &DDRB : \
|
||||
(((__pin) >= 30 && (__pin) <= 37) ? &DDRC : \
|
||||
((((__pin) >= 18 && (__pin) <= 21) || (__pin) == 38) ? &DDRD : \
|
||||
((((__pin) <= 3) || (__pin) == 5) ? &DDRE : \
|
||||
(((__pin) >= 54 && (__pin) <= 61) ? &DDRF : \
|
||||
((((__pin) >= 39 && (__pin) <= 41) || (__pin) == 4) ? &DDRG : \
|
||||
((((__pin) >= 6 && (__pin) <= 9) || (__pin) == 16 || (__pin) == 17) ? &DDRH : \
|
||||
(((__pin) == 14 || (__pin) == 15) ? &DDRJ : \
|
||||
(((__pin) >= 62 && (__pin) <= 69) ? &DDRK : &DDRL))))))))))
|
||||
#define __digitalPinToPINReg(__pin) \
|
||||
(((__pin) >= 22 && (__pin) <= 29) ? &PINA : \
|
||||
((((__pin) >= 10 && (__pin) <= 13) || ((__pin) >= 50 && (__pin) <= 53)) ? &PINB : \
|
||||
(((__pin) >= 30 && (__pin) <= 37) ? &PINC : \
|
||||
((((__pin) >= 18 && (__pin) <= 21) || (__pin) == 38) ? &PIND : \
|
||||
((((__pin) <= 3) || (__pin) == 5) ? &PINE : \
|
||||
(((__pin) >= 54 && (__pin) <= 61) ? &PINF : \
|
||||
((((__pin) >= 39 && (__pin) <= 41) || (__pin) == 4) ? &PING : \
|
||||
((((__pin) >= 6 && (__pin) <= 9) || (__pin) == 16 || (__pin) == 17) ? &PINH : \
|
||||
(((__pin) == 14 || (__pin) == 15) ? &PINJ : \
|
||||
(((__pin) >= 62 && (__pin) <= 69) ? &PINK : &PINL))))))))))
|
||||
#define __digitalPinToBit(__pin) \
|
||||
(((__pin) >= 7 && (__pin) <= 9) ? (__pin) - 3 : \
|
||||
(((__pin) >= 10 && (__pin) <= 13) ? (__pin) - 6 : \
|
||||
(((__pin) >= 22 && (__pin) <= 29) ? (__pin) - 22 : \
|
||||
(((__pin) >= 30 && (__pin) <= 37) ? 37 - (__pin) : \
|
||||
(((__pin) >= 39 && (__pin) <= 41) ? 41 - (__pin) : \
|
||||
(((__pin) >= 42 && (__pin) <= 49) ? 49 - (__pin) : \
|
||||
(((__pin) >= 50 && (__pin) <= 53) ? 53 - (__pin) : \
|
||||
(((__pin) >= 54 && (__pin) <= 61) ? (__pin) - 54 : \
|
||||
(((__pin) >= 62 && (__pin) <= 69) ? (__pin) - 62 : \
|
||||
(((__pin) == 0 || (__pin) == 15 || (__pin) == 17 || (__pin) == 21) ? 0 : \
|
||||
(((__pin) == 1 || (__pin) == 14 || (__pin) == 16 || (__pin) == 20) ? 1 : \
|
||||
(((__pin) == 19) ? 2 : \
|
||||
(((__pin) == 5 || (__pin) == 6 || (__pin) == 18) ? 3 : \
|
||||
(((__pin) == 2) ? 4 : \
|
||||
(((__pin) == 3 || (__pin) == 4) ? 5 : 7)))))))))))))))
|
||||
#elif defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__)
|
||||
#define __digitalPinToPortReg(__pin) (((__pin) <= 7) ? &PORTB : (((__pin) >= 8 && (__pin) <= 15) ? &PORTD : (((__pin) >= 16 && (__pin) <= 23) ? &PORTC : &PORTA)))
|
||||
#define __digitalPinToDDRReg(__pin) (((__pin) <= 7) ? &DDRB : (((__pin) >= 8 && (__pin) <= 15) ? &DDRD : (((__pin) >= 8 && (__pin) <= 15) ? &DDRC : &DDRA)))
|
||||
#define __digitalPinToPINReg(__pin) (((__pin) <= 7) ? &PINB : (((__pin) >= 8 && (__pin) <= 15) ? &PIND : (((__pin) >= 8 && (__pin) <= 15) ? &PINC : &PINA)))
|
||||
#define __digitalPinToBit(__pin) (((__pin) <= 7) ? (__pin) : (((__pin) >= 8 && (__pin) <= 15) ? (__pin) - 8 : (((__pin) >= 16 && (__pin) <= 23) ? (__pin) - 16 : (__pin) - 24)))
|
||||
#elif defined(ARDUINO_AVR_LEONARDO) || defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__)
|
||||
#define __digitalPinToPortReg(__pin) ((((__pin) <= 4) || (__pin) == 6 || (__pin) == 12 || (__pin) == 24 || (__pin) == 25 || (__pin) == 29) ? &PORTD : (((__pin) == 5 || (__pin) == 13) ? &PORTC : (((__pin) >= 18 && (__pin) <= 23)) ? &PORTF : (((__pin) == 7) ? &PORTE : &PORTB)))
|
||||
#define __digitalPinToDDRReg(__pin) ((((__pin) <= 4) || (__pin) == 6 || (__pin) == 12 || (__pin) == 24 || (__pin) == 25 || (__pin) == 29) ? &DDRD : (((__pin) == 5 || (__pin) == 13) ? &DDRC : (((__pin) >= 18 && (__pin) <= 23)) ? &DDRF : (((__pin) == 7) ? &DDRE : &DDRB)))
|
||||
#define __digitalPinToPINReg(__pin) ((((__pin) <= 4) || (__pin) == 6 || (__pin) == 12 || (__pin) == 24 || (__pin) == 25 || (__pin) == 29) ? &PIND : (((__pin) == 5 || (__pin) == 13) ? &PINC : (((__pin) >= 18 && (__pin) <= 23)) ? &PINF : (((__pin) == 7) ? &PINE : &PINB)))
|
||||
#define __digitalPinToBit(__pin) (((__pin) >= 8 && (__pin) <= 11) ? (__pin) - 4 : (((__pin) >= 18 && (__pin) <= 21) ? 25 - (__pin) : (((__pin) == 0) ? 2 : (((__pin) == 1) ? 3 : (((__pin) == 2) ? 1 : (((__pin) == 3) ? 0 : (((__pin) == 4) ? 4 : (((__pin) == 6) ? 7 : (((__pin) == 13) ? 7 : (((__pin) == 14) ? 3 : (((__pin) == 15) ? 1 : (((__pin) == 16) ? 2 : (((__pin) == 17) ? 0 : (((__pin) == 22) ? 1 : (((__pin) == 23) ? 0 : (((__pin) == 24) ? 4 : (((__pin) == 25) ? 7 : (((__pin) == 26) ? 4 : (((__pin) == 27) ? 5 : 6 )))))))))))))))))))
|
||||
#elif defined(ARDUINO_AVR_UNO) || defined(ARDUINO_AVR_DUEMILANOVE) || defined(__AVR_ATmega328__) || defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328PB__)
|
||||
#if defined(ARDUINO_AVR_UNO) || defined(ARDUINO_AVR_DUEMILANOVE) || defined(__AVR_ATmega328__) || defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328PB__) || defined (__AVR_ATmega168__)
|
||||
#if defined(__AVR_ATmega328PB__)
|
||||
#define __digitalPinToPortReg(__pin) (((__pin) <= 7) ? &PORTD : (((__pin) >= 8 && (__pin) <= 13) ? &PORTB : (((__pin) >= 14 && (__pin) <= 19) ? &PORTC : &PORTE)))
|
||||
#define __digitalPinToDDRReg(__pin) (((__pin) <= 7) ? &DDRD : (((__pin) >= 8 && (__pin) <= 13) ? &DDRB : (((__pin) >= 14 && (__pin) <= 19) ? &DDRC : &DDRE)))
|
||||
@@ -78,21 +18,14 @@
|
||||
#define __digitalPinToPINReg(__pin) (((__pin) <= 7) ? &PIND : (((__pin) >= 8 && (__pin) <= 13) ? &PINB : &PINC))
|
||||
#define __digitalPinToBit(__pin) (((__pin) <= 7) ? (__pin) : (((__pin) >= 8 && (__pin) <= 13) ? (__pin) - 8 : (__pin) - 14))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(ARDUINO_ARCH_AVR)
|
||||
#if !defined(__atomicWrite)
|
||||
#define __atomicWrite(A,P,V) do { if ((A) < 0x40) {bitWrite((A), (P), (V) );} else {uint8_t register saveSreg = SREG;cli();bitWrite((A), (P), (V));SREG = saveSreg;}} while(0)
|
||||
#endif
|
||||
#if !defined(digitalWriteFast)
|
||||
#define digitalWriteFast(__pin, __value) do { if (__builtin_constant_p(__pin) && __builtin_constant_p(__value)) { bitWrite(*__digitalPinToPortReg(__pin), (uint8_t)__digitalPinToBit(__pin), (__value)); } else { digitalWrite((__pin), (__value)); } } while (0)
|
||||
#endif
|
||||
#if !defined(pinModeFast)
|
||||
#define pinModeFast(__pin, __mode) do { if (__builtin_constant_p(__pin) && __builtin_constant_p(__mode) && (__mode!=INPUT_PULLUP)) { bitWrite(*__digitalPinToDDRReg(__pin), (uint8_t)__digitalPinToBit(__pin), (__mode)); } else { pinMode((__pin), (__mode)); } } while (0)
|
||||
#endif
|
||||
#if !defined(digitalReadFast)
|
||||
#define digitalReadFast(__pin) ( (bool) (__builtin_constant_p(__pin) ) ? (( bitRead(*__digitalPinToPINReg(__pin), (uint8_t)__digitalPinToBit(__pin))) ) : digitalRead((__pin)) )
|
||||
#endif
|
||||
#else
|
||||
// for all other archs use built-in pin access functions
|
||||
#define digitalWriteFast(__pin, __value) digitalWrite(__pin, __value)
|
||||
#define pinModeFast(__pin, __value) pinMode(__pin, __value)
|
||||
#define digitalReadFast(__pin) digitalRead(__pin)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -5,9 +5,9 @@
|
||||
* 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 Marcelo Aquino <marceloaqno@gmail.org>
|
||||
* Copyright (C) 2016 Marcelo Aquino
|
||||
* Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors
|
||||
* 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
|
||||
@@ -31,11 +31,6 @@ SPIClass SPI = SPIClass();
|
||||
|
||||
uint8_t SPIClass::initialized = 0;
|
||||
|
||||
uint8_t SPIClass::is_initialized()
|
||||
{
|
||||
return initialized;
|
||||
}
|
||||
|
||||
void SPIClass::begin()
|
||||
{
|
||||
if (!initialized) {
|
||||
@@ -5,9 +5,9 @@
|
||||
* 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 Marcelo Aquino <marceloaqno@gmail.org>
|
||||
* Copyright (C) 2016 Marcelo Aquino
|
||||
* Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors
|
||||
* 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
|
||||
@@ -24,17 +24,30 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include "bcm2835.h"
|
||||
#include "RPi.h"
|
||||
|
||||
#define SPI_HAS_TRANSACTION
|
||||
|
||||
#define SPI_CLOCK_BASE 256000000
|
||||
|
||||
// SPI Clock divider
|
||||
#define SPI_CLOCK_DIV2 2
|
||||
#define SPI_CLOCK_DIV4 4
|
||||
#define SPI_CLOCK_DIV8 8
|
||||
#define SPI_CLOCK_DIV16 16
|
||||
#define SPI_CLOCK_DIV32 32
|
||||
#define SPI_CLOCK_DIV64 64
|
||||
#define SPI_CLOCK_DIV128 128
|
||||
#define SPI_CLOCK_DIV1 BCM2835_SPI_CLOCK_DIVIDER_1
|
||||
#define SPI_CLOCK_DIV2 BCM2835_SPI_CLOCK_DIVIDER_2
|
||||
#define SPI_CLOCK_DIV4 BCM2835_SPI_CLOCK_DIVIDER_4
|
||||
#define SPI_CLOCK_DIV8 BCM2835_SPI_CLOCK_DIVIDER_8
|
||||
#define SPI_CLOCK_DIV16 BCM2835_SPI_CLOCK_DIVIDER_16
|
||||
#define SPI_CLOCK_DIV32 BCM2835_SPI_CLOCK_DIVIDER_32
|
||||
#define SPI_CLOCK_DIV64 BCM2835_SPI_CLOCK_DIVIDER_64
|
||||
#define SPI_CLOCK_DIV128 BCM2835_SPI_CLOCK_DIVIDER_128
|
||||
#define SPI_CLOCK_DIV256 BCM2835_SPI_CLOCK_DIVIDER_256
|
||||
#define SPI_CLOCK_DIV512 BCM2835_SPI_CLOCK_DIVIDER_512
|
||||
#define SPI_CLOCK_DIV1024 BCM2835_SPI_CLOCK_DIVIDER_1024
|
||||
#define SPI_CLOCK_DIV2048 BCM2835_SPI_CLOCK_DIVIDER_2048
|
||||
#define SPI_CLOCK_DIV4096 BCM2835_SPI_CLOCK_DIVIDER_4096
|
||||
#define SPI_CLOCK_DIV8192 BCM2835_SPI_CLOCK_DIVIDER_8192
|
||||
#define SPI_CLOCK_DIV16384 BCM2835_SPI_CLOCK_DIVIDER_16384
|
||||
#define SPI_CLOCK_DIV32768 BCM2835_SPI_CLOCK_DIVIDER_32768
|
||||
#define SPI_CLOCK_DIV65536 BCM2835_SPI_CLOCK_DIVIDER_65536
|
||||
|
||||
// SPI Data mode
|
||||
#define SPI_MODE0 BCM2835_SPI_MODE0
|
||||
@@ -42,6 +55,14 @@
|
||||
#define SPI_MODE2 BCM2835_SPI_MODE2
|
||||
#define SPI_MODE3 BCM2835_SPI_MODE3
|
||||
|
||||
#define LSBFIRST BCM2835_SPI_BIT_ORDER_LSBFIRST
|
||||
#define MSBFIRST BCM2835_SPI_BIT_ORDER_MSBFIRST
|
||||
|
||||
const uint8_t SS = 24;
|
||||
const uint8_t MOSI = 19;
|
||||
const uint8_t MISO = 21;
|
||||
const uint8_t SCK = 23;
|
||||
|
||||
/**
|
||||
* SPISettings class
|
||||
*/
|
||||
@@ -56,7 +77,7 @@ public:
|
||||
*/
|
||||
SPISettings()
|
||||
{
|
||||
init(BCM2835_SPI_CLOCK_DIVIDER_32, BCM2835_SPI_BIT_ORDER_MSBFIRST, BCM2835_SPI_MODE0);
|
||||
init(SPI_CLOCK_DIV32, MSBFIRST, SPI_MODE0);
|
||||
}
|
||||
/**
|
||||
* @brief SPISettings constructor.
|
||||
@@ -69,28 +90,43 @@ public:
|
||||
{
|
||||
uint16_t divider;
|
||||
|
||||
switch (clock) {
|
||||
case 500000:
|
||||
divider = BCM2835_SPI_CLOCK_DIVIDER_512;
|
||||
break;
|
||||
case 1000000:
|
||||
divider = BCM2835_SPI_CLOCK_DIVIDER_256;
|
||||
break;
|
||||
case 2000000:
|
||||
divider = BCM2835_SPI_CLOCK_DIVIDER_128;
|
||||
break;
|
||||
case 4000000:
|
||||
divider = BCM2835_SPI_CLOCK_DIVIDER_64;
|
||||
break;
|
||||
case 8000000:
|
||||
divider = BCM2835_SPI_CLOCK_DIVIDER_32;
|
||||
break;
|
||||
case 16000000:
|
||||
divider = BCM2835_SPI_CLOCK_DIVIDER_16;
|
||||
break;
|
||||
default:
|
||||
// 8Mhz
|
||||
divider = BCM2835_SPI_CLOCK_DIVIDER_32;
|
||||
if (clock >= SPI_CLOCK_BASE) {
|
||||
divider = SPI_CLOCK_DIV1;
|
||||
} else if (clock >= SPI_CLOCK_BASE / 2) {
|
||||
divider = SPI_CLOCK_DIV2;
|
||||
} else if (clock >= SPI_CLOCK_BASE / 4) {
|
||||
divider = SPI_CLOCK_DIV4;
|
||||
} else if (clock >= SPI_CLOCK_BASE / 8) {
|
||||
divider = SPI_CLOCK_DIV8;
|
||||
} else if (clock >= SPI_CLOCK_BASE / 16) {
|
||||
divider = SPI_CLOCK_DIV16;
|
||||
} else if (clock >= SPI_CLOCK_BASE / 32) {
|
||||
divider = SPI_CLOCK_DIV32;
|
||||
} else if (clock >= SPI_CLOCK_BASE / 64) {
|
||||
divider = SPI_CLOCK_DIV64;
|
||||
} else if (clock >= SPI_CLOCK_BASE / 128) {
|
||||
divider = SPI_CLOCK_DIV128;
|
||||
} else if (clock >= SPI_CLOCK_BASE / 256) {
|
||||
divider = SPI_CLOCK_DIV256;
|
||||
} else if (clock >= SPI_CLOCK_BASE / 512) {
|
||||
divider = SPI_CLOCK_DIV512;
|
||||
} else if (clock >= SPI_CLOCK_BASE / 1024) {
|
||||
divider = SPI_CLOCK_DIV1024;
|
||||
} else if (clock >= SPI_CLOCK_BASE / 2048) {
|
||||
divider = SPI_CLOCK_DIV2048;
|
||||
} else if (clock >= SPI_CLOCK_BASE / 4096) {
|
||||
divider = SPI_CLOCK_DIV4096;
|
||||
} else if (clock >= SPI_CLOCK_BASE / 8192) {
|
||||
divider = SPI_CLOCK_DIV8192;
|
||||
} else if (clock >= SPI_CLOCK_BASE / 16384) {
|
||||
divider = SPI_CLOCK_DIV16384;
|
||||
} else if (clock >= SPI_CLOCK_BASE / 32768) {
|
||||
divider = SPI_CLOCK_DIV32768;
|
||||
} else if (clock >= SPI_CLOCK_BASE / 65536) {
|
||||
divider = SPI_CLOCK_DIV65536;
|
||||
} else {
|
||||
// Default to 8Mhz
|
||||
divider = SPI_CLOCK_DIV32;
|
||||
}
|
||||
|
||||
init(divider, bitOrder, dataMode);
|
||||
@@ -124,16 +160,7 @@ private:
|
||||
class SPIClass
|
||||
{
|
||||
|
||||
private:
|
||||
static uint8_t initialized; //!< @brief SPI initialized flag.
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Checks if SPI was initialized.
|
||||
*
|
||||
* @return 0 if wasn't initialized, else 1 or more.
|
||||
*/
|
||||
static uint8_t is_initialized();
|
||||
/**
|
||||
* @brief Send and receive a byte.
|
||||
*
|
||||
@@ -210,6 +237,9 @@ public:
|
||||
* @param interruptNumber ignored parameter.
|
||||
*/
|
||||
static void notUsingInterrupt(uint8_t interruptNumber);
|
||||
|
||||
private:
|
||||
static uint8_t initialized; //!< @brief SPI initialized flag.
|
||||
};
|
||||
|
||||
uint8_t SPIClass::transfer(uint8_t data)
|
||||
@@ -28,6 +28,7 @@
|
||||
#if !DOXYGEN
|
||||
#include <stdint.h>
|
||||
#include "Stream.h"
|
||||
#include "RPi.h"
|
||||
|
||||
#define BUFFER_LENGTH 32
|
||||
|
||||
+39
-4
@@ -1,3 +1,22 @@
|
||||
/*
|
||||
* 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 Arduino_h
|
||||
#define Arduino_h
|
||||
|
||||
@@ -14,10 +33,21 @@
|
||||
#include "stdlib_noniso.h"
|
||||
|
||||
#ifdef LINUX_ARCH_RASPBERRYPI
|
||||
#include "rpi_util.h"
|
||||
using namespace rpi_util;
|
||||
#include "RPi.h"
|
||||
#define pinMode(pin, direction) rpi.pinMode(pin, direction)
|
||||
#define digitalWrite(pin, value) rpi.digitalWrite(pin, value)
|
||||
#define digitalRead(pin) rpi.digitalRead(pin)
|
||||
#define digitalPinToInterrupt(pin) rpi.digitalPinToInterrupt(pin)
|
||||
#else
|
||||
#include "GPIO.h"
|
||||
#define pinMode(pin, direction) gpio.pinMode(pin, direction)
|
||||
#define digitalWrite(pin, value) gpio.digitalWrite(pin, value)
|
||||
#define digitalRead(pin) gpio.digitalRead(pin)
|
||||
#define digitalPinToInterrupt(pin) gpio.digitalPinToInterrupt(pin)
|
||||
#endif
|
||||
|
||||
#include "interrupt.h"
|
||||
|
||||
#undef PSTR
|
||||
#define PSTR(x) (x)
|
||||
#undef F
|
||||
@@ -57,7 +87,11 @@ using namespace rpi_util;
|
||||
#define random(...) GET_MACRO(_0, ##__VA_ARGS__, randMinMax, randMax, rand)(__VA_ARGS__)
|
||||
|
||||
#ifndef delay
|
||||
#define delay _delay_ms
|
||||
#define delay _delay_milliseconds
|
||||
#endif
|
||||
|
||||
#ifndef delayMicroseconds
|
||||
#define delayMicroseconds _delay_microseconds
|
||||
#endif
|
||||
|
||||
using std::string;
|
||||
@@ -73,7 +107,8 @@ typedef char __FlashStringHelper;
|
||||
void yield(void);
|
||||
unsigned long millis(void);
|
||||
unsigned long micros(void);
|
||||
void _delay_ms(unsigned int millis);
|
||||
void _delay_milliseconds(unsigned int millis);
|
||||
void _delay_microseconds(unsigned int micro);
|
||||
void randomSeed(unsigned long seed);
|
||||
long randMax(long howbig);
|
||||
long randMinMax(long howsmall, long howbig);
|
||||
|
||||
@@ -5,9 +5,9 @@
|
||||
* 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 Marcelo Aquino <marceloaqno@gmail.org>
|
||||
* Copyright (C) 2016 Marcelo Aquino
|
||||
* Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors
|
||||
* 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
|
||||
@@ -103,7 +103,6 @@ size_t EthernetClient::write(uint8_t b)
|
||||
|
||||
size_t EthernetClient::write(const uint8_t *buf, size_t size)
|
||||
{
|
||||
int rc = 0;
|
||||
int bytes = 0;
|
||||
|
||||
if (_sock == -1) {
|
||||
@@ -111,7 +110,7 @@ size_t EthernetClient::write(const uint8_t *buf, size_t size)
|
||||
}
|
||||
|
||||
while (size > 0) {
|
||||
rc = send(_sock, buf + bytes, size, MSG_NOSIGNAL | MSG_DONTWAIT);
|
||||
int rc = send(_sock, buf + bytes, size, MSG_NOSIGNAL | MSG_DONTWAIT);
|
||||
if (rc == -1) {
|
||||
logError("send: %s\n", strerror(errno));
|
||||
close(_sock);
|
||||
|
||||
@@ -5,9 +5,9 @@
|
||||
* 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 Marcelo Aquino <marceloaqno@gmail.org>
|
||||
* Copyright (C) 2016 Marcelo Aquino
|
||||
* Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors
|
||||
* 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
|
||||
@@ -43,9 +43,6 @@
|
||||
class EthernetClient : public Client
|
||||
{
|
||||
|
||||
private:
|
||||
int _sock; //!< @brief Network socket.
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief EthernetClient constructor.
|
||||
@@ -56,7 +53,7 @@ public:
|
||||
*
|
||||
* @param sock Network socket.
|
||||
*/
|
||||
EthernetClient(int sock);
|
||||
explicit EthernetClient(int sock);
|
||||
/**
|
||||
* @brief Initiate a connection with host:port.
|
||||
*
|
||||
@@ -196,6 +193,9 @@ public:
|
||||
};
|
||||
|
||||
friend class EthernetServer;
|
||||
|
||||
private:
|
||||
int _sock; //!< @brief Network socket.
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -5,9 +5,9 @@
|
||||
* 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 Marcelo Aquino <marceloaqno@gmail.org>
|
||||
* Copyright (C) 2016 Marcelo Aquino
|
||||
* Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors
|
||||
* 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
|
||||
@@ -33,7 +33,7 @@
|
||||
#include "EthernetServer.h"
|
||||
|
||||
EthernetServer::EthernetServer(uint16_t port, uint16_t max_clients) : port(port),
|
||||
max_clients(max_clients)
|
||||
max_clients(max_clients), sockfd(-1)
|
||||
{
|
||||
clients.reserve(max_clients);
|
||||
}
|
||||
|
||||
@@ -5,9 +5,9 @@
|
||||
* 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 Marcelo Aquino <marceloaqno@gmail.org>
|
||||
* Copyright (C) 2016 Marcelo Aquino
|
||||
* Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors
|
||||
* 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
|
||||
@@ -42,19 +42,6 @@ class EthernetClient;
|
||||
class EthernetServer : public Server
|
||||
{
|
||||
|
||||
private:
|
||||
uint16_t port; //!< @brief Port number for the network socket.
|
||||
std::list<int> new_clients; //!< Socket list of new clients.
|
||||
std::vector<int> clients; //!< @brief Socket list of clients.
|
||||
uint16_t max_clients; //!< @brief The maximum number of allowed clients.
|
||||
int sockfd; //!< @brief Network socket used to accept connections.
|
||||
|
||||
/**
|
||||
* @brief Accept new clients if the total of connected clients is below max_clients.
|
||||
*
|
||||
*/
|
||||
void _accept();
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief EthernetServer constructor.
|
||||
@@ -116,6 +103,19 @@ public:
|
||||
* @return 0 if FAILURE else the number of characters sent.
|
||||
*/
|
||||
size_t write(const char *buffer, size_t size);
|
||||
|
||||
private:
|
||||
uint16_t port; //!< @brief Port number for the network socket.
|
||||
std::list<int> new_clients; //!< Socket list of new clients.
|
||||
std::vector<int> clients; //!< @brief Socket list of clients.
|
||||
uint16_t max_clients; //!< @brief The maximum number of allowed clients.
|
||||
int sockfd; //!< @brief Network socket used to accept connections.
|
||||
|
||||
/**
|
||||
* @brief Accept new clients if the total of connected clients is below max_clients.
|
||||
*
|
||||
*/
|
||||
void _accept();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,211 @@
|
||||
/*
|
||||
* 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 "GPIO.h"
|
||||
#include <dirent.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include "log.h"
|
||||
|
||||
// Declare a single default instance
|
||||
GPIO gpio = GPIO();
|
||||
|
||||
GPIO::GPIO()
|
||||
{
|
||||
FILE *f;
|
||||
DIR* dp;
|
||||
char file[64];
|
||||
|
||||
dp = opendir("/sys/class/gpio");
|
||||
if (dp == NULL) {
|
||||
logError("Could not open /sys/class/gpio directory");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
lastPinNum = 0;
|
||||
|
||||
while (true) {
|
||||
dirent *de = readdir(dp);
|
||||
if (de == NULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (strncmp("gpiochip", de->d_name, 8) == 0) {
|
||||
sprintf(file, "/sys/class/gpio/%s/base", de->d_name);
|
||||
f = fopen(file, "r");
|
||||
int base;
|
||||
if (fscanf(f, "%d", &base) == EOF) {
|
||||
logError("Failed to open %s\n", file);
|
||||
base = 0;
|
||||
}
|
||||
fclose(f);
|
||||
|
||||
sprintf(file, "/sys/class/gpio/%s/ngpio", de->d_name);
|
||||
f = fopen(file, "r");
|
||||
int ngpio;
|
||||
if (fscanf(f, "%d", &ngpio) == EOF) {
|
||||
logError("Failed to open %s\n", file);
|
||||
ngpio = 0;
|
||||
}
|
||||
fclose(f);
|
||||
|
||||
int max = ngpio + base - 1;
|
||||
if (lastPinNum < max) {
|
||||
lastPinNum = max;
|
||||
}
|
||||
}
|
||||
}
|
||||
closedir(dp);
|
||||
|
||||
exportedPins = new uint8_t[lastPinNum + 1];
|
||||
|
||||
for (int i = 0; i < lastPinNum + 1; ++i) {
|
||||
exportedPins[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
GPIO::GPIO(const GPIO& other)
|
||||
{
|
||||
lastPinNum = other.lastPinNum;
|
||||
|
||||
exportedPins = new uint8_t[lastPinNum + 1];
|
||||
for (int i = 0; i < lastPinNum + 1; ++i) {
|
||||
exportedPins[i] = other.exportedPins[i];
|
||||
}
|
||||
}
|
||||
|
||||
GPIO::~GPIO()
|
||||
{
|
||||
FILE *f;
|
||||
|
||||
for (int i = 0; i < lastPinNum + 1; ++i) {
|
||||
if (exportedPins[i]) {
|
||||
f = fopen("/sys/class/gpio/unexport", "w");
|
||||
fprintf(f, "%d\n", i);
|
||||
fclose(f);
|
||||
}
|
||||
}
|
||||
|
||||
delete [] exportedPins;
|
||||
}
|
||||
|
||||
void GPIO::pinMode(uint8_t pin, uint8_t mode)
|
||||
{
|
||||
FILE *f;
|
||||
|
||||
if (pin > lastPinNum) {
|
||||
return;
|
||||
}
|
||||
|
||||
f = fopen("/sys/class/gpio/export", "w");
|
||||
fprintf(f, "%d\n", pin);
|
||||
fclose(f);
|
||||
|
||||
int counter = 0;
|
||||
char file[128];
|
||||
sprintf(file, "/sys/class/gpio/gpio%d/direction", pin);
|
||||
|
||||
while ((f = fopen(file,"w")) == NULL) {
|
||||
// Wait 10 seconds for the file to be accessible if not open on first attempt
|
||||
sleep(1);
|
||||
counter++;
|
||||
if (counter > 10) {
|
||||
logError("Could not open /sys/class/gpio/gpio%u/direction", pin);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
if (mode == INPUT) {
|
||||
fprintf(f, "in\n");
|
||||
} else {
|
||||
fprintf(f, "out\n");
|
||||
}
|
||||
|
||||
exportedPins[pin] = 1;
|
||||
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
void GPIO::digitalWrite(uint8_t pin, uint8_t value)
|
||||
{
|
||||
FILE *f;
|
||||
char file[128];
|
||||
|
||||
if (pin > lastPinNum) {
|
||||
return;
|
||||
}
|
||||
if (0 == exportedPins[pin]) {
|
||||
pinMode(pin, OUTPUT);
|
||||
}
|
||||
|
||||
sprintf(file, "/sys/class/gpio/gpio%d/value", pin);
|
||||
f = fopen(file, "w");
|
||||
|
||||
if (value == 0) {
|
||||
fprintf(f, "0\n");
|
||||
} else {
|
||||
fprintf(f, "1\n");
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
uint8_t GPIO::digitalRead(uint8_t pin)
|
||||
{
|
||||
FILE *f;
|
||||
char file[128];
|
||||
|
||||
if (pin > lastPinNum) {
|
||||
return 0;
|
||||
}
|
||||
if (0 == exportedPins[pin]) {
|
||||
pinMode(pin, INPUT);
|
||||
}
|
||||
|
||||
sprintf(file, "/sys/class/gpio/gpio%d/value", pin);
|
||||
f = fopen(file, "r");
|
||||
|
||||
int i;
|
||||
if (fscanf(f, "%d", &i) == EOF) {
|
||||
logError("digitalRead: failed to read pin %u\n", pin);
|
||||
i = 0;
|
||||
}
|
||||
fclose(f);
|
||||
return i;
|
||||
}
|
||||
|
||||
uint8_t GPIO::digitalPinToInterrupt(uint8_t pin)
|
||||
{
|
||||
return pin;
|
||||
}
|
||||
|
||||
GPIO& GPIO::operator=(const GPIO& other)
|
||||
{
|
||||
if (this != &other) {
|
||||
lastPinNum = other.lastPinNum;
|
||||
|
||||
exportedPins = new uint8_t[lastPinNum + 1];
|
||||
for (int i = 0; i < lastPinNum + 1; ++i) {
|
||||
exportedPins[i] = other.exportedPins[i];
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* 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 GPIO_h
|
||||
#define GPIO_h
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define INPUT 0
|
||||
#define OUTPUT 1
|
||||
|
||||
#define LOW 0
|
||||
#define HIGH 1
|
||||
|
||||
/**
|
||||
* @brief GPIO class
|
||||
*/
|
||||
class GPIO
|
||||
{
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief GPIO constructor.
|
||||
*/
|
||||
GPIO();
|
||||
/**
|
||||
* @brief GPIO copy constructor.
|
||||
*/
|
||||
GPIO(const GPIO& other);
|
||||
/**
|
||||
* @brief GPIO destructor.
|
||||
*/
|
||||
~GPIO();
|
||||
/**
|
||||
* @brief Configures the specified pin to behave either as an input or an output.
|
||||
*
|
||||
* @param pin The number of the pin.
|
||||
* @param mode INPUT or OUTPUT.
|
||||
*/
|
||||
void pinMode(uint8_t pin, uint8_t mode);
|
||||
/**
|
||||
* @brief Write a high or a low value for the given pin.
|
||||
*
|
||||
* @param pin number.
|
||||
* @param value HIGH or LOW.
|
||||
*/
|
||||
void digitalWrite(uint8_t pin, uint8_t value);
|
||||
/**
|
||||
* @brief Reads the value from a specified pin.
|
||||
*
|
||||
* @param pin The number of the pin.
|
||||
* @return HIGH or LOW.
|
||||
*/
|
||||
uint8_t digitalRead(uint8_t pin);
|
||||
/**
|
||||
* @brief Arduino compatibility function, returns the same given pin.
|
||||
*
|
||||
* @param pin The number of the pin.
|
||||
* @return The same parameter pin number.
|
||||
*/
|
||||
uint8_t digitalPinToInterrupt(uint8_t pin);
|
||||
/**
|
||||
* @brief Overloaded assign operator.
|
||||
*
|
||||
*/
|
||||
GPIO& operator=(const GPIO& other);
|
||||
|
||||
private:
|
||||
int lastPinNum; //!< @brief Highest pin number supported.
|
||||
uint8_t *exportedPins; //!< @brief Array with information of which pins were exported.
|
||||
};
|
||||
|
||||
extern GPIO gpio;
|
||||
|
||||
#endif
|
||||
@@ -70,13 +70,13 @@ public:
|
||||
*
|
||||
* @param address to be set from a 32 bits integer.
|
||||
*/
|
||||
IPAddress(uint32_t address);
|
||||
explicit IPAddress(uint32_t address);
|
||||
/**
|
||||
* @brief IPAddress constructor.
|
||||
*
|
||||
* @param address to be set from a byte array.
|
||||
*/
|
||||
IPAddress(const uint8_t *address);
|
||||
explicit IPAddress(const uint8_t *address);
|
||||
/**
|
||||
* @brief Set the IP from a array of characters.
|
||||
*
|
||||
|
||||
@@ -210,9 +210,9 @@ size_t Print::printNumber(unsigned long n, uint8_t base)
|
||||
}
|
||||
|
||||
do {
|
||||
unsigned long m = n;
|
||||
char c = n % base;
|
||||
n /= base;
|
||||
char c = m - base * n;
|
||||
|
||||
*--str = c < 10 ? c + '0' : c + 'A' - 10;
|
||||
} while(n);
|
||||
|
||||
|
||||
@@ -5,9 +5,9 @@
|
||||
* 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 Marcelo Aquino <marceloaqno@gmail.org>
|
||||
* Copyright (C) 2016 Marcelo Aquino
|
||||
* Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors
|
||||
* 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
|
||||
@@ -179,25 +179,23 @@ bool SerialPort::open(int bauds)
|
||||
|
||||
bool SerialPort::setGroupPerm(const char *groupName)
|
||||
{
|
||||
struct group* devGrp;
|
||||
const mode_t ttyPermissions = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;
|
||||
const char *dev;
|
||||
int ret;
|
||||
|
||||
if (sd != -1 && groupName != NULL) {
|
||||
devGrp = getgrnam(groupName);
|
||||
struct group *devGrp = getgrnam(groupName);
|
||||
if (devGrp == NULL) {
|
||||
logError("getgrnam: %s failed. (%d) %s\n", groupName, errno, strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
const char *dev;
|
||||
if (isPty) {
|
||||
dev = ptsname(sd);
|
||||
} else {
|
||||
dev = serialPort.c_str();
|
||||
}
|
||||
|
||||
ret = chown(dev, -1, devGrp->gr_gid);
|
||||
int ret = chown(dev, -1, devGrp->gr_gid);
|
||||
if (ret == -1) {
|
||||
logError("Could not change PTY owner! (%d) %s\n", errno, strerror(errno));
|
||||
return false;
|
||||
|
||||
@@ -5,9 +5,9 @@
|
||||
* 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 Marcelo Aquino <marceloaqno@gmail.org>
|
||||
* Copyright (C) 2016 Marcelo Aquino
|
||||
* Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors
|
||||
* 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
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* 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 <stdio.h>
|
||||
#include "SerialSimulator.h"
|
||||
|
||||
void SerialSimulator::begin(int baud)
|
||||
{
|
||||
(void)baud;
|
||||
}
|
||||
|
||||
int SerialSimulator::available()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
int SerialSimulator::read()
|
||||
{
|
||||
return getchar();
|
||||
}
|
||||
|
||||
size_t SerialSimulator::write(uint8_t b)
|
||||
{
|
||||
return (size_t)::printf("%c", b);
|
||||
}
|
||||
|
||||
int SerialSimulator::peek()
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
void SerialSimulator::flush()
|
||||
{
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
void SerialSimulator::end()
|
||||
{
|
||||
flush();
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* 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 SerialSimulator_h
|
||||
#define SerialSimulator_h
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "Stream.h"
|
||||
|
||||
/**
|
||||
* @brief A class equivalent to Serial in Arduino but outputs to stdout
|
||||
*/
|
||||
class SerialSimulator : public Stream
|
||||
{
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief This function does nothing.
|
||||
*
|
||||
* @param baud Ignored parameter.
|
||||
*/
|
||||
void begin(int baud);
|
||||
/**
|
||||
* @brief This function does nothing.
|
||||
*
|
||||
* @return always returns 1.
|
||||
*/
|
||||
int available();
|
||||
/**
|
||||
* @brief Reads 1 key pressed from the keyboard.
|
||||
*
|
||||
* @return key character pressed cast to an int.
|
||||
*/
|
||||
int read();
|
||||
/**
|
||||
* @brief Writes a single byte to stdout.
|
||||
*
|
||||
* @param b byte to write.
|
||||
* @return -1 if error else, number of bytes written.
|
||||
*/
|
||||
size_t write(uint8_t b);
|
||||
/**
|
||||
* @brief Not supported.
|
||||
*
|
||||
* @return always returns -1.
|
||||
*/
|
||||
int peek();
|
||||
/**
|
||||
* @brief Flush stdout.
|
||||
*/
|
||||
void flush();
|
||||
/**
|
||||
* @brief Nothing to do, flush stdout.
|
||||
*/
|
||||
void end();
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,13 +1,13 @@
|
||||
/**
|
||||
/*
|
||||
* 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 Marcelo Aquino <marceloaqno@gmail.org>
|
||||
* Copyright (C) 2016 Marcelo Aquino
|
||||
* Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors
|
||||
* 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
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
/**
|
||||
/*
|
||||
* 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 Marcelo Aquino <marceloaqno@gmail.org>
|
||||
* Copyright (C) 2016 Marcelo Aquino
|
||||
* Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors
|
||||
* 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
|
||||
@@ -33,11 +33,6 @@
|
||||
class SoftEeprom
|
||||
{
|
||||
|
||||
private:
|
||||
size_t _length; //!< @brief Eeprom max size.
|
||||
char *_fileName; //!< @brief file where the eeprom values are stored.
|
||||
uint8_t *_values; //!< @brief copy of the eeprom values held in memory for a faster reading.
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief SoftEeprom constructor.
|
||||
@@ -86,6 +81,11 @@ public:
|
||||
*
|
||||
*/
|
||||
SoftEeprom& operator=(const SoftEeprom& other);
|
||||
|
||||
private:
|
||||
size_t _length; //!< @brief Eeprom max size.
|
||||
char *_fileName; //!< @brief file where the eeprom values are stored.
|
||||
uint8_t *_values; //!< @brief copy of the eeprom values held in memory for a faster reading.
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -57,6 +57,7 @@ public:
|
||||
Stream()
|
||||
{
|
||||
_timeout = 1000;
|
||||
_startMillis = 0;
|
||||
}
|
||||
|
||||
// parsing methods
|
||||
|
||||
@@ -1,3 +1,22 @@
|
||||
/*
|
||||
* 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 <time.h>
|
||||
#include <sys/time.h>
|
||||
#include <stdlib.h>
|
||||
@@ -34,7 +53,7 @@ unsigned long micros()
|
||||
return ((curTime.tv_sec - millis_at_start) * 1000000) + (curTime.tv_usec);
|
||||
}
|
||||
|
||||
void _delay_ms(unsigned int millis)
|
||||
void _delay_milliseconds(unsigned int millis)
|
||||
{
|
||||
struct timespec sleeper;
|
||||
|
||||
@@ -43,6 +62,15 @@ void _delay_ms(unsigned int millis)
|
||||
nanosleep(&sleeper, NULL);
|
||||
}
|
||||
|
||||
void _delay_microseconds(unsigned int micro)
|
||||
{
|
||||
struct timespec sleeper;
|
||||
|
||||
sleeper.tv_sec = (time_t)(micro / 1000000);
|
||||
sleeper.tv_nsec = (long)(micro % 1000000) * 1000;
|
||||
nanosleep(&sleeper, NULL);
|
||||
}
|
||||
|
||||
void randomSeed(unsigned long seed)
|
||||
{
|
||||
if (seed != 0) {
|
||||
|
||||
@@ -5,9 +5,9 @@
|
||||
* 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 Marcelo Aquino <marceloaqno@gmail.org>
|
||||
* Copyright (C) 2016 Marcelo Aquino
|
||||
* Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors
|
||||
* 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
|
||||
@@ -19,7 +19,7 @@
|
||||
* Based on wiringPi Copyright (c) 2012 Gordon Henderson.
|
||||
*/
|
||||
|
||||
#include "rpi_util.h"
|
||||
#include "interrupt.h"
|
||||
#include <pthread.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/ioctl.h>
|
||||
@@ -32,22 +32,14 @@
|
||||
#include <fcntl.h>
|
||||
#include <stropts.h>
|
||||
#include <errno.h>
|
||||
#include "SPI.h"
|
||||
#include <sched.h>
|
||||
#include "log.h"
|
||||
#include "cpuinfo.h"
|
||||
|
||||
extern "C" {
|
||||
int piHiPri(const int pri);
|
||||
}
|
||||
|
||||
struct ThreadArgs {
|
||||
void (*func)();
|
||||
int gpioPin;
|
||||
};
|
||||
|
||||
static const int *pin_to_gpio = 0;
|
||||
static rpi_info rpiinfo;
|
||||
|
||||
volatile bool interruptsEnabled = true;
|
||||
static pthread_mutex_t intMutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
@@ -62,36 +54,23 @@ static int sysFds[64] = {
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
};
|
||||
|
||||
int get_gpio_number(uint8_t physPin, uint8_t *gpio)
|
||||
/*
|
||||
* Part of wiringPi: Simple way to get your program running at high priority
|
||||
* with realtime schedulling.
|
||||
*/
|
||||
int piHiPri(const int pri)
|
||||
{
|
||||
if (pin_to_gpio == 0) {
|
||||
// detect board revision and set up accordingly
|
||||
if (get_rpi_info(&rpiinfo)) {
|
||||
logError("This module can only be run on a Raspberry Pi!\n");
|
||||
exit(1);
|
||||
}
|
||||
struct sched_param sched ;
|
||||
|
||||
if (rpiinfo.p1_revision == 1) {
|
||||
pin_to_gpio = &pin_to_gpio_rev1[0];
|
||||
} else if (rpiinfo.p1_revision == 2) {
|
||||
pin_to_gpio = &pin_to_gpio_rev2[0];
|
||||
} else { // assume model B+ or A+ or 2B
|
||||
pin_to_gpio = &pin_to_gpio_rev3[0];
|
||||
}
|
||||
}
|
||||
memset (&sched, 0, sizeof(sched)) ;
|
||||
|
||||
if ((rpiinfo.p1_revision != 3 && physPin > 26)
|
||||
|| (rpiinfo.p1_revision == 3 && physPin > 40)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (*(pin_to_gpio+physPin) == -1) {
|
||||
return -1;
|
||||
if (pri > sched_get_priority_max (SCHED_RR)) {
|
||||
sched.sched_priority = sched_get_priority_max (SCHED_RR) ;
|
||||
} else {
|
||||
*gpio = *(pin_to_gpio+physPin);
|
||||
sched.sched_priority = pri ;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return sched_setscheduler (0, SCHED_RR, &sched) ;
|
||||
}
|
||||
|
||||
void *interruptHandler(void *args)
|
||||
@@ -125,8 +104,14 @@ void *interruptHandler(void *args)
|
||||
// Do a dummy read to clear the interrupt
|
||||
// A one character read appars to be enough.
|
||||
// Followed by a seek to reset it.
|
||||
(void)read (fd, &c, 1) ;
|
||||
lseek (fd, 0, SEEK_SET) ;
|
||||
if (read (fd, &c, 1) < 0) {
|
||||
logError("Interrupt handler error: %s\n", strerror(errno));
|
||||
break;
|
||||
}
|
||||
if (lseek (fd, 0, SEEK_SET) < 0) {
|
||||
logError("Interrupt handler error: %s\n", strerror(errno));
|
||||
break;
|
||||
}
|
||||
// Call user function.
|
||||
pthread_mutex_lock(&intMutex);
|
||||
if (interruptsEnabled) {
|
||||
@@ -142,73 +127,12 @@ void *interruptHandler(void *args)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void rpi_util::pinMode(uint8_t physPin, uint8_t mode)
|
||||
{
|
||||
uint8_t gpioPin;
|
||||
|
||||
if (get_gpio_number(physPin, &gpioPin)) {
|
||||
logError("pinMode: invalid pin: %d\n", physPin);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if SPI is in use and target pin is related to SPI
|
||||
if (SPIClass::is_initialized() && gpioPin >= RPI_GPIO_P1_26 && gpioPin <= RPI_GPIO_P1_23) {
|
||||
return;
|
||||
} else {
|
||||
bcm2835_gpio_fsel(gpioPin, mode);
|
||||
}
|
||||
}
|
||||
|
||||
void rpi_util::digitalWrite(uint8_t physPin, uint8_t value)
|
||||
{
|
||||
uint8_t gpioPin;
|
||||
|
||||
if (get_gpio_number(physPin, &gpioPin)) {
|
||||
logError("digitalWrite: invalid pin: %d\n", physPin);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if SPI is in use and target pin is related to SPI
|
||||
if (SPIClass::is_initialized() && gpioPin >= RPI_GPIO_P1_26 && gpioPin <= RPI_GPIO_P1_23) {
|
||||
if (value == LOW && (gpioPin == RPI_GPIO_P1_24 || gpioPin == RPI_GPIO_P1_26)) {
|
||||
SPI.chipSelect(gpioPin);
|
||||
}
|
||||
} else {
|
||||
bcm2835_gpio_write(gpioPin, value);
|
||||
// Delay to allow any change in state to be reflected in the LEVn, register bit.
|
||||
delayMicroseconds(1);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t rpi_util::digitalRead(uint8_t physPin)
|
||||
{
|
||||
uint8_t gpioPin;
|
||||
|
||||
if (get_gpio_number(physPin, &gpioPin)) {
|
||||
logError("digitalRead: invalid pin: %d\n", physPin);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Check if SPI is in use and target pin is related to SPI
|
||||
if (SPIClass::is_initialized() && gpioPin >= RPI_GPIO_P1_26 && gpioPin <= RPI_GPIO_P1_23) {
|
||||
return 0;
|
||||
} else {
|
||||
return bcm2835_gpio_lev(gpioPin);
|
||||
}
|
||||
}
|
||||
|
||||
void rpi_util::attachInterrupt(uint8_t physPin, void (*func)(), uint8_t mode)
|
||||
void attachInterrupt(uint8_t gpioPin, void (*func)(), uint8_t mode)
|
||||
{
|
||||
FILE *fd;
|
||||
char fName[40];
|
||||
char c;
|
||||
int count, i;
|
||||
uint8_t gpioPin;
|
||||
|
||||
if (get_gpio_number(physPin, &gpioPin)) {
|
||||
logError("attachInterrupt: invalid pin: %d\n", physPin);
|
||||
return;
|
||||
}
|
||||
|
||||
if (threadIds[gpioPin] == NULL) {
|
||||
threadIds[gpioPin] = new pthread_t;
|
||||
@@ -216,24 +140,24 @@ void rpi_util::attachInterrupt(uint8_t physPin, void (*func)(), uint8_t mode)
|
||||
// Cancel the existing thread for that pin
|
||||
pthread_cancel(*threadIds[gpioPin]);
|
||||
// Wait a bit
|
||||
delay(1L);
|
||||
usleep(1000);
|
||||
}
|
||||
|
||||
// Export pin for interrupt
|
||||
if ((fd = fopen("/sys/class/gpio/export", "w")) == NULL) {
|
||||
logError("attachInterrupt: Unable to export pin %d for interrupt: %s\n", physPin, strerror(errno));
|
||||
logError("attachInterrupt: Unable to export pin %d for interrupt: %s\n", gpioPin, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
fprintf(fd, "%d\n", gpioPin);
|
||||
fclose(fd);
|
||||
|
||||
// Wait a bit the system to create /sys/class/gpio/gpio<GPIO number>
|
||||
delay(1L);
|
||||
usleep(1000);
|
||||
|
||||
snprintf(fName, sizeof(fName), "/sys/class/gpio/gpio%d/direction", gpioPin) ;
|
||||
if ((fd = fopen (fName, "w")) == NULL) {
|
||||
logError("attachInterrupt: Unable to open GPIO direction interface for pin %d: %s\n",
|
||||
physPin, strerror(errno));
|
||||
gpioPin, strerror(errno));
|
||||
exit(1) ;
|
||||
}
|
||||
fprintf(fd, "in\n") ;
|
||||
@@ -241,10 +165,11 @@ 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) {
|
||||
logError("attachInterrupt: Unable to open GPIO edge interface for pin %d: %s\n", physPin,
|
||||
logError("attachInterrupt: Unable to open GPIO edge interface for pin %d: %s\n", gpioPin,
|
||||
strerror(errno));
|
||||
exit(1) ;
|
||||
}
|
||||
|
||||
switch (mode) {
|
||||
case CHANGE:
|
||||
fprintf(fd, "both\n");
|
||||
@@ -268,7 +193,7 @@ void rpi_util::attachInterrupt(uint8_t physPin, void (*func)(), uint8_t mode)
|
||||
if (sysFds[gpioPin] == -1) {
|
||||
snprintf(fName, sizeof(fName), "/sys/class/gpio/gpio%d/value", gpioPin);
|
||||
if ((sysFds[gpioPin] = open(fName, O_RDWR)) < 0) {
|
||||
logError("Error reading pin %d: %s\n", physPin, strerror(errno));
|
||||
logError("Error reading pin %d: %s\n", gpioPin, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
@@ -289,15 +214,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 detachInterrupt(uint8_t gpioPin)
|
||||
{
|
||||
uint8_t gpioPin;
|
||||
|
||||
if (get_gpio_number(physPin, &gpioPin)) {
|
||||
logError("detachInterrupt: invalid pin: %d\n", physPin);
|
||||
return;
|
||||
}
|
||||
|
||||
// Cancel the thread
|
||||
if (threadIds[gpioPin] != NULL) {
|
||||
pthread_cancel(*threadIds[gpioPin]);
|
||||
@@ -320,20 +238,14 @@ void rpi_util::detachInterrupt(uint8_t physPin)
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
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 interrupts()
|
||||
{
|
||||
pthread_mutex_lock(&intMutex);
|
||||
interruptsEnabled = true;
|
||||
pthread_mutex_unlock(&intMutex);
|
||||
}
|
||||
|
||||
void rpi_util::noInterrupts()
|
||||
void noInterrupts()
|
||||
{
|
||||
pthread_mutex_lock(&intMutex);
|
||||
interruptsEnabled = false;
|
||||
@@ -1,4 +1,4 @@
|
||||
/**
|
||||
/*
|
||||
* 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
|
||||
@@ -6,8 +6,8 @@
|
||||
* network topology allowing messages to be routed to nodes.
|
||||
*
|
||||
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
|
||||
* Copyright (C) 2013-2016 Sensnology AB
|
||||
* Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors
|
||||
* 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
|
||||
@@ -15,41 +15,31 @@
|
||||
* 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.
|
||||
*
|
||||
* Based on wiringPi Copyright (c) 2012 Gordon Henderson.
|
||||
*/
|
||||
|
||||
#ifndef MyHwRPi_h
|
||||
#define MyHwRPi_h
|
||||
#ifndef interrupt_h
|
||||
#define interrupt_h
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include "MyHwLinuxGeneric.h"
|
||||
#include "log.h"
|
||||
#include "bcm2835.h"
|
||||
|
||||
class Bcm2835Init
|
||||
{
|
||||
public:
|
||||
Bcm2835Init()
|
||||
{
|
||||
if (!bcm2835_init()) {
|
||||
logError("Failed to initialized bcm2835.\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
~Bcm2835Init()
|
||||
{
|
||||
bcm2835_close();
|
||||
}
|
||||
};
|
||||
Bcm2835Init bcm2835Init;
|
||||
#define CHANGE 1
|
||||
#define FALLING 2
|
||||
#define RISING 3
|
||||
#define NONE 4
|
||||
|
||||
#undef hwDigitalWrite
|
||||
inline void hwDigitalWrite(uint8_t, uint8_t);
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#undef hwDigitalRead
|
||||
inline int hwDigitalRead(uint8_t);
|
||||
void attachInterrupt(uint8_t gpioPin, void(*func)(), uint8_t mode);
|
||||
void detachInterrupt(uint8_t gpioPin);
|
||||
void interrupts();
|
||||
void noInterrupts();
|
||||
|
||||
#undef hwPinMode
|
||||
inline void hwPinMode(uint8_t, uint8_t);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1,3 +1,22 @@
|
||||
/*
|
||||
* 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 "log.h"
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
@@ -1,3 +1,22 @@
|
||||
/*
|
||||
* 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 LOG_H
|
||||
#define LOG_H
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ LOCAL uint8_t MY_RF24_NODE_ADDRESS = AUTO;
|
||||
LOCAL RF24_receiveCallbackType RF24_receiveCallback = NULL;
|
||||
#endif
|
||||
|
||||
#ifdef LINUX_ARCH_RASPBERRYPI
|
||||
#ifdef LINUX_SPI_BCM
|
||||
uint8_t spi_rxbuff[32+1] ; //SPI receive buffer (payload max 32 bytes)
|
||||
uint8_t spi_txbuff[32+1] ; //SPI transmit buffer (payload max 32 bytes + 1 byte for the command)
|
||||
#endif
|
||||
@@ -56,7 +56,7 @@ LOCAL uint8_t RF24_spiMultiByteTransfer(const uint8_t cmd, uint8_t* buf, uint8_t
|
||||
RF24_csn(LOW);
|
||||
// timing
|
||||
delayMicroseconds(10);
|
||||
#ifdef LINUX_ARCH_RASPBERRYPI
|
||||
#ifdef LINUX_SPI_BCM
|
||||
uint8_t * prx = spi_rxbuff;
|
||||
uint8_t * ptx = spi_txbuff;
|
||||
uint8_t size = len + 1; // Add register value to transmit buffer
|
||||
|
||||
+1
-1
@@ -48,7 +48,7 @@ _SPI;
|
||||
|
||||
#define _BV(x) (1<<(x))
|
||||
|
||||
#if defined(__arm__)
|
||||
#if defined(__arm__) || defined(__linux__)
|
||||
#include <SPI.h>
|
||||
#else
|
||||
extern HardwareSPI SPI;
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
#include "RFM95.h"
|
||||
|
||||
#if defined(LINUX_ARCH_RASPBERRYPI)
|
||||
#if defined(LINUX_SPI_BCM)
|
||||
// SPI RX and TX buffers (max packet len + 1 byte for the command)
|
||||
uint8_t spi_rxbuff[RFM95_MAX_PACKET_LEN + 1];
|
||||
uint8_t spi_txbuff[RFM95_MAX_PACKET_LEN + 1];
|
||||
@@ -47,7 +47,7 @@ LOCAL uint8_t RFM95_spiMultiByteTransfer(const uint8_t cmd, uint8_t* buf, uint8_
|
||||
MY_RFM95_SPI_DATA_MODE));
|
||||
#endif
|
||||
RFM95_csn(LOW);
|
||||
#if defined(LINUX_ARCH_RASPBERRYPI)
|
||||
#if defined(LINUX_SPI_BCM)
|
||||
uint8_t * prx = spi_rxbuff;
|
||||
uint8_t * ptx = spi_txbuff;
|
||||
uint8_t size = len + 1; // Add register value to transmit buffer
|
||||
|
||||
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* 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 "RPi.h"
|
||||
#include <stdlib.h>
|
||||
#include "log.h"
|
||||
|
||||
const static int pin_to_gpio_rev1[41] = {-1, -1, -1, 0, -1, 1, -1, 4, 14, -1, 15, 17, 18, 21, -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 static 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 static 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 };
|
||||
|
||||
// Declare a single default instance
|
||||
RPi rpi = RPi();
|
||||
|
||||
const int* RPi::pin_to_gpio = NULL;
|
||||
rpi_info RPi::rpiinfo;
|
||||
|
||||
RPi::RPi()
|
||||
{
|
||||
if (!bcm2835_init()) {
|
||||
logError("Failed to initialized bcm2835.\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
RPi::~RPi()
|
||||
{
|
||||
bcm2835_close();
|
||||
}
|
||||
|
||||
void RPi::pinMode(uint8_t physPin, uint8_t mode)
|
||||
{
|
||||
uint8_t gpioPin;
|
||||
|
||||
if (physToGPIO(physPin, &gpioPin)) {
|
||||
logError("pinMode: invalid pin: %d\n", physPin);
|
||||
return;
|
||||
}
|
||||
|
||||
bcm2835_gpio_fsel(gpioPin, mode);
|
||||
}
|
||||
|
||||
void RPi::digitalWrite(uint8_t physPin, uint8_t value)
|
||||
{
|
||||
uint8_t gpioPin;
|
||||
|
||||
if (physToGPIO(physPin, &gpioPin)) {
|
||||
logError("digitalWrite: invalid pin: %d\n", physPin);
|
||||
return;
|
||||
}
|
||||
|
||||
bcm2835_gpio_write(gpioPin, value);
|
||||
// Delay to allow any change in state to be reflected in the LEVn, register bit.
|
||||
delayMicroseconds(1);
|
||||
}
|
||||
|
||||
uint8_t RPi::digitalRead(uint8_t physPin)
|
||||
{
|
||||
uint8_t gpioPin;
|
||||
|
||||
if (physToGPIO(physPin, &gpioPin)) {
|
||||
logError("digitalRead: invalid pin: %d\n", physPin);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return bcm2835_gpio_lev(gpioPin);
|
||||
}
|
||||
|
||||
uint8_t RPi::digitalPinToInterrupt(uint8_t physPin)
|
||||
{
|
||||
uint8_t gpioPin;
|
||||
|
||||
if (physToGPIO(physPin, &gpioPin)) {
|
||||
logError("digitalPinToInterrupt: invalid pin: %d\n", physPin);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return gpioPin;
|
||||
}
|
||||
|
||||
int RPi::physToGPIO(uint8_t physPin, uint8_t *gpio)
|
||||
{
|
||||
if (pin_to_gpio == NULL) {
|
||||
// detect board revision and set up accordingly
|
||||
if (get_rpi_info(&rpiinfo)) {
|
||||
logError("This module can only be run on a Raspberry Pi!\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (rpiinfo.p1_revision == 1) {
|
||||
pin_to_gpio = &pin_to_gpio_rev1[0];
|
||||
} else if (rpiinfo.p1_revision == 2) {
|
||||
pin_to_gpio = &pin_to_gpio_rev2[0];
|
||||
} else { // assume model B+ or A+ or 2B
|
||||
pin_to_gpio = &pin_to_gpio_rev3[0];
|
||||
}
|
||||
}
|
||||
|
||||
if ((rpiinfo.p1_revision != 3 && physPin > 26)
|
||||
|| (rpiinfo.p1_revision == 3 && physPin > 40)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (*(pin_to_gpio+physPin) == -1) {
|
||||
return -1;
|
||||
} else {
|
||||
*gpio = *(pin_to_gpio+physPin);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* 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 RPi_h
|
||||
#define RPi_h
|
||||
|
||||
#include <stdint.h>
|
||||
#include "bcm2835.h"
|
||||
#include "cpuinfo.h"
|
||||
|
||||
#define INPUT BCM2835_GPIO_FSEL_INPT
|
||||
#define OUTPUT BCM2835_GPIO_FSEL_OUTP
|
||||
|
||||
/**
|
||||
* @brief RPi class
|
||||
*/
|
||||
class RPi
|
||||
{
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief RPi constructor.
|
||||
*/
|
||||
RPi();
|
||||
/**
|
||||
* @brief RPi destructor.
|
||||
*/
|
||||
~RPi();
|
||||
/**
|
||||
* @brief Configures the specified pin to behave either as an input or an output.
|
||||
*
|
||||
* @param physPin The physical number of the pin.
|
||||
* @param mode INPUT or OUTPUT.
|
||||
*/
|
||||
void pinMode(uint8_t physPin, uint8_t mode);
|
||||
/**
|
||||
* @brief Write a high or a low value for the given pin.
|
||||
*
|
||||
* @param physPin The physical number of the pin.
|
||||
* @param value HIGH or LOW.
|
||||
*/
|
||||
void digitalWrite(uint8_t physPin, uint8_t value);
|
||||
/**
|
||||
* @brief Reads the value from a specified pin.
|
||||
*
|
||||
* @param physPin The physical number of the pin.
|
||||
* @return HIGH or LOW.
|
||||
*/
|
||||
uint8_t digitalRead(uint8_t physPin);
|
||||
/**
|
||||
* @brief Translate the physical pin number to the GPIO number for use in interrupt.
|
||||
*
|
||||
* @param physPin The physical number of the pin.
|
||||
* @return The GPIO pin number.
|
||||
*/
|
||||
uint8_t digitalPinToInterrupt(uint8_t physPin);
|
||||
/**
|
||||
* @brief Translate the physical pin number to the GPIO number.
|
||||
*
|
||||
* @param physPin The physical number of the pin.
|
||||
* @param gpio Pointer to write the GPIO pin number when success.
|
||||
* @return -1 if FAILURE or 0 if SUCCESS.
|
||||
*/
|
||||
static int physToGPIO(uint8_t physPin, uint8_t *gpio);
|
||||
|
||||
private:
|
||||
static const int *pin_to_gpio; //!< @brief Pointer to array of GPIO pins numbers.
|
||||
static rpi_info rpiinfo; //!< @brief Board information.
|
||||
};
|
||||
|
||||
extern RPi rpi;
|
||||
|
||||
#endif
|
||||
@@ -1,49 +0,0 @@
|
||||
/*
|
||||
* piHiPri:
|
||||
* Simple way to get your program running at high priority
|
||||
* with realtime schedulling.
|
||||
*
|
||||
* Copyright (c) 2012 Gordon Henderson
|
||||
***********************************************************************
|
||||
* This file is part of wiringPi:
|
||||
* https://projects.drogon.net/raspberry-pi/wiringpi/
|
||||
*
|
||||
* wiringPi is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* wiringPi is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with wiringPi.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
***********************************************************************
|
||||
*/
|
||||
|
||||
#include <sched.h>
|
||||
#include <string.h>
|
||||
|
||||
/*
|
||||
* piHiPri:
|
||||
* Attempt to set a high priority schedulling for the running program
|
||||
*********************************************************************************
|
||||
*/
|
||||
|
||||
int piHiPri (const int pri)
|
||||
{
|
||||
struct sched_param sched ;
|
||||
|
||||
memset (&sched, 0, sizeof(sched)) ;
|
||||
|
||||
if (pri > sched_get_priority_max (SCHED_RR)) {
|
||||
sched.sched_priority = sched_get_priority_max (SCHED_RR) ;
|
||||
} else {
|
||||
sched.sched_priority = pri ;
|
||||
}
|
||||
|
||||
return sched_setscheduler (0, SCHED_RR, &sched) ;
|
||||
}
|
||||
@@ -1,76 +0,0 @@
|
||||
/*
|
||||
* 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 Marcelo Aquino <marceloaqno@gmail.org>
|
||||
* Copyright (C) 2016 Marcelo Aquino
|
||||
* 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.
|
||||
*
|
||||
* Based on wiringPi Copyright (c) 2012 Gordon Henderson.
|
||||
*/
|
||||
|
||||
#ifndef rpi_util_h
|
||||
#define rpi_util_h
|
||||
|
||||
#include <stdint.h>
|
||||
#include "bcm2835.h"
|
||||
|
||||
const int pin_to_gpio_rev1[41] = {-1, -1, -1, 0, -1, 1, -1, 4, 14, -1, 15, 17, 18, 21, -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_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
|
||||
{
|
||||
|
||||
typedef enum {
|
||||
LSBFIRST = BCM2835_SPI_BIT_ORDER_LSBFIRST,
|
||||
MSBFIRST = BCM2835_SPI_BIT_ORDER_MSBFIRST
|
||||
} rpi_bitorder;
|
||||
|
||||
typedef enum {
|
||||
INPUT = BCM2835_GPIO_FSEL_INPT,
|
||||
OUTPUT = BCM2835_GPIO_FSEL_OUTP
|
||||
} rpi_pinmode;
|
||||
|
||||
typedef enum {
|
||||
CHANGE = 1,
|
||||
FALLING = 2,
|
||||
RISING = 3,
|
||||
NONE = 4
|
||||
} rpi_pinedge;
|
||||
|
||||
typedef enum {
|
||||
PIN_SPI_SS = 24,
|
||||
PIN_SPI_MOSI = 19,
|
||||
PIN_SPI_MISO = 21,
|
||||
PIN_SPI_SCK = 23
|
||||
} rpi_spipins;
|
||||
|
||||
const uint8_t SS = PIN_SPI_SS;
|
||||
const uint8_t MOSI = PIN_SPI_MOSI;
|
||||
const uint8_t MISO = PIN_SPI_MISO;
|
||||
const uint8_t SCK = PIN_SPI_SCK;
|
||||
|
||||
/* Some useful arduino functions */
|
||||
void pinMode(uint8_t physPin, uint8_t mode);
|
||||
void digitalWrite(uint8_t physPin, uint8_t value);
|
||||
uint8_t digitalRead(uint8_t physPin);
|
||||
void attachInterrupt(uint8_t physPin,void (*func)(), uint8_t mode);
|
||||
void detachInterrupt(uint8_t physPin);
|
||||
uint8_t digitalPinToInterrupt(uint8_t physPin);
|
||||
void interrupts();
|
||||
void noInterrupts();
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,289 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* Based on TMRh20 RF24 library, Copyright (c) 2015 Charles-Henri Hallard <tmrh20@gmail.com>
|
||||
*/
|
||||
|
||||
#include "SPI.h"
|
||||
#include <fcntl.h>
|
||||
#include <pthread.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <unistd.h>
|
||||
#include "log.h"
|
||||
|
||||
static pthread_mutex_t spiMutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
static pthread_mutexattr_t attr;
|
||||
|
||||
// Declare a single default instance
|
||||
SPIClass SPI = SPIClass();
|
||||
|
||||
uint8_t SPIClass::initialized = 0;
|
||||
int SPIClass::fd = -1;
|
||||
std::string SPIClass::device = SPI_SPIDEV_DEVICE;
|
||||
uint32_t SPIClass::speed = SPI_CLOCK_BASE;
|
||||
uint32_t SPIClass::speed_temp = SPI_CLOCK_BASE;
|
||||
struct spi_ioc_transfer SPIClass::tr = {0,0,0,0,0,8,1,0,0,0}; // 8 bits_per_word, 1 cs_change
|
||||
|
||||
SPIClass::SPIClass()
|
||||
{
|
||||
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
|
||||
pthread_mutex_init(&spiMutex, &attr);
|
||||
}
|
||||
|
||||
void SPIClass::begin(int busNo)
|
||||
{
|
||||
if (!initialized) {
|
||||
/* set spidev accordingly to busNo like:
|
||||
* busNo = 23 -> /dev/spidev2.3
|
||||
*
|
||||
* a bit messy but simple
|
||||
* */
|
||||
device[11] += (busNo / 10) % 10;
|
||||
device[13] += busNo % 10;
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
initialized++; // reference count
|
||||
}
|
||||
|
||||
void SPIClass::end()
|
||||
{
|
||||
if (initialized) {
|
||||
initialized--;
|
||||
}
|
||||
|
||||
if (!initialized) {
|
||||
if (!(fd < 0)) {
|
||||
close(fd);
|
||||
fd = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SPIClass::setBitOrder(uint8_t bit_order)
|
||||
{
|
||||
pthread_mutex_lock(&spiMutex);
|
||||
|
||||
/*
|
||||
* bit order
|
||||
*/
|
||||
int lsb_setting = bit_order;
|
||||
int ret = ioctl(fd, SPI_IOC_WR_LSB_FIRST, &lsb_setting);
|
||||
if (ret == -1) {
|
||||
logError("Can't set SPI bit order.\n");
|
||||
abort();
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&spiMutex);
|
||||
}
|
||||
|
||||
void SPIClass::setDataMode(uint8_t data_mode)
|
||||
{
|
||||
pthread_mutex_lock(&spiMutex);
|
||||
|
||||
/*
|
||||
* spi mode
|
||||
*/
|
||||
int ret = ioctl(fd, SPI_IOC_WR_MODE, &data_mode);
|
||||
if (ret == -1) {
|
||||
logError("Can't set SPI mode.\n");
|
||||
abort();
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&spiMutex);
|
||||
}
|
||||
|
||||
void SPIClass::setClockDivider(uint16_t divider)
|
||||
{
|
||||
pthread_mutex_lock(&spiMutex);
|
||||
|
||||
/*
|
||||
* max speed hz
|
||||
*/
|
||||
speed = SPI_CLOCK_BASE / divider;
|
||||
int ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);
|
||||
if (ret == -1) {
|
||||
logError("Can't set SPI max speed hz.\n");
|
||||
abort();
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&spiMutex);
|
||||
}
|
||||
|
||||
void SPIClass::chipSelect(int csn_chip)
|
||||
{
|
||||
if (csn_chip >= 0 && csn_chip <= 9) {
|
||||
device[13] = '0' + (csn_chip % 10);
|
||||
|
||||
init();
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t SPIClass::transfer(uint8_t data)
|
||||
{
|
||||
int ret;
|
||||
uint8_t tx[1] = {data};
|
||||
uint8_t rx[1] = {0};
|
||||
|
||||
pthread_mutex_lock(&spiMutex);
|
||||
|
||||
tr.tx_buf = (unsigned long)&tx[0];
|
||||
tr.rx_buf = (unsigned long)&rx[0];
|
||||
tr.len = 1;
|
||||
tr.speed_hz = speed;
|
||||
|
||||
ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
|
||||
if (ret < 1) {
|
||||
logError("Can't send spi message.\n");
|
||||
abort();
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&spiMutex);
|
||||
|
||||
return rx[0];
|
||||
}
|
||||
|
||||
void SPIClass::transfernb(char* tbuf, char* rbuf, uint32_t len)
|
||||
{
|
||||
int ret;
|
||||
|
||||
pthread_mutex_lock(&spiMutex);
|
||||
|
||||
tr.tx_buf = (unsigned long)tbuf;
|
||||
tr.rx_buf = (unsigned long)rbuf;
|
||||
tr.len = len;
|
||||
tr.speed_hz = speed;
|
||||
|
||||
ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
|
||||
if (ret < 1) {
|
||||
logError("Can't send spi message.\n");
|
||||
abort();
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&spiMutex);
|
||||
}
|
||||
|
||||
void SPIClass::transfern(char* buf, uint32_t len)
|
||||
{
|
||||
transfernb(buf, buf, len);
|
||||
}
|
||||
|
||||
void SPIClass::beginTransaction(SPISettings settings)
|
||||
{
|
||||
int ret;
|
||||
|
||||
pthread_mutex_lock(&spiMutex);
|
||||
|
||||
/*
|
||||
* spi mode
|
||||
*/
|
||||
ret = ioctl(fd, SPI_IOC_WR_MODE, &settings.dmode);
|
||||
if (ret == -1) {
|
||||
logError("Can't set spi mode.\n");
|
||||
abort();
|
||||
}
|
||||
|
||||
// Save the current speed
|
||||
speed_temp = speed;
|
||||
speed = settings.clock;
|
||||
|
||||
/*
|
||||
* bit order
|
||||
*/
|
||||
ret = ioctl(fd, SPI_IOC_WR_LSB_FIRST, &settings.border);
|
||||
if (ret == -1) {
|
||||
logError("Can't set bits per word.\n");
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
void SPIClass::endTransaction()
|
||||
{
|
||||
speed = speed_temp;
|
||||
pthread_mutex_unlock(&spiMutex);
|
||||
}
|
||||
|
||||
void SPIClass::usingInterrupt(uint8_t interruptNumber)
|
||||
{
|
||||
(void)interruptNumber;
|
||||
}
|
||||
|
||||
void SPIClass::notUsingInterrupt(uint8_t interruptNumber)
|
||||
{
|
||||
(void)interruptNumber;
|
||||
}
|
||||
|
||||
void SPIClass::init()
|
||||
{
|
||||
pthread_mutex_lock(&spiMutex);
|
||||
|
||||
if (fd >= 0) {
|
||||
close(fd);
|
||||
}
|
||||
|
||||
fd = open(device.c_str(), O_RDWR);
|
||||
if (fd < 0) {
|
||||
logError("Can't open SPI device: %s\n", device.c_str());
|
||||
abort();
|
||||
}
|
||||
|
||||
/*
|
||||
* spi mode
|
||||
*/
|
||||
uint8_t mode = SPI_MODE0;
|
||||
int ret = ioctl(fd, SPI_IOC_WR_MODE, &mode);
|
||||
if (ret == -1) {
|
||||
logError("Can't set SPI mode.\n");
|
||||
abort();
|
||||
}
|
||||
|
||||
/*
|
||||
* bits per word
|
||||
*/
|
||||
uint8_t bits = 0; // 0 corresponds to 8 bits per word
|
||||
ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits);
|
||||
if (ret == -1) {
|
||||
logError("Can't set SPI bits per word.\n");
|
||||
abort();
|
||||
}
|
||||
|
||||
/*
|
||||
* max speed hz
|
||||
*/
|
||||
speed = SPI_CLOCK_BASE;
|
||||
ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);
|
||||
if (ret == -1) {
|
||||
logError("Can't set SPI max speed hz.\n");
|
||||
abort();
|
||||
}
|
||||
|
||||
/*
|
||||
* bit order
|
||||
*/
|
||||
int lsb_setting = MSBFIRST;
|
||||
ret = ioctl(fd, SPI_IOC_WR_LSB_FIRST, &lsb_setting);
|
||||
if (ret == -1) {
|
||||
logError("Can't set SPI bit order.\n");
|
||||
abort();
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&spiMutex);
|
||||
}
|
||||
@@ -0,0 +1,206 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* Based on TMRh20 RF24 library, Copyright (c) 2015 Charles-Henri Hallard <tmrh20@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef SPI_H
|
||||
#define SPI_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
#include <linux/spi/spidev.h>
|
||||
|
||||
#define SPI_HAS_TRANSACTION
|
||||
|
||||
#define MSBFIRST 0
|
||||
#define LSBFIRST SPI_LSB_FIRST
|
||||
|
||||
#define SPI_CLOCK_BASE 16000000 // 16Mhz
|
||||
|
||||
#define SPI_CLOCK_DIV2 2
|
||||
#define SPI_CLOCK_DIV4 4
|
||||
#define SPI_CLOCK_DIV8 8
|
||||
#define SPI_CLOCK_DIV16 16
|
||||
#define SPI_CLOCK_DIV32 32
|
||||
#define SPI_CLOCK_DIV64 64
|
||||
#define SPI_CLOCK_DIV128 128
|
||||
|
||||
// SPI Data mode
|
||||
#define SPI_MODE0 SPI_MODE_0
|
||||
#define SPI_MODE1 SPI_MODE_1
|
||||
#define SPI_MODE2 SPI_MODE_2
|
||||
#define SPI_MODE3 SPI_MODE_3
|
||||
|
||||
#ifndef SPI_SPIDEV_DEVICE
|
||||
#define SPI_SPIDEV_DEVICE "/dev/spidev0.0"
|
||||
#endif
|
||||
|
||||
// Default to Raspberry Pi
|
||||
const uint8_t SS = 24;
|
||||
const uint8_t MOSI = 19;
|
||||
const uint8_t MISO = 21;
|
||||
const uint8_t SCK = 23;
|
||||
|
||||
/**
|
||||
* SPISettings class
|
||||
*/
|
||||
class SPISettings
|
||||
{
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief SPISettings constructor.
|
||||
*/
|
||||
SPISettings()
|
||||
{
|
||||
init(SPI_CLOCK_BASE, MSBFIRST, SPI_MODE0);
|
||||
}
|
||||
/**
|
||||
* @brief SPISettings constructor.
|
||||
*
|
||||
* @param clock SPI clock speed in Hz.
|
||||
* @param bitOrder SPI bit order.
|
||||
* @param dataMode SPI data mode.
|
||||
*/
|
||||
SPISettings(uint32_t clock, uint8_t bitOrder, uint8_t dataMode)
|
||||
{
|
||||
init(clock, bitOrder, dataMode);
|
||||
}
|
||||
|
||||
uint32_t clock; //!< @brief SPI clock.
|
||||
uint8_t border; //!< @brief SPI bit order.
|
||||
uint8_t dmode; //!< @brief SPI data mode.
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief Initialized class members.
|
||||
*
|
||||
* @param clk SPI clock.
|
||||
* @param bitOrder SPI bit order.
|
||||
* @param dataMode SPI data mode.
|
||||
*/
|
||||
void init(uint32_t clk, uint8_t bitOrder, uint8_t dataMode)
|
||||
{
|
||||
clock = clk;
|
||||
border = bitOrder;
|
||||
dmode = dataMode;
|
||||
}
|
||||
|
||||
friend class SPIClass;
|
||||
};
|
||||
|
||||
class SPIClass
|
||||
{
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief SPIClass constructor.
|
||||
*/
|
||||
SPIClass();
|
||||
/**
|
||||
* @brief Start SPI operations.
|
||||
*/
|
||||
static void begin(int busNo=0);
|
||||
/**
|
||||
* @brief End SPI operations.
|
||||
*/
|
||||
static void end();
|
||||
/**
|
||||
* @brief Sets the SPI bit order.
|
||||
*
|
||||
* @param bit_order The desired bit order.
|
||||
*/
|
||||
static void setBitOrder(uint8_t bit_order);
|
||||
/**
|
||||
* @brief Sets the SPI data mode.
|
||||
*
|
||||
* @param data_mode The desired data mode.
|
||||
*/
|
||||
static void setDataMode(uint8_t data_mode);
|
||||
/**
|
||||
* @brief Sets the SPI clock divider and therefore the SPI clock speed.
|
||||
*
|
||||
* @param divider The desired SPI clock divider.
|
||||
*/
|
||||
static void setClockDivider(uint16_t divider);
|
||||
/**
|
||||
* @brief Sets the chip select pin.
|
||||
*
|
||||
* @param csn_chip Specifies the CS chip.
|
||||
*/
|
||||
static void chipSelect(int csn_chip);
|
||||
/**
|
||||
* @brief Transfer a single byte
|
||||
*
|
||||
* @param data Byte to send
|
||||
* @return Data returned via spi
|
||||
*/
|
||||
static uint8_t transfer(uint8_t data);
|
||||
/**
|
||||
* @brief Transfer a buffer of data
|
||||
*
|
||||
* @param tbuf Transmit buffer
|
||||
* @param rbuf Receive buffer
|
||||
* @param len Length of the data
|
||||
*/
|
||||
static void transfernb(char* tbuf, char* rbuf, uint32_t len);
|
||||
/**
|
||||
* @briefTransfer a buffer of data without an rx buffer
|
||||
*
|
||||
* @param buf Pointer to a buffer of data
|
||||
* @param len Length of the data
|
||||
*/
|
||||
static void transfern(char* buf, uint32_t len);
|
||||
/**
|
||||
* @brief Start SPI transaction.
|
||||
*
|
||||
* @param settings for SPI.
|
||||
*/
|
||||
static void beginTransaction(SPISettings settings);
|
||||
/**
|
||||
* @brief End SPI transaction.
|
||||
*/
|
||||
static void endTransaction();
|
||||
/**
|
||||
* @brief Not implemented.
|
||||
*
|
||||
* @param interruptNumber ignored parameter.
|
||||
*/
|
||||
static void usingInterrupt(uint8_t interruptNumber);
|
||||
/**
|
||||
* @brief Not implemented.
|
||||
*
|
||||
* @param interruptNumber ignored parameter.
|
||||
*/
|
||||
static void notUsingInterrupt(uint8_t interruptNumber);
|
||||
|
||||
private:
|
||||
static uint8_t initialized; //!< @brief SPI initialized flag.
|
||||
static int fd; //!< @brief SPI device file descriptor.
|
||||
static std::string device; //!< @brief Default SPI device.
|
||||
static uint32_t speed; //!< @brief SPI speed.
|
||||
static uint32_t speed_temp; //!< @brief Used when doing transaction.
|
||||
static struct spi_ioc_transfer tr; //!< @brief Auxiliar struct for data transfer.
|
||||
|
||||
static void init();
|
||||
};
|
||||
|
||||
extern SPIClass SPI;
|
||||
|
||||
#endif
|
||||
@@ -60,7 +60,7 @@ void SPIFlash::select()
|
||||
#ifndef SPI_HAS_TRANSACTION
|
||||
noInterrupts();
|
||||
#endif
|
||||
#ifndef ESP8266
|
||||
#if defined(SPCR) && defined(SPSR)
|
||||
_SPCR = SPCR;
|
||||
_SPSR = SPSR;
|
||||
#endif
|
||||
@@ -88,7 +88,7 @@ void SPIFlash::unselect()
|
||||
#else
|
||||
interrupts();
|
||||
#endif
|
||||
#ifndef ESP8266
|
||||
#if defined(SPCR) && defined(SPSR)
|
||||
SPCR = _SPCR;
|
||||
SPSR = _SPSR;
|
||||
#endif
|
||||
@@ -97,7 +97,7 @@ void SPIFlash::unselect()
|
||||
/// setup SPI, read device ID etc...
|
||||
boolean SPIFlash::initialize()
|
||||
{
|
||||
#ifndef ESP8266
|
||||
#if defined(SPCR) && defined(SPSR)
|
||||
_SPCR = SPCR;
|
||||
_SPSR = SPSR;
|
||||
#endif
|
||||
|
||||
@@ -350,7 +350,7 @@ void presentation()
|
||||
|
||||
// Get controller configuration
|
||||
Serial.print("Get Config: ");
|
||||
metric = getConfig().isMetric;
|
||||
metric = getControllerConfig().isMetric;
|
||||
Serial.println(metric ? "Metric":"Imperial");
|
||||
wait(LONG_WAIT);
|
||||
|
||||
|
||||
@@ -84,7 +84,7 @@ void sendPingOrPongResponse( MyMessage msg )
|
||||
nodeTypeAsCharRepresentation(msg.sender));
|
||||
|
||||
// Set payload to current time in millis to ensure each message is unique
|
||||
response.set( millis() );
|
||||
response.set( (uint32_t)millis() );
|
||||
response.setDestination(msg.sender);
|
||||
send(response);
|
||||
}
|
||||
@@ -92,7 +92,7 @@ void sendPingOrPongResponse( MyMessage msg )
|
||||
void setNodeId(byte nodeID)
|
||||
{
|
||||
LOG(F("Setting node id to: %i.\n***Please restart the node for changes to take effect.\n"), nodeID);
|
||||
eeprom_write_byte((uint8_t*)EEPROM_NODE_ID_ADDRESS, (byte)nodeID);
|
||||
hwWriteConfig(EEPROM_NODE_ID_ADDRESS, (byte)nodeID);
|
||||
}
|
||||
|
||||
const char * msgTypeAsCharRepresentation( mysensor_data mType )
|
||||
@@ -103,4 +103,4 @@ const char * msgTypeAsCharRepresentation( mysensor_data mType )
|
||||
const char * nodeTypeAsCharRepresentation( uint8_t node )
|
||||
{
|
||||
return node == YING ? "Ying Node" : "Yang Node";
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
/**
|
||||
/*
|
||||
* 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
|
||||
@@ -6,7 +6,7 @@
|
||||
* network topology allowing messages to be routed to nodes.
|
||||
*
|
||||
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
|
||||
* Copyright (C) 2013-2016 Sensnology AB
|
||||
* Copyright (C) 2013-2017 Sensnology AB
|
||||
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
|
||||
*
|
||||
* Documentation: http://www.mysensors.org
|
||||
@@ -33,7 +33,7 @@
|
||||
// Enable this if you are using an Arduino connected to the USB
|
||||
//#define MY_LINUX_SERIAL_PORT "/dev/ttyACM0"
|
||||
// Enable this if you need to connect to a controller running on the same device
|
||||
//#define MY_IS_SERIAL_PTY
|
||||
//#define MY_LINUX_IS_SERIAL_PTY
|
||||
// Choose a symlink name for the PTY device
|
||||
//#define MY_LINUX_SERIAL_PTY "/dev/ttyMySensorsGateway"
|
||||
// Grant access to the specified system group for the serial device
|
||||
|
||||
+8
-12
@@ -7,22 +7,18 @@
|
||||
"type": "git",
|
||||
"url": "https://github.com/mysensors/MySensors.git"
|
||||
},
|
||||
"version": "2.1.0",
|
||||
"version": "2.1.1",
|
||||
"frameworks": "arduino",
|
||||
"platforms": [
|
||||
"atmelavr",
|
||||
"atmelsam",
|
||||
"espressif"
|
||||
"espressif8266"
|
||||
],
|
||||
"exclude": [
|
||||
"tests",
|
||||
"Documentation"
|
||||
],
|
||||
"build": {
|
||||
"srcFilter": [
|
||||
"+<*.c>",
|
||||
"+<*.cpp>",
|
||||
"+<*.h>"
|
||||
"export": {
|
||||
"exclude": [
|
||||
"tests",
|
||||
"Documentation",
|
||||
"Doxyfile"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
name=MySensors
|
||||
version=2.1.0
|
||||
version=2.1.1
|
||||
author=The MySensors Team
|
||||
maintainer=The MySensors Team
|
||||
sentence=Home Automation Framework
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* 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-2015 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 <stdint.h>
|
||||
#include <pins_arduino.h>
|
||||
#define MY_DEBUG
|
||||
#define MY_RADIO_NRF24
|
||||
#define MY_OTA_FIRMWARE_FEATURE
|
||||
#include <MySensors.h>
|
||||
Reference in New Issue
Block a user