13 #ifndef _SPI_H_INCLUDED
14 #define _SPI_H_INCLUDED
20 #define SPI_HAS_TRANSACTION 1
35 #define SPI_CLOCK_DIV4 0x00
36 #define SPI_CLOCK_DIV16 0x01
37 #define SPI_CLOCK_DIV64 0x02
38 #define SPI_CLOCK_DIV128 0x03
39 #define SPI_CLOCK_DIV2 0x04
40 #define SPI_CLOCK_DIV8 0x05
41 #define SPI_CLOCK_DIV32 0x06
43 #define SPI_MODE0 0x00
44 #define SPI_MODE1 0x04
45 #define SPI_MODE2 0x08
46 #define SPI_MODE3 0x0C
48 #define SPI_MODE_MASK 0x0C // CPOL = bit 3, CPHA = bit 2 on SPCR
49 #define SPI_CLOCK_MASK 0x03 // SPR1 = bit 1, SPR0 = bit 0 on SPCR
50 #define SPI_2XCLOCK_MASK 0x01 // SPI2X = bit 0 on SPSR
54 #define SPI_AVR_EIMSK EIMSK
56 #define SPI_AVR_EIMSK GICR
58 #define SPI_AVR_EIMSK GIMSK
63 SPISettings(uint32_t clock, uint8_t bitOrder, uint8_t dataMode) {
64 if (__builtin_constant_p(clock)) {
65 init_AlwaysInline(clock, bitOrder, dataMode);
67 init_MightInline(clock, bitOrder, dataMode);
71 init_AlwaysInline(4000000, MSBFIRST, SPI_MODE0);
74 void init_MightInline(uint32_t clock, uint8_t bitOrder, uint8_t dataMode) {
75 init_AlwaysInline(clock, bitOrder, dataMode);
77 void init_AlwaysInline(uint32_t clock, uint8_t bitOrder, uint8_t dataMode)
78 __attribute__((__always_inline__)) {
102 if (__builtin_constant_p(clock)) {
103 if (clock >= F_CPU / 2) {
105 }
else if (clock >= F_CPU / 4) {
107 }
else if (clock >= F_CPU / 8) {
109 }
else if (clock >= F_CPU / 16) {
111 }
else if (clock >= F_CPU / 32) {
113 }
else if (clock >= F_CPU / 64) {
119 uint32_t clockSetting = F_CPU / 2;
121 while (clockDiv < 6 && clock < clockSetting) {
135 spcr = _BV(SPE) | _BV(MSTR) | ((bitOrder == LSBFIRST) ? _BV(DORD) : 0) |
136 (dataMode & SPI_MODE_MASK) | ((clockDiv >> 1) & SPI_CLOCK_MASK);
137 spsr = clockDiv & SPI_2XCLOCK_MASK;
155 static void usingInterrupt(uint8_t interruptNumber);
160 inline static void beginTransaction(
SPISettings settings) {
161 if (interruptMode > 0) {
163 if (interruptMode == 1) {
164 interruptSave = SPI_AVR_EIMSK;
165 SPI_AVR_EIMSK &= ~interruptMask;
169 interruptSave = SREG;
173 #ifdef SPI_TRANSACTION_MISMATCH_LED
174 if (inTransactionFlag) {
175 pinMode(SPI_TRANSACTION_MISMATCH_LED, OUTPUT);
176 digitalWrite(SPI_TRANSACTION_MISMATCH_LED, HIGH);
178 inTransactionFlag = 1;
180 SPCR = settings.spcr;
181 SPSR = settings.spsr;
185 inline static uint8_t transfer(uint8_t data) {
188 while (!(SPSR & _BV(SPIF))) ;
191 inline static uint16_t transfer16(uint16_t data) {
192 union { uint16_t val;
struct { uint8_t lsb; uint8_t msb; }; } in, out;
194 if (!(SPCR & _BV(DORD))) {
196 while (!(SPSR & _BV(SPIF))) ;
199 while (!(SPSR & _BV(SPIF))) ;
203 while (!(SPSR & _BV(SPIF))) ;
206 while (!(SPSR & _BV(SPIF))) ;
211 inline static void transfer(
void *buf,
size_t count) {
212 if (count == 0)
return;
213 uint8_t *p = (uint8_t *)buf;
215 while (--count > 0) {
216 uint8_t out = *(p + 1);
217 while (!(SPSR & _BV(SPIF))) ;
222 while (!(SPSR & _BV(SPIF))) ;
227 inline static void endTransaction(
void) {
228 #ifdef SPI_TRANSACTION_MISMATCH_LED
229 if (!inTransactionFlag) {
230 pinMode(SPI_TRANSACTION_MISMATCH_LED, OUTPUT);
231 digitalWrite(SPI_TRANSACTION_MISMATCH_LED, HIGH);
233 inTransactionFlag = 0;
235 if (interruptMode > 0) {
237 if (interruptMode == 1) {
238 SPI_AVR_EIMSK = interruptSave;
242 SREG = interruptSave;
252 inline static void setBitOrder(uint8_t bitOrder) {
253 if (bitOrder == LSBFIRST) SPCR |= _BV(DORD);
254 else SPCR &= ~(_BV(DORD));
258 inline static void setDataMode(uint8_t dataMode) {
259 SPCR = (SPCR & ~SPI_MODE_MASK) | dataMode;
263 inline static void setClockDivider(uint8_t clockDiv) {
264 SPCR = (SPCR & ~SPI_CLOCK_MASK) | (clockDiv & SPI_CLOCK_MASK);
265 SPSR = (SPSR & ~SPI_2XCLOCK_MASK) | ((clockDiv >> 2) & SPI_2XCLOCK_MASK);
270 inline static void attachInterrupt() { SPCR |= _BV(SPIE); }
271 inline static void detachInterrupt() { SPCR &= ~_BV(SPIE); }
274 static uint8_t interruptMode;
275 static uint8_t interruptMask;
276 static uint8_t interruptSave;
277 #ifdef SPI_TRANSACTION_MISMATCH_LED
278 static uint8_t inTransactionFlag;