-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
482 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
|
||
#ifndef __TurboSPI_h__ | ||
#define __TurboSPI_h__ | ||
|
||
#include <Arduino.h> | ||
|
||
class TurboSPI | ||
{ | ||
public: | ||
/** Initialize the SPI bus */ | ||
void Begin(); | ||
/** Set SPI options. | ||
* | ||
* \param[in] divisor SCK clock divider relative to the system clock. | ||
*/ | ||
void Init(uint8_t divisor); | ||
/** Receive a byte. | ||
* | ||
* \return The byte. | ||
*/ | ||
uint8_t Receive(); | ||
/** Receive multiple bytes. | ||
* | ||
* \param[out] buf Buffer to receive the data. | ||
* \param[in] n Number of bytes to receive. | ||
* | ||
* \return Zero for no error or nonzero error code. | ||
*/ | ||
uint8_t Receive(uint8_t* buf, size_t n); | ||
/** Send a byte. | ||
* | ||
* \param[in] data Byte to send | ||
*/ | ||
void Send(uint8_t data); | ||
/** Send multiple bytes. | ||
* | ||
* \param[in] buf Buffer for data to be sent. | ||
* \param[in] n Number of bytes to send. | ||
*/ | ||
void Send(const uint8_t* buf, size_t n); | ||
}; | ||
|
||
class DigitalPin | ||
{ | ||
public: | ||
DigitalPin(); | ||
|
||
void Begin(uint8_t pinID); | ||
void PinMode(uint8_t dwMode); | ||
|
||
void High(); | ||
void Low(); | ||
|
||
private: | ||
uint8_t m_Pin; | ||
#if defined(__SAM3X8E__) || defined(__SAM3X8H__) | ||
Pio *m_Port; | ||
uint32_t m_Mask; | ||
#elif defined(__AVR__) | ||
volatile uint8_t *m_Port; | ||
uint8_t m_Mask; | ||
#endif | ||
}; | ||
|
||
#endif // __TurboSPI_h__ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
|
||
#include "TurboSPI.h" | ||
|
||
#ifdef __AVR__ | ||
//------------------------------------------------------------------------------ | ||
void TurboSPI::Begin() | ||
{ | ||
#ifdef __AVR_ATmega328P__ | ||
// Save a few bytes for 328 CPU - gcc optimizes single bit '|' to sbi. | ||
PORTB |= 1 << 2; // SS high | ||
DDRB |= 1 << 2; // SS output mode | ||
DDRB |= 1 << 3; // MOSI output mode | ||
DDRB |= 1 << 5; // SCK output mode | ||
#else // __AVR_ATmega328P__ | ||
|
||
// set SS high - may be chip select for another SPI device | ||
digitalWrite(SS, HIGH); | ||
|
||
// SS must be in output mode even it is not chip select | ||
pinMode(SS, OUTPUT); | ||
pinMode(MOSI, OUTPUT); | ||
pinMode(SCK, OUTPUT); | ||
#endif // __AVR_ATmega328P__ | ||
} | ||
//------------------------------------------------------------------------------ | ||
void TurboSPI::Init(uint8_t divisor) | ||
{ | ||
uint8_t b = 2; | ||
uint8_t r = 0; | ||
|
||
// See AVR processor documentation. | ||
for (; divisor > b && r < 7; b <<= 1, r += r < 5 ? 1 : 2) | ||
{ | ||
} | ||
SPCR = (1 << SPE) | (1 << MSTR) | (r >> 1); | ||
SPSR = r & 1 ? 0 : 1 << SPI2X; | ||
} | ||
//------------------------------------------------------------------------------ | ||
uint8_t TurboSPI::Receive() | ||
{ | ||
SPDR = 0XFF; | ||
while (!(SPSR & (1 << SPIF))) | ||
; | ||
return SPDR; | ||
} | ||
//------------------------------------------------------------------------------ | ||
uint8_t TurboSPI::Receive(uint8_t* buf, size_t n) | ||
{ | ||
if (n-- == 0) | ||
{ | ||
return 0; | ||
} | ||
SPDR = 0XFF; | ||
for (size_t i = 0; i < n; i++) | ||
{ | ||
while (!(SPSR & (1 << SPIF))) | ||
; | ||
uint8_t b = SPDR; | ||
SPDR = 0XFF; | ||
buf[i] = b; | ||
} | ||
while (!(SPSR & (1 << SPIF))) | ||
; | ||
buf[n] = SPDR; | ||
return 0; | ||
} | ||
//------------------------------------------------------------------------------ | ||
void TurboSPI::Send(uint8_t data) | ||
{ | ||
SPDR = data; | ||
while (!(SPSR & (1 << SPIF))) | ||
; | ||
} | ||
//------------------------------------------------------------------------------ | ||
void TurboSPI::Send(const uint8_t* buf, size_t n) | ||
{ | ||
if (n == 0) | ||
{ | ||
return; | ||
} | ||
SPDR = buf[0]; | ||
if (n > 1) | ||
{ | ||
uint8_t b = buf[1]; | ||
size_t i = 2; | ||
while (1) | ||
{ | ||
while (!(SPSR & (1 << SPIF))) | ||
; | ||
SPDR = b; | ||
if (i == n) | ||
{ | ||
break; | ||
} | ||
b = buf[i++]; | ||
} | ||
} | ||
while (!(SPSR & (1 << SPIF))) | ||
; | ||
} | ||
|
||
////////////////////////////////////////////////////////////////////////// | ||
DigitalPin::DigitalPin() | ||
: m_Pin(0) | ||
, m_Port(0) | ||
, m_Mask(0) | ||
{ | ||
} | ||
|
||
void DigitalPin::Begin(uint8_t pinID) | ||
{ | ||
m_Pin = pinID; | ||
m_Port = portOutputRegister(digitalPinToPort(pinID)); | ||
m_Mask = digitalPinToBitMask(pinID); | ||
} | ||
|
||
void DigitalPin::PinMode(uint8_t dwMode) | ||
{ | ||
pinMode(m_Pin, dwMode); | ||
} | ||
|
||
void DigitalPin::High() | ||
{ | ||
*m_Port |= m_Mask; | ||
} | ||
|
||
void DigitalPin::Low() | ||
{ | ||
*m_Port &= ~m_Mask; | ||
} | ||
|
||
#endif // __AVR__ |
Oops, something went wrong.