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.
This commit is contained in:
Marcelo Aquino
2017-01-14 23:50:21 +01:00
committed by Henrik Ekblad
parent aa5cecfca1
commit 2e0f6b6229
43 changed files with 1574 additions and 593 deletions
+16
View File
@@ -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
View File
@@ -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
+1 -5
View File
@@ -66,12 +66,8 @@
#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
Vendored
+65 -17
View File
@@ -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."
+16 -1
View File
@@ -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, ...)
{
+9 -4
View File
@@ -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);
-146
View File
@@ -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);
}
+15 -15
View File
@@ -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);
}
}
+3 -8
View File
@@ -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) {
+72 -42
View File
@@ -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
View File
@@ -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);
+4 -5
View File
@@ -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);
+7 -7
View File
@@ -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
+4 -4
View File
@@ -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);
}
+16 -16
View File
@@ -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
+211
View File
@@ -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;
}
+91
View File
@@ -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
+2 -2
View File
@@ -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.
*
+2 -2
View File
@@ -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);
+6 -8
View File
@@ -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;
+3 -3
View File
@@ -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
+56
View File
@@ -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();
}
+76
View File
@@ -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
+4 -4
View File
@@ -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
+9 -9
View File
@@ -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
+1
View File
@@ -57,6 +57,7 @@ public:
Stream()
{
_timeout = 1000;
_startMillis = 0;
}
// parsing methods
+29 -1
View File
@@ -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;
+21 -31
View File
@@ -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
+19
View File
@@ -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>
+19
View File
@@ -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
+2 -2
View File
@@ -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
View File
@@ -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;
+2 -2
View File
@@ -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
+127
View File
@@ -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;
}
+89
View File
@@ -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
-49
View File
@@ -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) ;
}
-76
View File
@@ -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
+289
View File
@@ -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);
}
+206
View File
@@ -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
+3 -3
View File
@@ -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