aboutsummaryrefslogtreecommitdiff
path: root/libraries/SPI/SPI.cpp
diff options
context:
space:
mode:
authorPaulStoffregen <paul@pjrc.com>2014-08-01 05:38:27 -0700
committerPaulStoffregen <paul@pjrc.com>2014-08-01 05:38:27 -0700
commit48f5256789369bd5a4d8d9b9a663982aea717c7d (patch)
tree62f016b657c81b94e25ebc6fbfba971c8b9fff0c /libraries/SPI/SPI.cpp
parente057236dd6d37e80afe8345111e16df12832143d (diff)
SPI Transactions for AVR
Diffstat (limited to 'libraries/SPI/SPI.cpp')
-rw-r--r--libraries/SPI/SPI.cpp102
1 files changed, 84 insertions, 18 deletions
diff --git a/libraries/SPI/SPI.cpp b/libraries/SPI/SPI.cpp
index 5e48073..9a7a400 100644
--- a/libraries/SPI/SPI.cpp
+++ b/libraries/SPI/SPI.cpp
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2010 by Cristian Maglie <c.maglie@bug.st>
+ * Copyright (c) 2014 by Paul Stoffregen <paul@pjrc.com> (Transaction API)
* SPI Master library for arduino.
*
* This file is free software; you can redistribute it and/or modify
@@ -8,13 +9,20 @@
* published by the Free Software Foundation.
*/
-#include "pins_arduino.h"
#include "SPI.h"
+#include "pins_arduino.h"
SPIClass SPI;
-void SPIClass::begin() {
+uint8_t SPIClass::interruptMode = 0;
+uint8_t SPIClass::interruptMask = 0;
+uint8_t SPIClass::interruptSave = 0;
+#ifdef SPI_TRANSACTION_MISMATCH_LED
+uint8_t SPIClass::inTransactionFlag = 0;
+#endif
+void SPIClass::begin()
+{
// Set SS to high so a connected chip will be "deselected" by default
digitalWrite(SS, HIGH);
@@ -39,28 +47,86 @@ void SPIClass::begin() {
pinMode(MOSI, OUTPUT);
}
-
void SPIClass::end() {
SPCR &= ~_BV(SPE);
}
-void SPIClass::setBitOrder(uint8_t bitOrder)
-{
- if(bitOrder == LSBFIRST) {
- SPCR |= _BV(DORD);
- } else {
- SPCR &= ~(_BV(DORD));
- }
-}
+// mapping of interrupt numbers to bits within SPI_AVR_EIMSK
+#if defined(__AVR_ATmega32U4__)
+ #define SPI_INT0_MASK (1<<INT0)
+ #define SPI_INT1_MASK (1<<INT1)
+ #define SPI_INT2_MASK (1<<INT2)
+ #define SPI_INT3_MASK (1<<INT3)
+ #define SPI_INT4_MASK (1<<INT6)
+#elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)
+ #define SPI_INT0_MASK (1<<INT0)
+ #define SPI_INT1_MASK (1<<INT1)
+ #define SPI_INT2_MASK (1<<INT2)
+ #define SPI_INT3_MASK (1<<INT3)
+ #define SPI_INT4_MASK (1<<INT4)
+ #define SPI_INT5_MASK (1<<INT5)
+ #define SPI_INT6_MASK (1<<INT6)
+ #define SPI_INT7_MASK (1<<INT7)
+#elif defined(EICRA) && defined(EICRB) && defined(EIMSK)
+ #define SPI_INT0_MASK (1<<INT4)
+ #define SPI_INT1_MASK (1<<INT5)
+ #define SPI_INT2_MASK (1<<INT0)
+ #define SPI_INT3_MASK (1<<INT1)
+ #define SPI_INT4_MASK (1<<INT2)
+ #define SPI_INT5_MASK (1<<INT3)
+ #define SPI_INT6_MASK (1<<INT6)
+ #define SPI_INT7_MASK (1<<INT7)
+#else
+ #ifdef INT0
+ #define SPI_INT0_MASK (1<<INT0)
+ #endif
+ #ifdef INT1
+ #define SPI_INT1_MASK (1<<INT1)
+ #endif
+ #ifdef INT2
+ #define SPI_INT2_MASK (1<<INT2)
+ #endif
+#endif
-void SPIClass::setDataMode(uint8_t mode)
+void SPIClass::usingInterrupt(uint8_t interruptNumber)
{
- SPCR = (SPCR & ~SPI_MODE_MASK) | mode;
-}
+ uint8_t mask;
-void SPIClass::setClockDivider(uint8_t rate)
-{
- SPCR = (SPCR & ~SPI_CLOCK_MASK) | (rate & SPI_CLOCK_MASK);
- SPSR = (SPSR & ~SPI_2XCLOCK_MASK) | ((rate >> 2) & SPI_2XCLOCK_MASK);
+ if (interruptMode > 1) return;
+
+ noInterrupts();
+ switch (interruptNumber) {
+ #ifdef SPI_INT0_MASK
+ case 0: mask = SPI_INT0_MASK; break;
+ #endif
+ #ifdef SPI_INT1_MASK
+ case 1: mask = SPI_INT1_MASK; break;
+ #endif
+ #ifdef SPI_INT2_MASK
+ case 2: mask = SPI_INT2_MASK; break;
+ #endif
+ #ifdef SPI_INT3_MASK
+ case 3: mask = SPI_INT3_MASK; break;
+ #endif
+ #ifdef SPI_INT4_MASK
+ case 4: mask = SPI_INT4_MASK; break;
+ #endif
+ #ifdef SPI_INT5_MASK
+ case 5: mask = SPI_INT5_MASK; break;
+ #endif
+ #ifdef SPI_INT6_MASK
+ case 6: mask = SPI_INT6_MASK; break;
+ #endif
+ #ifdef SPI_INT7_MASK
+ case 7: mask = SPI_INT7_MASK; break;
+ #endif
+ default:
+ interruptMode = 2;
+ interrupts();
+ return;
+ }
+ interruptMode = 1;
+ interruptMask |= mask;
+ interrupts();
}