241 lines
5.1 KiB
C++
241 lines
5.1 KiB
C++
#ifndef SOFTSPI_H
|
|
#define SOFTSPI_H
|
|
|
|
//#include "IO.h"
|
|
#include "fastGPIO.h"
|
|
|
|
// wemos D1 mini
|
|
#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
|
|
|
|
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
|