Restructure RPi files (#827)

- Restructure SPi files for linux and RPi
- Update RPi revision detection (#826)
This commit is contained in:
Marcelo Aquino
2017-04-19 22:03:10 +02:00
committed by Henrik Ekblad
parent 26c237adad
commit 4c31e22d6f
19 changed files with 345 additions and 505 deletions
+8 -8
View File
@@ -34,16 +34,16 @@
#ifdef LINUX_ARCH_RASPBERRYPI
#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)
#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)
#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"
+9 -9
View File
@@ -27,9 +27,9 @@
#include "log.h"
// Declare a single default instance
GPIO gpio = GPIO();
GPIOClass GPIO = GPIOClass();
GPIO::GPIO()
GPIOClass::GPIOClass()
{
FILE *f;
DIR* dp;
@@ -83,7 +83,7 @@ GPIO::GPIO()
}
}
GPIO::GPIO(const GPIO& other)
GPIOClass::GPIOClass(const GPIOClass& other)
{
lastPinNum = other.lastPinNum;
@@ -93,7 +93,7 @@ GPIO::GPIO(const GPIO& other)
}
}
GPIO::~GPIO()
GPIOClass::~GPIOClass()
{
FILE *f;
@@ -108,7 +108,7 @@ GPIO::~GPIO()
delete [] exportedPins;
}
void GPIO::pinMode(uint8_t pin, uint8_t mode)
void GPIOClass::pinMode(uint8_t pin, uint8_t mode)
{
FILE *f;
@@ -144,7 +144,7 @@ void GPIO::pinMode(uint8_t pin, uint8_t mode)
fclose(f);
}
void GPIO::digitalWrite(uint8_t pin, uint8_t value)
void GPIOClass::digitalWrite(uint8_t pin, uint8_t value)
{
FILE *f;
char file[128];
@@ -168,7 +168,7 @@ void GPIO::digitalWrite(uint8_t pin, uint8_t value)
fclose(f);
}
uint8_t GPIO::digitalRead(uint8_t pin)
uint8_t GPIOClass::digitalRead(uint8_t pin)
{
FILE *f;
char file[128];
@@ -192,12 +192,12 @@ uint8_t GPIO::digitalRead(uint8_t pin)
return i;
}
uint8_t GPIO::digitalPinToInterrupt(uint8_t pin)
uint8_t GPIOClass::digitalPinToInterrupt(uint8_t pin)
{
return pin;
}
GPIO& GPIO::operator=(const GPIO& other)
GPIOClass& GPIOClass::operator=(const GPIOClass& other)
{
if (this != &other) {
lastPinNum = other.lastPinNum;
+9 -9
View File
@@ -31,22 +31,22 @@
/**
* @brief GPIO class
*/
class GPIO
class GPIOClass
{
public:
/**
* @brief GPIO constructor.
* @brief GPIOClass constructor.
*/
GPIO();
GPIOClass();
/**
* @brief GPIO copy constructor.
* @brief GPIOClass copy constructor.
*/
GPIO(const GPIO& other);
GPIOClass(const GPIOClass& other);
/**
* @brief GPIO destructor.
* @brief GPIOClass destructor.
*/
~GPIO();
~GPIOClass();
/**
* @brief Configures the specified pin to behave either as an input or an output.
*
@@ -79,13 +79,13 @@ public:
* @brief Overloaded assign operator.
*
*/
GPIO& operator=(const GPIO& other);
GPIOClass& operator=(const GPIOClass& other);
private:
int lastPinNum; //!< @brief Highest pin number supported.
uint8_t *exportedPins; //!< @brief Array with information of which pins were exported.
};
extern GPIO gpio;
extern GPIOClass GPIO;
#endif
+31
View File
@@ -0,0 +1,31 @@
/*
* 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 _SPI_H_
#define _SPI_H_
#ifdef LINUX_SPI_BCM
#include "SPIBCM.h"
#define SPI SPIBCM
#elif LINUX_SPI_SPIDEV
#include "SPIDEV.h"
#define SPI SPIDEV
#endif
#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 "SPIDEV.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
SPIDEVClass SPIDEV = SPIDEVClass();
uint8_t SPIDEVClass::initialized = 0;
int SPIDEVClass::fd = -1;
std::string SPIDEVClass::device = SPI_SPIDEV_DEVICE;
uint32_t SPIDEVClass::speed = SPI_CLOCK_BASE;
uint32_t SPIDEVClass::speed_temp = SPI_CLOCK_BASE;
struct spi_ioc_transfer SPIDEVClass::tr = {0,0,0,0,0,8,1,0,0,0}; // 8 bits_per_word, 1 cs_change
SPIDEVClass::SPIDEVClass()
{
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init(&spiMutex, &attr);
}
void SPIDEVClass::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 SPIDEVClass::end()
{
if (initialized) {
initialized--;
}
if (!initialized) {
if (!(fd < 0)) {
close(fd);
fd = -1;
}
}
}
void SPIDEVClass::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 SPIDEVClass::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 SPIDEVClass::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 SPIDEVClass::chipSelect(int csn_chip)
{
if (csn_chip >= 0 && csn_chip <= 9) {
device[13] = '0' + (csn_chip % 10);
init();
}
}
uint8_t SPIDEVClass::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 SPIDEVClass::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 SPIDEVClass::transfern(char* buf, uint32_t len)
{
transfernb(buf, buf, len);
}
void SPIDEVClass::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 SPIDEVClass::endTransaction()
{
speed = speed_temp;
pthread_mutex_unlock(&spiMutex);
}
void SPIDEVClass::usingInterrupt(uint8_t interruptNumber)
{
(void)interruptNumber;
}
void SPIDEVClass::notUsingInterrupt(uint8_t interruptNumber)
{
(void)interruptNumber;
}
void SPIDEVClass::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);
}
+209
View File
@@ -0,0 +1,209 @@
/*
* 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 SPIDEV_h
#define SPIDEV_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 SPIDEVClass;
};
/**
* SPIDEV class
*/
class SPIDEVClass
{
public:
/**
* @brief SPIDEVClass constructor.
*/
SPIDEVClass();
/**
* @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);
/**
* @brief Transfer 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 SPIDEVClass SPIDEV;
#endif