many updates..
new sensors.. display.. led.. drawing.. stuff..
This commit is contained in:
122
io/GPIO.h
Normal file
122
io/GPIO.h
Normal file
@@ -0,0 +1,122 @@
|
||||
#ifndef ESP_LIB_GPIO_H
|
||||
#define ESP_LIB_GPIO_H
|
||||
|
||||
#include "../Platforms.h"
|
||||
|
||||
|
||||
#if ESP8266
|
||||
|
||||
#include "fastGPIO.h"
|
||||
|
||||
struct GPIO {
|
||||
|
||||
static inline bool get(const uint8_t num) {
|
||||
return GPIO_INPUT_GET(num);
|
||||
}
|
||||
|
||||
static inline void set(const uint8_t num) {
|
||||
GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, 1 << num);
|
||||
}
|
||||
|
||||
static inline void clear(const uint8_t num) {
|
||||
GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, 1 << num);
|
||||
}
|
||||
|
||||
static inline void setOutput(const uint8_t num) {
|
||||
switch(num) {
|
||||
case 0: GPIO0_OUTPUT_SET; break;
|
||||
case 1: GPIO1_OUTPUT_SET; break;
|
||||
case 2: GPIO2_OUTPUT_SET; break;
|
||||
case 3: GPIO3_OUTPUT_SET; break;
|
||||
case 4: GPIO4_OUTPUT_SET; break;
|
||||
case 5: GPIO5_OUTPUT_SET; break;
|
||||
//case 6: GPIO6_OUTPUT_SET; break;
|
||||
//case 7: GPIO7_OUTPUT_SET; break;
|
||||
//case 8: GPIO8_OUTPUT_SET; break;
|
||||
case 9: GPIO9_OUTPUT_SET; break;
|
||||
case 10: GPIO10_OUTPUT_SET; break;
|
||||
//case 11: GPIO11_OUTPUT_SET; break;
|
||||
case 12: GPIO12_OUTPUT_SET; break;
|
||||
case 13: GPIO13_OUTPUT_SET; break;
|
||||
case 14: GPIO14_OUTPUT_SET; break;
|
||||
case 15: GPIO15_OUTPUT_SET; break;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void setInput(const uint8_t num) {
|
||||
switch(num) {
|
||||
case 0: GPIO0_INPUT_SET; break;
|
||||
case 1: GPIO1_INPUT_SET; break;
|
||||
case 2: GPIO2_INPUT_SET; break;
|
||||
case 3: GPIO3_INPUT_SET; break;
|
||||
case 4: GPIO4_INPUT_SET; break;
|
||||
case 5: GPIO5_INPUT_SET; break;
|
||||
//case 6: GPIO6_INPUT_SET; break;
|
||||
//case 7: GPIO7_INPUT_SET; break;
|
||||
//case 8: GPIO8_INPUT_SET; break;
|
||||
case 9: GPIO9_INPUT_SET; break;
|
||||
case 10: GPIO10_INPUT_SET; break;
|
||||
//case 11: GPIO11_INPUT_SET; break;
|
||||
case 12: GPIO12_INPUT_SET; break;
|
||||
case 13: GPIO13_INPUT_SET; break;
|
||||
case 14: GPIO14_INPUT_SET; break;
|
||||
case 15: GPIO15_INPUT_SET; break;
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#elif ESP32
|
||||
|
||||
#include "driver/gpio.h"
|
||||
|
||||
struct MyGPIO {
|
||||
|
||||
static inline bool get(const uint8_t num) {
|
||||
return get((gpio_num_t)num);
|
||||
}
|
||||
static inline bool get(const gpio_num_t num) {
|
||||
return gpio_get_level(num); // TODO faster access like READ_PERI_REG??
|
||||
}
|
||||
|
||||
template <typename T> static inline void setOrClear(const uint8_t num, const T val) {
|
||||
if (val) {set(num);} else {clear(num);}
|
||||
//WRITE_PERI_REG(GPIO_OUT_W1TS_REG, (val != 0) << num); // branchless but usually slower
|
||||
//WRITE_PERI_REG(GPIO_OUT_W1TC_REG, (val == 0) << num);
|
||||
}
|
||||
|
||||
static inline void set(const uint8_t num) {
|
||||
WRITE_PERI_REG(GPIO_OUT_W1TS_REG, 1 << num);
|
||||
}
|
||||
|
||||
static inline void clear(const uint8_t num) {
|
||||
WRITE_PERI_REG(GPIO_OUT_W1TC_REG, 1 << num);
|
||||
}
|
||||
|
||||
static inline void setOutput(const uint8_t num) {
|
||||
setOutput((gpio_num_t)num);
|
||||
}
|
||||
static inline void setOutput(const gpio_num_t num) {
|
||||
gpio_set_direction(num, GPIO_MODE_OUTPUT);
|
||||
}
|
||||
|
||||
static inline void setInput(const uint8_t num) {
|
||||
setInput((gpio_num_t)num);
|
||||
}
|
||||
static inline void setInput(const gpio_num_t num) {
|
||||
gpio_set_direction(num, GPIO_MODE_INPUT);
|
||||
}
|
||||
|
||||
static void toggleBuiltInLED() {
|
||||
static bool level = false;
|
||||
setOutput(GPIO_NUM_2);
|
||||
level = !level;
|
||||
if (level) {set(GPIO_NUM_2);} else {clear(GPIO_NUM_2);}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#endif // ESP_LIB_GPIO_H
|
||||
228
io/HardSPI.h
Normal file
228
io/HardSPI.h
Normal file
@@ -0,0 +1,228 @@
|
||||
#ifndef HARDSPI_H
|
||||
#define HARDSPI_H
|
||||
|
||||
#include "../Debug.h"
|
||||
#include "driver/spi_master.h"
|
||||
#include <cmath>
|
||||
#include <string.h>
|
||||
|
||||
//static spi_transaction_t trans[2];
|
||||
|
||||
#define PIN_NUM_MISO GPIO_NUM_19
|
||||
#define PIN_NUM_MOSI GPIO_NUM_23
|
||||
#define PIN_NUM_CLK GPIO_NUM_18
|
||||
#define PIN_NUM_CS GPIO_NUM_2
|
||||
|
||||
|
||||
template <int PIN_NUM_MISO, int PIN_NUM_MOSI, int PIN_NUM_CLK> class HardSPI {
|
||||
//class HardSPI {
|
||||
|
||||
static constexpr int MAX_LEN = 4000;
|
||||
|
||||
spi_device_handle_t spi;
|
||||
|
||||
spi_bus_config_t buscfg;
|
||||
|
||||
spi_device_interface_config_t devcfg;
|
||||
|
||||
static constexpr const char* TAG = "hwSPI";
|
||||
|
||||
public:
|
||||
|
||||
// can be called before every transmit
|
||||
// static void IRAM_ATTR pre_transfer_callback(spi_transaction_t *t) {
|
||||
// }
|
||||
|
||||
/** ctor */
|
||||
HardSPI() {
|
||||
init();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void init() {
|
||||
|
||||
int ret;
|
||||
|
||||
// BUS specific options
|
||||
memset(&buscfg, 0, sizeof(buscfg));
|
||||
buscfg.miso_io_num = PIN_NUM_MISO;
|
||||
buscfg.mosi_io_num = PIN_NUM_MOSI;
|
||||
buscfg.sclk_io_num = PIN_NUM_CLK;
|
||||
buscfg.quadwp_io_num = -1;
|
||||
buscfg.quadhd_io_num = -1;
|
||||
buscfg.max_transfer_sz = MAX_LEN;//320*240*2;
|
||||
buscfg.flags = 0;
|
||||
buscfg.intr_flags = 0;
|
||||
|
||||
// DEVICE specific options
|
||||
memset(&devcfg, 0, sizeof(devcfg));
|
||||
devcfg.clock_speed_hz = 10 * 1000 * 1000;
|
||||
devcfg.mode = 0;
|
||||
devcfg.spics_io_num = -1;//PIN_NUM_CS; // currently not used
|
||||
devcfg.queue_size = 2;
|
||||
devcfg.pre_cb = nullptr;
|
||||
//devcfg.pre_cb = pre_transfer_callback; // can be called before every transmit
|
||||
|
||||
// Initialize the SPI bus
|
||||
ret = spi_bus_initialize(HSPI_HOST, &buscfg, 1);
|
||||
ESP_ERROR_CHECK(ret);
|
||||
|
||||
// Attach the device to the SPI bus
|
||||
ret = spi_bus_add_device(HSPI_HOST, &devcfg, &spi);
|
||||
ESP_ERROR_CHECK(ret);
|
||||
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/** blocking transmit the given bytes */
|
||||
void write(const uint8_t* data, size_t len) {
|
||||
|
||||
spi_transaction_t t;
|
||||
memset(&t, 0, sizeof(spi_transaction_t));
|
||||
|
||||
while(len > 0) {
|
||||
|
||||
const size_t chunkLen = min(MAX_LEN, (len));
|
||||
t.length = 8 * chunkLen; // in bits
|
||||
t.tx_buffer = data; // MOSI only
|
||||
t.flags = 0;
|
||||
|
||||
// blocking transfer
|
||||
esp_err_t ret = spi_device_polling_transmit(spi, &t);
|
||||
ESP_ERROR_CHECK(ret);
|
||||
|
||||
// update remaining length and data pointer
|
||||
len -= chunkLen;
|
||||
data += chunkLen;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void read(uint8_t* dst, size_t len) {
|
||||
|
||||
// sanity check
|
||||
{
|
||||
const size_t addr = reinterpret_cast<size_t>(dst);
|
||||
if ((addr % 4) != 0) {
|
||||
ESP_LOGE(TAG, "read-buffer must be 32-bit aligned");
|
||||
}
|
||||
}
|
||||
|
||||
spi_transaction_t t;
|
||||
memset(&t, 0, sizeof(spi_transaction_t));
|
||||
|
||||
//debugMod1(TAG, "read %d bytes", len);
|
||||
|
||||
while(len > 0) {
|
||||
|
||||
const size_t chunkLen = min(MAX_LEN, (len));
|
||||
//ESP_LOGI(TAG, "- read %d byte chunk", chunkLen);
|
||||
t.length = 8 * chunkLen; // in bits
|
||||
t.rx_buffer = dst; // MISO only
|
||||
t.flags = 0;
|
||||
|
||||
// blocking transfer
|
||||
esp_err_t ret = spi_device_polling_transmit(spi, &t);
|
||||
ESP_ERROR_CHECK(ret);
|
||||
|
||||
// update remaining length and destination-data pointer
|
||||
len -= chunkLen;
|
||||
dst += chunkLen;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** send 4 bytes onto the bus while reading 4 bytes response */
|
||||
uint32_t readWriteQuad(uint32_t write) {
|
||||
|
||||
spi_transaction_t t;
|
||||
memset(&t, 0, sizeof(spi_transaction_t));
|
||||
t.length = 8*4;
|
||||
t.rxlength = 8*4;
|
||||
t.tx_data[0] = (write >> 24) & 0xFF;
|
||||
t.tx_data[1] = (write >> 16) & 0xFF;
|
||||
t.tx_data[2] = (write >> 8) & 0xFF;
|
||||
t.tx_data[3] = (write >> 0) & 0xFF;
|
||||
t.flags = SPI_TRANS_USE_RXDATA | SPI_TRANS_USE_TXDATA;
|
||||
|
||||
esp_err_t ret = spi_device_polling_transmit(spi, &t);
|
||||
ESP_ERROR_CHECK(ret);
|
||||
|
||||
return
|
||||
(static_cast<uint32_t>(t.rx_data[0]) << 24) |
|
||||
(static_cast<uint32_t>(t.rx_data[1]) << 16) |
|
||||
(static_cast<uint32_t>(t.rx_data[2]) << 8) |
|
||||
(static_cast<uint32_t>(t.rx_data[3]) << 0);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/** read one byte from the bus */
|
||||
uint8_t readByte() {
|
||||
|
||||
spi_transaction_t t;
|
||||
memset(&t, 0, sizeof(spi_transaction_t));
|
||||
t.length = 8*1;
|
||||
t.flags = SPI_TRANS_USE_RXDATA;
|
||||
|
||||
esp_err_t ret = spi_device_polling_transmit(spi, &t);
|
||||
ESP_ERROR_CHECK(ret);
|
||||
|
||||
return t.rx_data[0];
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void writeByte(const uint8_t byte) {
|
||||
|
||||
spi_transaction_t t;
|
||||
memset(&t, 0, sizeof(spi_transaction_t));
|
||||
t.length = 8*1;
|
||||
t.tx_data[0] = byte;
|
||||
t.flags = SPI_TRANS_USE_TXDATA;
|
||||
|
||||
esp_err_t ret = spi_device_polling_transmit(spi, &t);
|
||||
ESP_ERROR_CHECK(ret);
|
||||
|
||||
}
|
||||
|
||||
void writeWord(const uint16_t word) {
|
||||
|
||||
spi_transaction_t t;
|
||||
memset(&t, 0, sizeof(spi_transaction_t));
|
||||
t.length = 8*2;
|
||||
t.tx_data[0] = static_cast<uint8_t>(word>>8);
|
||||
t.tx_data[1] = static_cast<uint8_t>(word>>0);
|
||||
t.flags = SPI_TRANS_USE_TXDATA;
|
||||
|
||||
esp_err_t ret = spi_device_polling_transmit(spi, &t);
|
||||
ESP_ERROR_CHECK(ret);
|
||||
|
||||
}
|
||||
|
||||
void writeQuad(const uint32_t quad) {
|
||||
|
||||
spi_transaction_t t;
|
||||
memset(&t, 0, sizeof(spi_transaction_t));
|
||||
t.length = 8*4;
|
||||
t.tx_data[0] = static_cast<uint8_t>(quad>>24);
|
||||
t.tx_data[1] = static_cast<uint8_t>(quad>>16);
|
||||
t.tx_data[2] = static_cast<uint8_t>(quad>>8);
|
||||
t.tx_data[3] = static_cast<uint8_t>(quad>>0);
|
||||
t.flags = SPI_TRANS_USE_TXDATA;
|
||||
|
||||
esp_err_t ret = spi_device_polling_transmit(spi, &t);
|
||||
ESP_ERROR_CHECK(ret);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif // HARDSPI_H
|
||||
240
io/SoftI2C.h
Normal file
240
io/SoftI2C.h
Normal file
@@ -0,0 +1,240 @@
|
||||
#ifndef SOFTI2C_H
|
||||
#define SOFTI2C_H
|
||||
|
||||
#include "../Platforms.h"
|
||||
#include "../Debug.h"
|
||||
#include "GPIO.h"
|
||||
|
||||
|
||||
#if ESP8266
|
||||
#include "fastGPIO.h"
|
||||
#elif ESP32
|
||||
# error "Not yet supported"
|
||||
#endif
|
||||
|
||||
// https://www.best-microcontroller-projects.com/i2c-tutorial.html
|
||||
|
||||
namespace i2c {
|
||||
|
||||
static constexpr const char* NAME = "SoftI2C";
|
||||
|
||||
#if ESP8266
|
||||
|
||||
// static inline void init() {
|
||||
// //debugMod(NAME, "init()");
|
||||
// GPIO5_OUTPUT_SET; // clock is always output
|
||||
// //GPIO5_INPUT_PULLUP_SET; // pullup for i2c
|
||||
// //GPIO4_INPUT_PULLUP_SET; // pullup for i2c
|
||||
// }
|
||||
|
||||
// static inline void sclLo() {GPIO5_L;}
|
||||
// static inline void sclHi() {GPIO5_H;}
|
||||
// static inline void sclDirOut() {GPIO5_OUTPUT_SET;}
|
||||
|
||||
// static inline void sdaDirIn() {GPIO4_INPUT_SET;}// GPIO4_INPUT_PULLUP_SET;}
|
||||
// static inline void sdaDirOut() {GPIO4_OUTPUT_SET;}
|
||||
// static inline uint8_t sdaRead() {return GPIO4_IN;}
|
||||
// static inline void sdaLo() {GPIO4_L;}
|
||||
// static inline void sdaHi() {GPIO4_H;}
|
||||
|
||||
static constexpr const uint8_t PIN_SCL = 5;
|
||||
static constexpr const uint8_t PIN_SDA = 4;
|
||||
|
||||
#elif ESP32
|
||||
//# error "Not yet supported"
|
||||
#endif
|
||||
|
||||
|
||||
#if (SOFTI2C_SPEED == 1)
|
||||
|
||||
// safe
|
||||
static inline void waitShort() {os_delay_us(1);}
|
||||
static inline void waitLong() {os_delay_us(10);}
|
||||
|
||||
#elif (SOFTI2C_SPEED == 2)
|
||||
|
||||
// fast
|
||||
static inline void waitShort() {asm("nop");asm("nop");}
|
||||
static inline void waitLong() {os_delay_us(1);}
|
||||
|
||||
#elif (SOFTI2C_SPEED == 3)
|
||||
|
||||
// ultra fast
|
||||
static inline void waitShort() {}
|
||||
static inline void waitLong() {asm("nop");asm("nop");asm("nop");asm("nop");}
|
||||
|
||||
#else
|
||||
|
||||
#error "SOFTI2C Speed not set"
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
static inline void init() {
|
||||
GPIO::setOutput(PIN_SCL); // always output
|
||||
}
|
||||
|
||||
static inline void sclLo() {GPIO::clear(PIN_SCL);}
|
||||
static inline void sclHi() {GPIO::set(PIN_SCL);}
|
||||
static inline void sclDirOut() {GPIO::setOutput(PIN_SCL);}
|
||||
|
||||
static inline void sdaDirIn() {GPIO::setInput(PIN_SDA);}// GPIO4_INPUT_PULLUP_SET;}
|
||||
static inline void sdaDirOut() {GPIO::setOutput(PIN_SDA);}
|
||||
static inline uint8_t sdaRead() {return GPIO::get(PIN_SDA);}
|
||||
static inline void sdaLo() {GPIO::clear(PIN_SDA);}
|
||||
static inline void sdaHi() {GPIO::set(PIN_SDA);}
|
||||
|
||||
|
||||
static inline void start() {
|
||||
|
||||
init();
|
||||
sdaDirOut();
|
||||
sclDirOut();
|
||||
|
||||
sdaHi();
|
||||
sclHi();
|
||||
|
||||
waitLong();
|
||||
sdaLo();
|
||||
|
||||
waitLong();
|
||||
sclLo();
|
||||
|
||||
waitLong();
|
||||
|
||||
}
|
||||
|
||||
static inline void stop() {
|
||||
|
||||
sdaDirOut();
|
||||
sclDirOut();
|
||||
|
||||
sdaLo();
|
||||
sclLo();
|
||||
|
||||
waitLong();
|
||||
sclHi();
|
||||
|
||||
waitLong();
|
||||
sdaHi();
|
||||
|
||||
sdaDirIn(); // free the bus
|
||||
|
||||
waitLong();
|
||||
|
||||
}
|
||||
|
||||
|
||||
/** write one bit to the bus */
|
||||
static inline void writeBit(const bool out) {
|
||||
sdaDirOut(); // switch to output mode
|
||||
if(out) {sdaHi();} else {sdaLo();} // apply data
|
||||
sclHi(); // clock pulse
|
||||
waitShort();
|
||||
sclLo();
|
||||
waitShort();
|
||||
sdaDirIn(); // free the bus
|
||||
}
|
||||
|
||||
/** read one bit from the bus */
|
||||
static inline uint8_t readBit() {
|
||||
sdaDirIn(); // switch to input mode
|
||||
sclHi(); // clock pulse and read
|
||||
waitShort();
|
||||
const uint8_t val = sdaRead();
|
||||
sclLo();
|
||||
waitShort();
|
||||
return val;
|
||||
}
|
||||
|
||||
static inline bool readAck() {
|
||||
const uint8_t res = readBit();
|
||||
//os_printf("readAck() - Bus: %d\n", res);
|
||||
return res == 0; // ACK when input pulled low
|
||||
}
|
||||
|
||||
static inline void writeAck() {
|
||||
writeBit(0);
|
||||
}
|
||||
|
||||
static inline void writeNAck() {
|
||||
writeBit(1);
|
||||
}
|
||||
|
||||
/** read 8 bits from the bus, WITHOUT sending ACK/NACK */
|
||||
static uint8_t IN_FLASH readByte() {
|
||||
return
|
||||
(readBit() << 7) |
|
||||
(readBit() << 6) |
|
||||
(readBit() << 5) |
|
||||
(readBit() << 4) |
|
||||
(readBit() << 3) |
|
||||
(readBit() << 2) |
|
||||
(readBit() << 1) |
|
||||
(readBit() << 0);
|
||||
}
|
||||
|
||||
/** read the given number of bytes from the slave and generate ACK/NACK as needed */
|
||||
static void readBytes(uint8_t* dst, uint8_t len) {
|
||||
while(len) {
|
||||
*dst = readByte();
|
||||
--len;
|
||||
++dst;
|
||||
if (len) {writeAck();} else {writeNAck();} // done? or want more?
|
||||
}
|
||||
}
|
||||
|
||||
/** write one byte to the bus */
|
||||
static void IN_FLASH 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));
|
||||
}
|
||||
|
||||
/** write one byte to the bus and check slave's ACK/NACK */
|
||||
static bool IN_FLASH writeByteAndCheck(const uint8_t byte) {
|
||||
writeByte(byte);
|
||||
return readAck();
|
||||
}
|
||||
|
||||
/** write several bytes to the bus and check slave's ACK/NACK */
|
||||
static bool IN_FLASH writeBytesAndCheck(const uint8_t* src, uint8_t len) {
|
||||
while(len) {
|
||||
const bool ok = writeByteAndCheck(*src);
|
||||
if (!ok) {return false;}
|
||||
--len; ++src;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static inline bool startWrite(const uint8_t addr7) {
|
||||
start();
|
||||
writeByte( (addr7<<1) | 0 );
|
||||
const bool ok = readAck();
|
||||
return ok;
|
||||
}
|
||||
|
||||
static inline bool startRead(const uint8_t addr7) {
|
||||
start();
|
||||
writeByte( (addr7<<1) | 1 );
|
||||
const bool ok = readAck();
|
||||
return ok;
|
||||
}
|
||||
|
||||
static inline bool query(const uint8_t addr7) {
|
||||
bool ok = startWrite(addr7);
|
||||
stop();
|
||||
return ok;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // SOFTSPI_H
|
||||
402
io/SoftSPI.h
402
io/SoftSPI.h
@@ -1,11 +1,19 @@
|
||||
#ifndef SOFTSPI_H
|
||||
#define SOFTSPI_H
|
||||
|
||||
//#include "IO.h"
|
||||
#include "GPIO.h"
|
||||
#include "../Platforms.h"
|
||||
#include "../Debug.h"
|
||||
|
||||
|
||||
|
||||
#pragma GCC push_options
|
||||
#pragma GCC optimize ("O3")
|
||||
|
||||
|
||||
|
||||
/*
|
||||
|
||||
#if (PLATFORM == NODE_MCU) || (PLATFORM == WEMOS_D1_MINI)
|
||||
|
||||
#include "fastGPIO.h"
|
||||
@@ -34,29 +42,35 @@
|
||||
#include "driver/gpio.h"
|
||||
#include <stdint.h>
|
||||
|
||||
#define SPI_PIN_MISO GPIO_NUM_35
|
||||
#define SPI_PIN_MOSI GPIO_NUM_32
|
||||
#define SPI_PIN_CLK GPIO_NUM_27
|
||||
#define SPI_PIN_CS GPIO_NUM_25
|
||||
// #define SPI_PIN_MISO GPIO_NUM_35
|
||||
// #define SPI_PIN_MOSI GPIO_NUM_32
|
||||
// #define SPI_PIN_CLK GPIO_NUM_27
|
||||
// #define SPI_PIN_CS GPIO_NUM_25
|
||||
|
||||
#define SPI_CS_OUTPUT gpio_set_direction(SPI_PIN_CS, GPIO_MODE_OUTPUT)
|
||||
#define SPI_MOSI_OUTPUT gpio_set_direction(SPI_PIN_MOSI, GPIO_MODE_OUTPUT)
|
||||
#define SPI_MISO_INPUT gpio_set_direction(SPI_PIN_MISO, GPIO_MODE_INPUT)
|
||||
#define SPI_PIN_MISO GPIO_NUM_19
|
||||
#define SPI_PIN_MOSI GPIO_NUM_23
|
||||
#define SPI_PIN_CLK GPIO_NUM_18
|
||||
#define SPI_PIN_CS GPIO_NUM_2
|
||||
|
||||
#define SPI_CS_OUTPUT GPIO::setOutput(SPI_PIN_CS)
|
||||
#define SPI_MOSI_OUTPUT GPIO::setOutput(SPI_PIN_MOSI)
|
||||
#define SPI_MISO_INPUT GPIO::setInput(SPI_PIN_MISO)
|
||||
#define SPI_MISO_NO_PULLUP //gpio_set_pull_mode(SPI_PIN_MISO, GPIO_FLOATING) /// ??????
|
||||
#define SPI_CLK_OUTPUT gpio_set_direction(SPI_PIN_CLK, GPIO_MODE_OUTPUT)
|
||||
#define SPI_CLK_OUTPUT GPIO::setOutput(SPI_PIN_CLK)
|
||||
|
||||
#define SPI_CS_LO gpio_set_level(SPI_PIN_CS, 0)
|
||||
#define SPI_CS_HI gpio_set_level(SPI_PIN_CS, 1)
|
||||
#define SPI_CS_LO GPIO::clear(SPI_PIN_CS)
|
||||
#define SPI_CS_HI GPIO::set(SPI_PIN_CS)
|
||||
|
||||
#define SPI_CLK_LO gpio_set_level(SPI_PIN_CLK, 0)
|
||||
#define SPI_CLK_HI gpio_set_level(SPI_PIN_CLK, 1)
|
||||
#define SPI_CLK_LO GPIO::clear(SPI_PIN_CLK)
|
||||
#define SPI_CLK_HI GPIO::set(SPI_PIN_CLK)
|
||||
|
||||
#define SPI_MOSI_LO gpio_set_level(SPI_PIN_MOSI, 0)
|
||||
#define SPI_MOSI_HI gpio_set_level(SPI_PIN_MOSI, 1)
|
||||
#define SPI_MOSI_LO GPIO::clear(SPI_PIN_MOSI)
|
||||
#define SPI_MOSI_HI GPIO::set(SPI_PIN_MOSI)
|
||||
#define SPI_MOSI_SC(v) GPIO::setOrClear(SPI_PIN_MOSI, v)
|
||||
|
||||
#define SPI_MISO_READ gpio_get_level(SPI_PIN_MISO)
|
||||
#define SPI_MISO_READ GPIO::get(SPI_PIN_MISO);
|
||||
|
||||
#define SPI_FAST
|
||||
#define SPI_FAST
|
||||
|
||||
#else
|
||||
#error "not supported"
|
||||
@@ -66,18 +80,6 @@ namespace spi {
|
||||
|
||||
static constexpr const char* NAME = "SoftSPI";
|
||||
|
||||
// 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!
|
||||
@@ -94,12 +96,14 @@ namespace spi {
|
||||
|
||||
static inline bool getMISO() {return SPI_MISO_READ;} // D6
|
||||
|
||||
|
||||
#ifdef SPI_FAST
|
||||
static inline void wait() {
|
||||
__asm__ __volatile__("nop");
|
||||
//__asm__ __volatile__("nop");
|
||||
}
|
||||
static inline void waitLong() {
|
||||
DELAY_US(1);
|
||||
//DELAY_US(1);
|
||||
__asm__ __volatile__("nop"); __asm__ __volatile__("nop");
|
||||
}
|
||||
#else
|
||||
static inline void wait() {
|
||||
@@ -136,7 +140,7 @@ namespace spi {
|
||||
return (inp) ? 1 : 0;
|
||||
}
|
||||
|
||||
/** write one bit to the bus */
|
||||
// write one bit to the bus
|
||||
static inline void writeBit(const bool out) {
|
||||
if(out) {SPI_MOSI_HI;} else {SPI_MOSI_LO;}
|
||||
wait();
|
||||
@@ -146,7 +150,7 @@ namespace spi {
|
||||
wait();
|
||||
}
|
||||
|
||||
/** read one bit from the bus */
|
||||
// read one bit from the bus
|
||||
static inline uint8_t readBit() {
|
||||
clkHi();
|
||||
wait();
|
||||
@@ -172,7 +176,7 @@ namespace spi {
|
||||
}
|
||||
|
||||
|
||||
/** read 16 bits */
|
||||
// read 16 bits
|
||||
static uint16_t IN_FLASH readWord() {
|
||||
return
|
||||
(readBit() << 15) |
|
||||
@@ -193,54 +197,87 @@ namespace spi {
|
||||
(readBit() << 0);
|
||||
}
|
||||
|
||||
/** read 8 bits */
|
||||
static uint8_t IN_FLASH readByte() {
|
||||
// read 8 bits
|
||||
static uint8_t IRAM_ATTR readByte() {
|
||||
return
|
||||
(readBit() << 7) |
|
||||
(readBit() << 6) |
|
||||
(readBit() << 5) |
|
||||
(readBit() << 4) |
|
||||
(readBit() << 3) |
|
||||
(readBit() << 2) |
|
||||
(readBit() << 1) |
|
||||
(readBit() << 0);
|
||||
(readBit() << 7) |
|
||||
(readBit() << 6) |
|
||||
(readBit() << 5) |
|
||||
(readBit() << 4) |
|
||||
(readBit() << 3) |
|
||||
(readBit() << 2) |
|
||||
(readBit() << 1) |
|
||||
(readBit() << 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void IN_FLASH 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 IRAM_ATTR writeQuad(const uint32_t quad) {
|
||||
writeBit(quad & BIT(31));
|
||||
writeBit(quad & BIT(30));
|
||||
writeBit(quad & BIT(29));
|
||||
writeBit(quad & BIT(28));
|
||||
writeBit(quad & BIT(27));
|
||||
writeBit(quad & BIT(26));
|
||||
writeBit(quad & BIT(25));
|
||||
writeBit(quad & BIT(24));
|
||||
writeBit(quad & BIT(23));
|
||||
writeBit(quad & BIT(22));
|
||||
writeBit(quad & BIT(21));
|
||||
writeBit(quad & BIT(20));
|
||||
writeBit(quad & BIT(19));
|
||||
writeBit(quad & BIT(18));
|
||||
writeBit(quad & BIT(17));
|
||||
writeBit(quad & BIT(16));
|
||||
writeBit(quad & BIT(15));
|
||||
writeBit(quad & BIT(14));
|
||||
writeBit(quad & BIT(13));
|
||||
writeBit(quad & BIT(12));
|
||||
writeBit(quad & BIT(11));
|
||||
writeBit(quad & BIT(10));
|
||||
writeBit(quad & BIT( 9));
|
||||
writeBit(quad & BIT( 8));
|
||||
writeBit(quad & BIT( 7));
|
||||
writeBit(quad & BIT( 6));
|
||||
writeBit(quad & BIT( 5));
|
||||
writeBit(quad & BIT( 4));
|
||||
writeBit(quad & BIT( 3));
|
||||
writeBit(quad & BIT( 2));
|
||||
writeBit(quad & BIT( 1));
|
||||
writeBit(quad & BIT( 0));
|
||||
}
|
||||
|
||||
static void IN_FLASH 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 void IRAM_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 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));
|
||||
}
|
||||
|
||||
static uint16_t IN_FLASH readWriteWord(const uint16_t word) {
|
||||
return
|
||||
(readWriteBit(word & BIT(15)) << 15) |
|
||||
(readWriteBit(word & BIT(15)) << 15) |
|
||||
(readWriteBit(word & BIT(14)) << 14) |
|
||||
(readWriteBit(word & BIT(13)) << 13) |
|
||||
(readWriteBit(word & BIT(12)) << 12) |
|
||||
@@ -273,6 +310,225 @@ namespace spi {
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
template <int PIN_MISO, int PIN_MOSI, int PIN_CLK, bool fast> class SoftSPI {
|
||||
|
||||
static constexpr const char* NAME = "softSPI";
|
||||
|
||||
public:
|
||||
|
||||
/** ctor */
|
||||
SoftSPI() {
|
||||
init();
|
||||
}
|
||||
|
||||
private:
|
||||
void init() {
|
||||
debugMod(NAME, "init()");
|
||||
GPIO::setInput(PIN_MISO);
|
||||
GPIO::setOutput(PIN_MOSI);
|
||||
GPIO::setOutput(PIN_CLK);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
static inline void wait() {
|
||||
if (!fast) {
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
__asm__ __volatile__("nop");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline void clkLo() { GPIO::clear(PIN_CLK); }
|
||||
inline void clkHi() { GPIO::set(PIN_CLK); }
|
||||
|
||||
/** write one bit to the bus */
|
||||
inline void writeBit(const bool out) {
|
||||
if(out) {GPIO::set(PIN_MOSI);} else {GPIO::clear(PIN_MOSI);}
|
||||
wait();
|
||||
clkHi();
|
||||
wait();
|
||||
clkLo();
|
||||
wait();
|
||||
}
|
||||
|
||||
/** read one bit from the bus */
|
||||
inline uint8_t readBit() {
|
||||
clkHi();
|
||||
wait();
|
||||
const bool val = GPIO::get(PIN_MISO);
|
||||
wait();
|
||||
clkLo();
|
||||
wait();
|
||||
return (val) ? 1 : 0;
|
||||
}
|
||||
|
||||
inline uint8_t readWriteBit(const bool out) {
|
||||
if(out) {GPIO::set(PIN_MOSI);} else {GPIO::clear(PIN_MOSI);}
|
||||
wait();
|
||||
clkHi();
|
||||
wait();
|
||||
const bool inp = GPIO::get(PIN_MISO);
|
||||
wait();
|
||||
clkLo();
|
||||
wait();
|
||||
return (inp) ? 1 : 0;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
void IRAM_ATTR writeQuad(const uint32_t quad) {
|
||||
// writeBit(quad & BIT(31));
|
||||
// writeBit(quad & BIT(30));
|
||||
// writeBit(quad & BIT(29));
|
||||
// writeBit(quad & BIT(28));
|
||||
// writeBit(quad & BIT(27));
|
||||
// writeBit(quad & BIT(26));
|
||||
// writeBit(quad & BIT(25));
|
||||
// writeBit(quad & BIT(24));
|
||||
// writeBit(quad & BIT(23));
|
||||
// writeBit(quad & BIT(22));
|
||||
// writeBit(quad & BIT(21));
|
||||
// writeBit(quad & BIT(20));
|
||||
// writeBit(quad & BIT(19));
|
||||
// writeBit(quad & BIT(18));
|
||||
// writeBit(quad & BIT(17));
|
||||
// writeBit(quad & BIT(16));
|
||||
// writeBit(quad & BIT(15));
|
||||
// writeBit(quad & BIT(14));
|
||||
// writeBit(quad & BIT(13));
|
||||
// writeBit(quad & BIT(12));
|
||||
// writeBit(quad & BIT(11));
|
||||
// writeBit(quad & BIT(10));
|
||||
// writeBit(quad & BIT( 9));
|
||||
// writeBit(quad & BIT( 8));
|
||||
// writeBit(quad & BIT( 7));
|
||||
// writeBit(quad & BIT( 6));
|
||||
// writeBit(quad & BIT( 5));
|
||||
// writeBit(quad & BIT( 4));
|
||||
// writeBit(quad & BIT( 3));
|
||||
// writeBit(quad & BIT( 2));
|
||||
// writeBit(quad & BIT( 1));
|
||||
// writeBit(quad & BIT( 0));
|
||||
writeByte((quad>>24)&0xFF);
|
||||
writeByte((quad>>16)&0xFF);
|
||||
writeByte((quad>> 8)&0xFF);
|
||||
writeByte((quad>> 0)&0xFF);
|
||||
}
|
||||
|
||||
void IRAM_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));
|
||||
writeByte((word>>8)&0xFF);
|
||||
writeByte((word>>0)&0xFF);
|
||||
}
|
||||
|
||||
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() {
|
||||
GPIO::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;
|
||||
|
||||
Reference in New Issue
Block a user