many updates..

new sensors.. display.. led.. drawing.. stuff..
This commit is contained in:
kazu
2019-01-17 23:12:01 +01:00
parent 90e9fee101
commit 5cb02880b3
30 changed files with 5305 additions and 97 deletions

122
io/GPIO.h Normal file
View 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
View 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

1
io/PWM.h Normal file
View File

@@ -0,0 +1 @@

240
io/SoftI2C.h Normal file
View 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

View File

@@ -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;