#ifndef SOFTSPI_H #define SOFTSPI_H #include "GPIO.h" #include "../Platforms.h" #include "../Debug.h" #pragma GCC push_options #pragma GCC optimize ("O3") // NOTE: the last template argument has changed from "bool fast" to "int slowdown" where 0 is now fastest! template class SoftSPI { static constexpr const char* NAME = "softSPI"; #ifndef BIT #define BIT(x) (1<>24)&0xFF); writeByte((quad>>16)&0xFF); writeByte((quad>> 8)&0xFF); writeByte((quad>> 0)&0xFF); } void IRAM_ATTR writeWord(const uint16_t word) { writeByte((word>>8)&0xFF); writeByte((word>>0)&0xFF); } inline void IRAM_ATTR writeByte(uint8_t byte) { writeBit(byte & BIT( 7)); writeBit(byte & BIT( 6)); writeBit(byte & BIT( 5)); writeBit(byte & BIT( 4)); writeBit(byte & BIT( 3)); writeBit(byte & BIT( 2)); writeBit(byte & BIT( 1)); writeBit(byte & BIT( 0)); } /** read 8 bits */ uint8_t readByte() { MyGPIO::clear(PIN_MOSI); return (readBit() << 7) | (readBit() << 6) | (readBit() << 5) | (readBit() << 4) | (readBit() << 3) | (readBit() << 2) | (readBit() << 1) | (readBit() << 0); } uint8_t readWriteByte(const uint8_t byte) { return (readWriteBit(byte & BIT( 7)) << 7) | (readWriteBit(byte & BIT( 6)) << 6) | (readWriteBit(byte & BIT( 5)) << 5) | (readWriteBit(byte & BIT( 4)) << 4) | (readWriteBit(byte & BIT( 3)) << 3) | (readWriteBit(byte & BIT( 2)) << 2) | (readWriteBit(byte & BIT( 1)) << 1) | (readWriteBit(byte & BIT( 0)) << 0); } uint32_t readWriteQuad(const uint32_t quad) { return readWriteByte((quad>>24)&0xFF) << 24 | readWriteByte((quad>>16)&0xFF) << 16 | readWriteByte((quad>> 8)&0xFF) << 8 | readWriteByte((quad>> 0)&0xFF) << 0; } void write(const uint8_t* data, size_t len) { while(len) { writeByte(*data); ++data; --len; } } void read(uint8_t* dst, size_t len) { while(len) { *dst = readByte(); ++dst; --len; } } }; #pragma GCC pop_options // create an instance ONCE //SoftSPI spi; //using spi = SoftSPI; #endif // SOFTSPI_H