#ifndef SOFTSPI_H #define SOFTSPI_H //#include "IO.h" #include "../Platforms.h" #if (PLATFORM == NODE_MCU) || (PLATFORM == WEMOS_D1_MINI) #include "fastGPIO.h" #define SPI_CS_OUTPUT GPIO15_OUTPUT_SET #define SPI_MOSI_OUTPUT GPIO13_OUTPUT_SET #define SPI_MISO_INPUT GPIO12_INPUT_SET #define SPI_MISO_NO_PULLUP GPIO12_INPUT_PULLUP_UNSET #define SPI_CLK_OUTPUT GPIO14_OUTPUT_SET #define SPI_CS_LO GPIO15_L #define SPI_CS_HI GPIO15_H #define SPI_CLK_LO GPIO14_L #define SPI_CLK_HI GPIO14_H #define SPI_MOSI_LO GPIO13_L #define SPI_MOSI_HI GPIO13_H #define SPI_MISO_READ GPIO12_IN #define SPI_FAST #elif (PLATFORM == NODE32S) #define SPI_CS_OUTPUT GPIO15_OUTPUT_SET #define SPI_MOSI_OUTPUT GPIO13_OUTPUT_SET #define SPI_MISO_INPUT GPIO12_INPUT_SET #define SPI_MISO_NO_PULLUP GPIO12_INPUT_PULLUP_UNSET #define SPI_CLK_OUTPUT GPIO14_OUTPUT_SET #define SPI_CS_LO GPIO15_L #define SPI_CS_HI GPIO15_H #define SPI_CLK_LO GPIO14_L #define SPI_CLK_HI GPIO14_H #define SPI_MOSI_LO GPIO13_L #define SPI_MOSI_HI GPIO13_H #define SPI_MISO_READ GPIO12_IN #define SPI_FAST #endif namespace spi { // MTDI GPIO12 MISO (DIN) D6 // MTCK GPIO13 MOSI (DOUT) D7 // MTMS GPIO14 CLOCK D5 // MTDO GPIO15 CS / SS D8 // #define PIN_CLK 14 // #define PIN_MISO 12 // #define PIN_MOSI 13 // #define BIT(nr) (1 << 0) //public: // SoftSPI() { // // NOT CALLED! // // CALL INIT() manually! // } // THINGS THAT SHOULD RUN FAST AND THUS BE KEPT IN RAM static inline void csLo() { SPI_CS_LO; } // D8 static inline void csHi() { SPI_CS_HI; } // D8 static inline void clkLo() { SPI_CLK_LO; } // D5 static inline void clkHi() { SPI_CLK_HI; } // D5 static inline bool getMISO() {return SPI_MISO_READ;} // D6 #ifdef SPI_FAST static inline void wait() { __asm__ __volatile__("nop"); } static inline void waitLong() { os_delay_us(1); } #else static inline void wait() { os_delay_us(2); } static inline void waitLong() { os_delay_us(50); } #endif static void chipSelect() { clkLo(); wait(); csLo(); waitLong(); } static void chipDeselect() { clkLo(); wait(); csHi(); wait(); } static inline uint8_t readWriteBit(const bool out) { if(out) {SPI_MOSI_HI;} else {SPI_MOSI_LO;} wait(); clkHi(); wait(); const bool inp = getMISO(); wait(); clkLo(); wait(); return (inp) ? 1 : 0; } /** write one bit to the bus */ static inline void writeBit(const bool out) { if(out) {SPI_MOSI_HI;} else {SPI_MOSI_LO;} wait(); clkHi(); wait(); clkLo(); wait(); } /** read one bit from the bus */ static inline uint8_t readBit() { clkHi(); wait(); const bool val = getMISO(); wait(); clkLo(); wait(); return (val) ? 1 : 0; } // THINGS THAT MAY RUN SLOWER FROM THE FLASH static void ICACHE_FLASH_ATTR init() { SPI_MISO_INPUT; SPI_MISO_NO_PULLUP; // D6: MISO SPI_MOSI_OUTPUT; // D7: MOSI SPI_CLK_OUTPUT; // D5: CLK SPI_CS_OUTPUT; // D8: CS } /** read 16 bits */ static uint16_t ICACHE_FLASH_ATTR readWord() { return (readBit() << 15) | (readBit() << 14) | (readBit() << 13) | (readBit() << 12) | (readBit() << 11) | (readBit() << 10) | (readBit() << 9) | (readBit() << 8) | (readBit() << 7) | (readBit() << 6) | (readBit() << 5) | (readBit() << 4) | (readBit() << 3) | (readBit() << 2) | (readBit() << 1) | (readBit() << 0); } /** read 8 bits */ static uint8_t ICACHE_FLASH_ATTR readByte() { return (readBit() << 7) | (readBit() << 6) | (readBit() << 5) | (readBit() << 4) | (readBit() << 3) | (readBit() << 2) | (readBit() << 1) | (readBit() << 0); } static void ICACHE_FLASH_ATTR writeWord(const uint16_t word) { writeBit(word & BIT(15)); writeBit(word & BIT(14)); writeBit(word & BIT(13)); writeBit(word & BIT(12)); writeBit(word & BIT(11)); writeBit(word & BIT(10)); writeBit(word & BIT( 9)); writeBit(word & BIT( 8)); writeBit(word & BIT( 7)); writeBit(word & BIT( 6)); writeBit(word & BIT( 5)); writeBit(word & BIT( 4)); writeBit(word & BIT( 3)); writeBit(word & BIT( 2)); writeBit(word & BIT( 1)); writeBit(word & BIT( 0)); } static void ICACHE_FLASH_ATTR writeByte(const 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)); } static uint16 ICACHE_FLASH_ATTR readWriteWord(const uint16_t word) { return (readWriteBit(word & BIT(15)) << 15) | (readWriteBit(word & BIT(14)) << 14) | (readWriteBit(word & BIT(13)) << 13) | (readWriteBit(word & BIT(12)) << 12) | (readWriteBit(word & BIT(11)) << 11) | (readWriteBit(word & BIT(10)) << 10) | (readWriteBit(word & BIT( 9)) << 9) | (readWriteBit(word & BIT( 8)) << 8) | (readWriteBit(word & BIT( 7)) << 7) | (readWriteBit(word & BIT( 6)) << 6) | (readWriteBit(word & BIT( 5)) << 5) | (readWriteBit(word & BIT( 4)) << 4) | (readWriteBit(word & BIT( 3)) << 3) | (readWriteBit(word & BIT( 2)) << 2) | (readWriteBit(word & BIT( 1)) << 1) | (readWriteBit(word & BIT( 0)) << 0); } static uint8 ICACHE_FLASH_ATTR 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); } } // create an instance ONCE //SoftSPI spi; //using spi = SoftSPI; #endif // SOFTSPI_H