mirror of
https://github.com/IoTManagerProject/IoTManager.git
synced 2026-03-28 23:22:19 +03:00
181 lines
5.1 KiB
C++
181 lines
5.1 KiB
C++
/* Arduino DigitalIO Library
|
|
* Copyright (C) 2013 by William Greiman
|
|
*
|
|
* This file is part of the Arduino DigitalIO Library
|
|
*
|
|
* This Library is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This Library 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 General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with the Arduino DigitalIO Library. If not, see
|
|
* <http://www.gnu.org/licenses/>.
|
|
*/
|
|
/**
|
|
* @file
|
|
* @brief Software SPI.
|
|
*
|
|
* @defgroup softSPI Software SPI
|
|
* @details Software SPI Template Class.
|
|
* @{
|
|
*/
|
|
|
|
#ifndef SoftSPI_h
|
|
#define SoftSPI_h
|
|
#include "DigitalPin.h"
|
|
//------------------------------------------------------------------------------
|
|
/** Nop for timing. */
|
|
#define nop asm volatile ("nop\n\t")
|
|
//------------------------------------------------------------------------------
|
|
/** Pin Mode for MISO is input.*/
|
|
#define MISO_MODE INPUT
|
|
/** Pullups disabled for MISO are disabled. */
|
|
#define MISO_LEVEL false
|
|
/** Pin Mode for MOSI is output.*/
|
|
#define MOSI_MODE OUTPUT
|
|
/** Pin Mode for SCK is output. */
|
|
#define SCK_MODE OUTPUT
|
|
//------------------------------------------------------------------------------
|
|
/**
|
|
* @class SoftSPI
|
|
* @brief Fast software SPI.
|
|
*/
|
|
template<uint8_t MisoPin, uint8_t MosiPin, uint8_t SckPin, uint8_t Mode = 0>
|
|
class SoftSPI
|
|
{
|
|
public:
|
|
//----------------------------------------------------------------------------
|
|
/** Initialize SoftSPI pins. */
|
|
void begin()
|
|
{
|
|
fastPinConfig(MisoPin, MISO_MODE, MISO_LEVEL);
|
|
fastPinConfig(MosiPin, MOSI_MODE, !MODE_CPHA(Mode));
|
|
fastPinConfig(SckPin, SCK_MODE, MODE_CPOL(Mode));
|
|
}
|
|
//----------------------------------------------------------------------------
|
|
/** Soft SPI receive byte.
|
|
* @return Data byte received.
|
|
*/
|
|
inline __attribute__((always_inline))
|
|
uint8_t receive()
|
|
{
|
|
uint8_t data = 0;
|
|
receiveBit(7, &data);
|
|
receiveBit(6, &data);
|
|
receiveBit(5, &data);
|
|
receiveBit(4, &data);
|
|
receiveBit(3, &data);
|
|
receiveBit(2, &data);
|
|
receiveBit(1, &data);
|
|
receiveBit(0, &data);
|
|
return data;
|
|
}
|
|
//----------------------------------------------------------------------------
|
|
/** Soft SPI send byte.
|
|
* @param[in] data Data byte to send.
|
|
*/
|
|
inline __attribute__((always_inline))
|
|
void send(uint8_t data)
|
|
{
|
|
sendBit(7, data);
|
|
sendBit(6, data);
|
|
sendBit(5, data);
|
|
sendBit(4, data);
|
|
sendBit(3, data);
|
|
sendBit(2, data);
|
|
sendBit(1, data);
|
|
sendBit(0, data);
|
|
}
|
|
//----------------------------------------------------------------------------
|
|
/** Soft SPI transfer byte.
|
|
* @param[in] txData Data byte to send.
|
|
* @return Data byte received.
|
|
*/
|
|
inline __attribute__((always_inline))
|
|
uint8_t transfer(uint8_t txData)
|
|
{
|
|
uint8_t rxData = 0;
|
|
transferBit(7, &rxData, txData);
|
|
transferBit(6, &rxData, txData);
|
|
transferBit(5, &rxData, txData);
|
|
transferBit(4, &rxData, txData);
|
|
transferBit(3, &rxData, txData);
|
|
transferBit(2, &rxData, txData);
|
|
transferBit(1, &rxData, txData);
|
|
transferBit(0, &rxData, txData);
|
|
return rxData;
|
|
}
|
|
|
|
private:
|
|
//----------------------------------------------------------------------------
|
|
inline __attribute__((always_inline))
|
|
bool MODE_CPHA(uint8_t mode)
|
|
{
|
|
return (mode & 1) != 0;
|
|
}
|
|
inline __attribute__((always_inline))
|
|
bool MODE_CPOL(uint8_t mode)
|
|
{
|
|
return (mode & 2) != 0;
|
|
}
|
|
inline __attribute__((always_inline))
|
|
void receiveBit(uint8_t bit, uint8_t* data)
|
|
{
|
|
if (MODE_CPHA(Mode)) {
|
|
fastDigitalWrite(SckPin, !MODE_CPOL(Mode));
|
|
}
|
|
nop;
|
|
nop;
|
|
fastDigitalWrite(SckPin,
|
|
MODE_CPHA(Mode) ? MODE_CPOL(Mode) : !MODE_CPOL(Mode));
|
|
if (fastDigitalRead(MisoPin)) {
|
|
*data |= 1 << bit;
|
|
}
|
|
if (!MODE_CPHA(Mode)) {
|
|
fastDigitalWrite(SckPin, MODE_CPOL(Mode));
|
|
}
|
|
}
|
|
//----------------------------------------------------------------------------
|
|
inline __attribute__((always_inline))
|
|
void sendBit(uint8_t bit, uint8_t data)
|
|
{
|
|
if (MODE_CPHA(Mode)) {
|
|
fastDigitalWrite(SckPin, !MODE_CPOL(Mode));
|
|
}
|
|
fastDigitalWrite(MosiPin, data & (1 << bit));
|
|
fastDigitalWrite(SckPin,
|
|
MODE_CPHA(Mode) ? MODE_CPOL(Mode) : !MODE_CPOL(Mode));
|
|
nop;
|
|
nop;
|
|
if (!MODE_CPHA(Mode)) {
|
|
fastDigitalWrite(SckPin, MODE_CPOL(Mode));
|
|
}
|
|
}
|
|
//----------------------------------------------------------------------------
|
|
inline __attribute__((always_inline))
|
|
void transferBit(uint8_t bit, uint8_t* rxData, uint8_t txData)
|
|
{
|
|
if (MODE_CPHA(Mode)) {
|
|
fastDigitalWrite(SckPin, !MODE_CPOL(Mode));
|
|
}
|
|
fastDigitalWrite(MosiPin, txData & (1 << bit));
|
|
fastDigitalWrite(SckPin,
|
|
MODE_CPHA(Mode) ? MODE_CPOL(Mode) : !MODE_CPOL(Mode));
|
|
if (fastDigitalRead(MisoPin)) {
|
|
*rxData |= 1 << bit;
|
|
}
|
|
if (!MODE_CPHA(Mode)) {
|
|
fastDigitalWrite(SckPin, MODE_CPOL(Mode));
|
|
}
|
|
}
|
|
//----------------------------------------------------------------------------
|
|
};
|
|
#endif // SoftSPI_h
|
|
/** @} */
|