Files
MySensors/drivers/BCM/SPI.h
T
Olivier 8bb3cfb2e1 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
2017-01-18 21:57:07 +01:00

263 lines
6.8 KiB
C++

/*
* 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 <stdio.h>
#include "bcm2835.h"
#include "RPi.h"
#define SPI_HAS_TRANSACTION
#define SPI_CLOCK_BASE 256000000
// SPI Clock divider
#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
#define SPI_MODE1 BCM2835_SPI_MODE1
#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
*/
class SPISettings
{
public:
/**
* @brief SPISettings constructor.
*
* Default clock speed is 8Mhz.
*/
SPISettings()
{
init(SPI_CLOCK_DIV32, 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)
{
uint16_t divider;
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);
}
uint16_t cdiv; //!< @brief SPI clock divider.
uint8_t border; //!< @brief SPI bit order.
uint8_t dmode; //!< @brief SPI data mode.
private:
/**
* @brief Initialized class members.
*
* @param divider SPI clock divider.
* @param bitOrder SPI bit order.
* @param dataMode SPI data mode.
*/
void init(uint16_t divider, uint8_t bitOrder, uint8_t dataMode)
{
cdiv = divider;
border = bitOrder;
dmode = dataMode;
}
friend class SPIClass;
};
/**
* SPIClass class
*/
class SPIClass
{
public:
/**
* @brief Send and receive a byte.
*
* @param data to send.
* @return byte received.
*/
inline static uint8_t transfer(uint8_t data);
/**
* @brief Send and receive a number of bytes.
*
* @param tbuf Sending buffer.
* @param rbuf Receive buffer.
* @param len Buffer length.
*/
inline static void transfernb(char* tbuf, char* rbuf, uint32_t len);
/**
* @brief Send and receive a number of bytes.
*
* @param buf Buffer to read from and write to.
* @param len Buffer length.
*/
inline static void transfern(char* buf, uint32_t len);
/**
* @brief Start SPI operations.
*/
static void begin();
/**
* @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_pin Specifies the CS pin.
*/
static void chipSelect(int csn_pin);
/**
* @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.
};
uint8_t SPIClass::transfer(uint8_t data)
{
return bcm2835_spi_transfer(data);
}
void SPIClass::transfernb(char* tbuf, char* rbuf, uint32_t len)
{
bcm2835_spi_transfernb( tbuf, rbuf, len);
}
void SPIClass::transfern(char* buf, uint32_t len)
{
transfernb(buf, buf, len);
}
extern SPIClass SPI;
#endif