diff --git a/SampleProjects/TestSomething/test/defines.cpp b/SampleProjects/TestSomething/test/defines.cpp index 6b09d851..c0f43344 100644 --- a/SampleProjects/TestSomething/test/defines.cpp +++ b/SampleProjects/TestSomething/test/defines.cpp @@ -8,4 +8,26 @@ unittest(binary) assertEqual(100, B1100100); } +#ifdef __AVR__ +#define DDRE _SFR_IO8(0x02) + + unittest(SFR_IO8) + { + // in normal arduino code, you can do this. in arduino_ci, you might get an + // error like: cannot take the address of an rvalue of type 'int' + // + // this tests that directly + auto foo = &DDRE; // avoid compiler warning by using the result of an expression + } + +unittest(read_write) +{ + _SFR_IO8(1) = 0x11; + _SFR_IO8(2) = 0x22; + assertEqual((int) 0x11, (int) _SFR_IO8(1)); + assertEqual((int) 0x22, (int) _SFR_IO8(2)); + assertEqual((int) 0x2211, (int) _SFR_IO16(1)); +} +#endif + unittest_main() diff --git a/SampleProjects/TestSomething/test/godmode.cpp b/SampleProjects/TestSomething/test/godmode.cpp index e6c69502..d9ab6716 100644 --- a/SampleProjects/TestSomething/test/godmode.cpp +++ b/SampleProjects/TestSomething/test/godmode.cpp @@ -175,18 +175,35 @@ unittest(spi) { // 8-bit state->reset(); state->spi.dataIn = "LMNO"; + SPI.beginTransaction(SPISettings(14000000, LSBFIRST, SPI_MODE0)); uint8_t out8 = SPI.transfer('a'); + SPI.endTransaction(); assertEqual("a", state->spi.dataOut); assertEqual('L', out8); assertEqual("MNO", state->spi.dataIn); - // 16-bit + // 16-bit MSBFIRST union { uint16_t val; struct { char lsb; char msb; }; } in16, out16; state->reset(); state->spi.dataIn = "LMNO"; in16.lsb = 'a'; in16.msb = 'b'; + SPI.beginTransaction(SPISettings(14000000, MSBFIRST, SPI_MODE0)); out16.val = SPI.transfer16(in16.val); + SPI.endTransaction(); + assertEqual("NO", state->spi.dataIn); + assertEqual('M', out16.lsb); + assertEqual('L', out16.msb); + assertEqual("ba", state->spi.dataOut); + + // 16-bit LSBFIRST + state->reset(); + state->spi.dataIn = "LMNO"; + in16.lsb = 'a'; + in16.msb = 'b'; + SPI.beginTransaction(SPISettings(14000000, LSBFIRST, SPI_MODE0)); + out16.val = SPI.transfer16(in16.val); + SPI.endTransaction(); assertEqual("NO", state->spi.dataIn); assertEqual('L', out16.lsb); assertEqual('M', out16.msb); @@ -196,7 +213,9 @@ unittest(spi) { state->reset(); state->spi.dataIn = "LMNOP"; char inBuf[6] = "abcde"; + SPI.beginTransaction(SPISettings(14000000, LSBFIRST, SPI_MODE0)); SPI.transfer(inBuf, 4); + SPI.endTransaction(); assertEqual("abcd", state->spi.dataOut); assertEqual("LMNOe", String(inBuf)); diff --git a/cpp/arduino/Godmode.cpp b/cpp/arduino/Godmode.cpp index 102afca6..36f44cfd 100644 --- a/cpp/arduino/Godmode.cpp +++ b/cpp/arduino/Godmode.cpp @@ -113,3 +113,5 @@ SPIClass SPI = SPIClass(&GODMODE()->spi.dataIn, &GODMODE()->spi.dataOut); // defined in Wire.h TwoWire Wire = TwoWire(); + +volatile uint8_t __ARDUINO_CI_SFR_MOCK[1024]; diff --git a/cpp/arduino/SPI.h b/cpp/arduino/SPI.h index f10cd201..15cfdf31 100644 --- a/cpp/arduino/SPI.h +++ b/cpp/arduino/SPI.h @@ -40,7 +40,10 @@ class SPISettings { public: - SPISettings(uint32_t clock, uint8_t bitOrder, uint8_t dataMode){}; + uint8_t bitOrder; + SPISettings(uint32_t clock, uint8_t bitOrder = MSBFIRST, uint8_t dataMode = SPI_MODE0){ + this->bitOrder = bitOrder; + }; SPISettings(){}; }; @@ -68,6 +71,7 @@ class SPIClass: public ObservableDataStream { // and configure the correct settings. void beginTransaction(SPISettings settings) { + this->bitOrder = settings.bitOrder; #ifdef SPI_TRANSACTION_MISMATCH_LED if (inTransactionFlag) { pinMode(SPI_TRANSACTION_MISMATCH_LED, OUTPUT); @@ -94,7 +98,7 @@ class SPIClass: public ObservableDataStream { uint16_t transfer16(uint16_t data) { union { uint16_t val; struct { uint8_t lsb; uint8_t msb; }; } in, out; in.val = data; - if (!(SPCR & (1 << DORD))) { + if (bitOrder == MSBFIRST) { out.msb = transfer(in.msb); out.lsb = transfer(in.lsb); } else { @@ -143,6 +147,7 @@ class SPIClass: public ObservableDataStream { #endif bool isStarted = false; + uint8_t bitOrder; String* dataIn; String* dataOut; }; diff --git a/cpp/arduino/avr/io.h b/cpp/arduino/avr/io.h index f07699a0..41c9811b 100644 --- a/cpp/arduino/avr/io.h +++ b/cpp/arduino/avr/io.h @@ -96,7 +96,15 @@ #ifndef _AVR_IO_H_ #define _AVR_IO_H_ -#define _SFR_IO8(io_addr) (io_addr) // this macro is all we need from the sfr file +#include + +// hardware mocks +extern volatile uint8_t __ARDUINO_CI_SFR_MOCK[1024]; +#define _SFR_IO8(io_addr) (*(volatile uint8_t *)(__ARDUINO_CI_SFR_MOCK + io_addr)) // this macro is all we need from the sfr file +#define _SFR_IO16(io_addr) (*(volatile uint16_t *)(__ARDUINO_CI_SFR_MOCK + io_addr)) // this macro is all we need from the sfr file +#define _SFR_MEM8(io_addr) (*(volatile uint8_t *)(__ARDUINO_CI_SFR_MOCK + io_addr)) // this macro is all we need from the sfr file +#define _SFR_MEM16(io_addr) (*(volatile uint16_t *)(__ARDUINO_CI_SFR_MOCK + io_addr)) // this macro is all we need from the sfr file +#define _SFR_MEM32(io_addr) (*(volatile uint32_t *)(__ARDUINO_CI_SFR_MOCK + io_addr)) // this macro is all we need from the sfr file #if defined (__AVR_AT94K__) # include "ioat94k.h"