minor platform macro changes
worked on code for LoRa SX1276
This commit is contained in:
7
Debug.h
7
Debug.h
@@ -42,6 +42,8 @@ extern "C" {
|
||||
#define debugMod9(module, str, v1, v2, v3, v4, v5, v6, v7, v8, v9)
|
||||
#define IF_DEBUG(a)
|
||||
#define debugShow(a, b)
|
||||
|
||||
#warning "not using debug output"
|
||||
|
||||
#elif ESP8266
|
||||
|
||||
@@ -66,14 +68,13 @@ extern "C" {
|
||||
os_printf("\n");
|
||||
}
|
||||
|
||||
#elif (PLATFORM == WROOM32_DEVKIT)
|
||||
#elif ESP32
|
||||
|
||||
#ifndef CONFIG_LOG_DEFAULT_LEVEL
|
||||
#define CONFIG_LOG_DEFAULT_LEVEL 3
|
||||
#endif
|
||||
#include "esp_log.h"
|
||||
|
||||
|
||||
#define debug(str) ESP_LOGI("", str);
|
||||
#define debugMod(module, str) ESP_LOGI(module, str);
|
||||
#define debugMod1(module, str, val) ESP_LOGI(module, str, val);
|
||||
@@ -84,7 +85,9 @@ extern "C" {
|
||||
#define debugShow(buf, len) hexdump(buf,len)
|
||||
|
||||
#else
|
||||
|
||||
#error "unsupported platform"
|
||||
|
||||
#endif
|
||||
|
||||
#endif // DEBUG_H
|
||||
|
||||
24
Platforms.h
24
Platforms.h
@@ -7,20 +7,32 @@
|
||||
// https://blog.anto.io/wp-content/uploads/2016/12/esp32.png
|
||||
// https://i.pinimg.com/originals/c6/57/83/c657835e84aaf91832a770ea0d7d0767.jpg
|
||||
#define WROOM32_DEVKIT 32
|
||||
#define TTGO 33
|
||||
|
||||
|
||||
#define ESP8266 (PLATFORM == WEMOS_D1_MINI) || (PLATFORM == NODE_MCU)
|
||||
#define ESP32 (PLATFORM == WROOM32_DEVKIT)
|
||||
#define ESP32 (PLATFORM == WROOM32_DEVKIT) || (PLATFORM == TTGO)
|
||||
|
||||
|
||||
#if (PLATFORM == WROOM32_DEVKIT)
|
||||
#define DELAY_US(us) ets_delay_us(us)
|
||||
#define IN_FLASH
|
||||
#ifndef PLATFORM
|
||||
#error "PLATFORM compile time variable not defined"
|
||||
#endif
|
||||
|
||||
#if (PLATFORM == WEMOS_D1_MINI) || (PLATFORM == NODE_MCU)
|
||||
#if (ESP32)
|
||||
|
||||
#pragma message "Using ESP32"
|
||||
#define DELAY_US(us) ets_delay_us(us)
|
||||
#define IN_FLASH
|
||||
|
||||
#elif (ESP8266)
|
||||
|
||||
#pragma message "Using ESP8266"
|
||||
#define DELAY_US(us) os_delay_us(us)
|
||||
#define IN_FLASH ICACHE_FLASH_ATTR
|
||||
|
||||
#else
|
||||
|
||||
#error "unsupported platform";
|
||||
|
||||
#endif
|
||||
|
||||
//#define min(a,b) (a<b) ? (a) : (b)
|
||||
|
||||
412
ext/rf/SX1276.h
412
ext/rf/SX1276.h
@@ -1,9 +1,419 @@
|
||||
#ifndef RF_SX1276
|
||||
#define RF_SX1276
|
||||
|
||||
class SX1276 {
|
||||
/*
|
||||
// registers
|
||||
#define REG_FIFO 0x00
|
||||
#define REG_OP_MODE 0x01
|
||||
#define REG_FRF_MSB 0x06
|
||||
#define REG_FRF_MID 0x07
|
||||
#define REG_FRF_LSB 0x08
|
||||
#define REG_PA_CONFIG 0x09
|
||||
#define REG_OCP 0x0b
|
||||
#define REG_LNA 0x0c
|
||||
#define REG_FIFO_ADDR_PTR 0x0d
|
||||
#define REG_FIFO_TX_BASE_ADDR 0x0e
|
||||
#define REG_FIFO_RX_BASE_ADDR 0x0f
|
||||
#define REG_FIFO_RX_CURRENT_ADDR 0x10
|
||||
#define REG_IRQ_FLAGS 0x12
|
||||
#define REG_RX_NB_BYTES 0x13
|
||||
#define REG_PKT_SNR_VALUE 0x19
|
||||
#define REG_PKT_RSSI_VALUE 0x1a
|
||||
#define REG_MODEM_CONFIG_1 0x1d
|
||||
#define REG_MODEM_CONFIG_2 0x1e
|
||||
#define REG_PREAMBLE_MSB 0x20
|
||||
#define REG_PREAMBLE_LSB 0x21
|
||||
#define REG_PAYLOAD_LENGTH 0x22
|
||||
#define REG_MODEM_CONFIG_3 0x26
|
||||
#define REG_FREQ_ERROR_MSB 0x28
|
||||
#define REG_FREQ_ERROR_MID 0x29
|
||||
#define REG_FREQ_ERROR_LSB 0x2a
|
||||
#define REG_RSSI_WIDEBAND 0x2c
|
||||
#define REG_DETECTION_OPTIMIZE 0x31
|
||||
#define REG_INVERTIQ 0x33
|
||||
#define REG_DETECTION_THRESHOLD 0x37
|
||||
#define REG_SYNC_WORD 0x39
|
||||
#define REG_INVERTIQ2 0x3b
|
||||
#define REG_DIO_MAPPING_1 0x40
|
||||
#define REG_VERSION 0x42
|
||||
#define REG_PA_DAC 0x4d
|
||||
|
||||
// modes
|
||||
#define MODE_LONG_RANGE_MODE 0x80
|
||||
#define MODE_SLEEP 0x00
|
||||
#define MODE_STDBY 0x01
|
||||
#define MODE_TX 0x03
|
||||
#define MODE_RX_CONTINUOUS 0x05
|
||||
#define MODE_RX_SINGLE 0x06
|
||||
|
||||
// PA config
|
||||
#define PA_BOOST 0x80
|
||||
|
||||
// IRQ masks
|
||||
#define IRQ_TX_DONE_MASK 0x08
|
||||
#define IRQ_PAYLOAD_CRC_ERROR_MASK 0x20
|
||||
#define IRQ_RX_DONE_MASK 0x40
|
||||
|
||||
#define MAX_PKT_LENGTH 255
|
||||
|
||||
#if (ESP8266 || ESP32)
|
||||
#define ISR_PREFIX ICACHE_RAM_ATTR
|
||||
#else
|
||||
#define ISR_PREFIX
|
||||
#endif
|
||||
|
||||
*/
|
||||
|
||||
#include "../../Debug.h"
|
||||
|
||||
template <typename SPI, int PIN_SLAVE_SEL, int PIN_RESET, int PIN_DIO0> class SX1276 {
|
||||
|
||||
SPI& spi;
|
||||
|
||||
static constexpr const uint8_t REG_FIFO = 0x00;
|
||||
static constexpr const uint8_t REG_OP_MODE = 0x01;
|
||||
static constexpr const uint8_t REG_FRF_MSB = 0x06;
|
||||
static constexpr const uint8_t REG_FRF_MID = 0x07;
|
||||
static constexpr const uint8_t REG_FRF_LSB = 0x08;
|
||||
static constexpr const uint8_t REG_PA_CONFIG = 0x09;
|
||||
static constexpr const uint8_t REG_OCP = 0x0b;
|
||||
static constexpr const uint8_t REG_LNA = 0x0c;
|
||||
static constexpr const uint8_t REG_FIFO_ADDR_PTR = 0x0d;
|
||||
static constexpr const uint8_t REG_FIFO_TX_BASE_ADDR = 0x0e;
|
||||
static constexpr const uint8_t REG_FIFO_RX_BASE_ADDR = 0x0f;
|
||||
|
||||
static constexpr const uint8_t REG_FIFO_RX_CURRENT_ADDR = 0x10;
|
||||
static constexpr const uint8_t REG_IRQ_FLAGS = 0x12;
|
||||
static constexpr const uint8_t REG_RX_NB_BYTES = 0x13;
|
||||
static constexpr const uint8_t REG_PKT_SNR_VALUE = 0x19;
|
||||
static constexpr const uint8_t REG_PKT_RSSI_VALUE = 0x1a;
|
||||
static constexpr const uint8_t REG_MODEM_CONFIG_1 = 0x1d;
|
||||
static constexpr const uint8_t REG_MODEM_CONFIG_2 = 0x1e;
|
||||
|
||||
static constexpr const uint8_t REG_PAYLOAD_LENGTH = 0x22;
|
||||
static constexpr const uint8_t REG_MODEM_CONFIG_3 = 0x26;
|
||||
|
||||
static constexpr const uint8_t REG_VERSION = 0x42;
|
||||
static constexpr const uint8_t REG_PA_DAC = 0x4d;
|
||||
|
||||
// modes
|
||||
static constexpr const uint8_t MODE_LONG_RANGE_MODE = 0x80;
|
||||
static constexpr const uint8_t MODE_SLEEP = 0x00;
|
||||
static constexpr const uint8_t MODE_STDBY = 0x01;
|
||||
static constexpr const uint8_t MODE_TX = 0x03;
|
||||
static constexpr const uint8_t MODE_RX_CONTINUOUS = 0x05;
|
||||
static constexpr const uint8_t MODE_RX_SINGLE = 0x06;
|
||||
|
||||
// PA config
|
||||
static constexpr const uint8_t PA_BOOST = 0x80;
|
||||
|
||||
static constexpr const uint8_t PA_OUTPUT_RFO_PIN = 0;
|
||||
static constexpr const uint8_t PA_OUTPUT_PA_BOOST_PIN = 1;
|
||||
|
||||
// IRQ marks
|
||||
static constexpr const uint8_t IRQ_TX_DONE_MASK = 0x08;
|
||||
static constexpr const uint8_t IRQ_PAYLOAD_CRC_ERROR_MASK = 0x20;
|
||||
static constexpr const uint8_t IRQ_RX_DONE_MASK = 0x40;
|
||||
|
||||
static constexpr const uint8_t MAX_PKT_LENGTH = 255;
|
||||
|
||||
|
||||
static constexpr const char* NAME = "LoRa";
|
||||
|
||||
uint32_t curFreq = 0;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
struct PacketDetails {
|
||||
int8_t rssi;
|
||||
float snr;
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
SX1276(SPI& spi) : spi(spi) {
|
||||
MyGPIO::setOutput(PIN_SLAVE_SEL);
|
||||
MyGPIO::setOutput(PIN_RESET);
|
||||
reset();
|
||||
check();
|
||||
init();
|
||||
}
|
||||
|
||||
void init() {
|
||||
|
||||
debugMod(NAME, "init()");
|
||||
|
||||
// sleep mode
|
||||
sleep();
|
||||
|
||||
// set the RF frequency
|
||||
setFrequency(866E6);
|
||||
|
||||
// set base address
|
||||
writeRegister(REG_FIFO_TX_BASE_ADDR, 0);
|
||||
writeRegister(REG_FIFO_RX_BASE_ADDR, 0);
|
||||
|
||||
// set LNA boost
|
||||
writeRegister(REG_LNA, readRegister(REG_LNA) | 0x03);
|
||||
|
||||
// set auto AGC
|
||||
writeRegister(REG_MODEM_CONFIG_3, 0x04);
|
||||
|
||||
// set output power to 17 dBm
|
||||
setTxPower(17);
|
||||
|
||||
// put in standby mode
|
||||
idle();
|
||||
|
||||
debugMod(NAME, "init complete");
|
||||
|
||||
}
|
||||
|
||||
// void setUseCRC(bool use) {
|
||||
// if (use) {
|
||||
// writeRegister(REG_MODEM_CONFIG_2, readRegister(REG_MODEM_CONFIG_2) | 0x04);
|
||||
// } else {
|
||||
// writeRegister(REG_MODEM_CONFIG_2, readRegister(REG_MODEM_CONFIG_2) & 0xfb);
|
||||
// }
|
||||
// }
|
||||
|
||||
void idle() {
|
||||
debugMod(NAME, "idle()");
|
||||
writeRegister(REG_OP_MODE, MODE_LONG_RANGE_MODE | MODE_STDBY);
|
||||
}
|
||||
|
||||
void sleep() {
|
||||
debugMod(NAME, "sleep()");
|
||||
writeRegister(REG_OP_MODE, MODE_LONG_RANGE_MODE | MODE_SLEEP);
|
||||
}
|
||||
|
||||
bool isTransmitting() {
|
||||
if ((readRegister(REG_OP_MODE) & MODE_TX) == MODE_TX) {return true;}
|
||||
if (readRegister(REG_IRQ_FLAGS) & IRQ_TX_DONE_MASK) {writeRegister(REG_IRQ_FLAGS, IRQ_TX_DONE_MASK);} // clear TX-done IRQ flag
|
||||
return false;
|
||||
}
|
||||
|
||||
int send(const uint8_t* data, uint8_t len, bool async) {
|
||||
|
||||
debugMod1(NAME, "send(%d bytes)", len);
|
||||
|
||||
//if (len > MAX_PKT_LENGTH) {return -1;}
|
||||
if (isTransmitting()) {return 0;}
|
||||
|
||||
// put in standby mode
|
||||
idle();
|
||||
|
||||
//if (implicitHeader) {
|
||||
// implicitHeaderMode();
|
||||
//} else {
|
||||
explicitHeaderMode();
|
||||
//}
|
||||
|
||||
// reset FIFO address and payload length
|
||||
writeRegister(REG_FIFO_ADDR_PTR, 0);
|
||||
writeRegister(REG_PAYLOAD_LENGTH, 0);
|
||||
|
||||
// write data into FIFO
|
||||
debugMod(NAME, "writing FIFO");
|
||||
for (uint16_t i = 0; i < len; ++i) {writeRegister(REG_FIFO, data[i]);}
|
||||
writeRegister(REG_PAYLOAD_LENGTH, len);
|
||||
|
||||
|
||||
//if ((async) && (_onTxDone)) writeRegister(REG_DIO_MAPPING_1, 0x40); // DIO0 => TXDONE
|
||||
|
||||
// put in TX mode
|
||||
debugMod(NAME, "starting TX");
|
||||
writeRegister(REG_OP_MODE, MODE_LONG_RANGE_MODE | MODE_TX);
|
||||
|
||||
if (!async) {
|
||||
debugMod(NAME, "waiting");
|
||||
while ((readRegister(REG_IRQ_FLAGS) & IRQ_TX_DONE_MASK) == 0) {yield();} // wait for TX done
|
||||
writeRegister(REG_IRQ_FLAGS, IRQ_TX_DONE_MASK); // clear IRQ TX-done flag
|
||||
debugMod(NAME, "done");
|
||||
}
|
||||
|
||||
return len;
|
||||
|
||||
}
|
||||
|
||||
/** switch to RX-mode. either for a single frame or permanent */
|
||||
void setRX(bool single) {
|
||||
|
||||
// reset FIFO address
|
||||
writeRegister(REG_FIFO_ADDR_PTR, 0);
|
||||
|
||||
// put in single RX mode
|
||||
if (single) {
|
||||
writeRegister(REG_OP_MODE, MODE_LONG_RANGE_MODE | MODE_RX_SINGLE);
|
||||
} else {
|
||||
writeRegister(REG_OP_MODE, MODE_LONG_RANGE_MODE | MODE_RX_CONTINUOUS);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** fetch one received packet, if any is available. requires setRX(..) beforehand to actually receive something! */
|
||||
int read(uint8_t* dst, PacketDetails* det) {
|
||||
|
||||
uint8_t irqFlags = readRegister(REG_IRQ_FLAGS);
|
||||
|
||||
explicitHeaderMode();
|
||||
|
||||
// clear all current IRQ flags
|
||||
writeRegister(REG_IRQ_FLAGS, irqFlags);
|
||||
|
||||
// got something?
|
||||
if ((irqFlags & IRQ_RX_DONE_MASK) && (irqFlags & IRQ_PAYLOAD_CRC_ERROR_MASK) == 0) {
|
||||
|
||||
// read packet length
|
||||
uint8_t packetLength = readRegister(REG_RX_NB_BYTES);
|
||||
|
||||
// set FIFO address to current RX address
|
||||
writeRegister(REG_FIFO_ADDR_PTR, readRegister(REG_FIFO_RX_CURRENT_ADDR));
|
||||
|
||||
// read the packet
|
||||
for (uint16_t i = 0; i < packetLength; ++i) {
|
||||
dst[i] = readRegister(REG_FIFO);
|
||||
}
|
||||
|
||||
// read the details?
|
||||
if (det) {
|
||||
det->rssi = (readRegister(REG_PKT_RSSI_VALUE) - (curFreq < 868E6 ? 164 : 157));
|
||||
det->snr = ((int8_t)readRegister(REG_PKT_SNR_VALUE)) * 0.25f;
|
||||
}
|
||||
|
||||
// put in standby mode
|
||||
//idle();
|
||||
return packetLength;
|
||||
|
||||
}
|
||||
|
||||
// nothing available
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
private:
|
||||
|
||||
void yield() {
|
||||
usleep(5000);
|
||||
}
|
||||
|
||||
void explicitHeaderMode() {
|
||||
writeRegister(REG_MODEM_CONFIG_1, readRegister(REG_MODEM_CONFIG_1) & 0xfe);
|
||||
}
|
||||
|
||||
void implicitHeaderMode() {
|
||||
writeRegister(REG_MODEM_CONFIG_1, readRegister(REG_MODEM_CONFIG_1) | 0x01);
|
||||
}
|
||||
|
||||
// uint8_t getMode() {
|
||||
// const uint8_t mode = readRegister(REG_OP_MODE);
|
||||
// debugMod1(NAME, "mode: %d", mode);
|
||||
// return mode;
|
||||
// }
|
||||
|
||||
/** set the RF frequency to use (in Hz) */
|
||||
void setFrequency(uint32_t hz) {
|
||||
this->curFreq = hz;
|
||||
debugMod1(NAME, "setFrequency(%d Hz)", (int)hz);
|
||||
const uint64_t frf = ((uint64_t)hz << 19) / 32000000;
|
||||
writeRegister(REG_FRF_MSB, (uint8_t)(frf >> 16));
|
||||
writeRegister(REG_FRF_MID, (uint8_t)(frf >> 8));
|
||||
writeRegister(REG_FRF_LSB, (uint8_t)(frf >> 0));
|
||||
}
|
||||
|
||||
/** configure the TX power (in dB). but what is the pin for??? */
|
||||
void setTxPower(int level, int outputPin = PA_OUTPUT_PA_BOOST_PIN) {
|
||||
|
||||
debugMod1(NAME, "setTx(%d dB)", level);
|
||||
|
||||
if (PA_OUTPUT_RFO_PIN == outputPin) {
|
||||
|
||||
// RFO
|
||||
if (level < 0) {level = 0;}
|
||||
if (level > 14) {level = 14;}
|
||||
writeRegister(REG_PA_CONFIG, 0x70 | level);
|
||||
|
||||
} else {
|
||||
|
||||
// PA BOOST
|
||||
if (level > 17) {
|
||||
|
||||
if (level > 20) {level = 20;}
|
||||
|
||||
// subtract 3 from level, so 18 - 20 maps to 15 - 17
|
||||
level -= 3;
|
||||
|
||||
// High Power +20 dBm Operation (Semtech SX1276/77/78/79 5.4.3.)
|
||||
writeRegister(REG_PA_DAC, 0x87);
|
||||
setOCP(140);
|
||||
|
||||
} else {
|
||||
if (level < 2) {level = 2;}
|
||||
//Default value PA_HF/LF or +17dBm
|
||||
writeRegister(REG_PA_DAC, 0x84);
|
||||
setOCP(100);
|
||||
}
|
||||
|
||||
writeRegister(REG_PA_CONFIG, PA_BOOST | (level - 2));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/** perform hard reset */
|
||||
void reset() {
|
||||
debugMod(NAME, "reset");
|
||||
//MyGPIO::set(PIN_RESET);
|
||||
//usleep(20*1000);
|
||||
MyGPIO::clear(PIN_RESET); // perform reset
|
||||
usleep(20*1000);
|
||||
MyGPIO::set(PIN_RESET);
|
||||
usleep(20*1000);
|
||||
debugMod(NAME, "reset done");
|
||||
}
|
||||
|
||||
/** check the chip's version */
|
||||
void check() {
|
||||
uint8_t version = readRegister(REG_VERSION);
|
||||
debugMod1(NAME, "version %d", version);
|
||||
if (version != 0x12) {debugMod(NAME, "!! unsupported chip version detected");}
|
||||
}
|
||||
|
||||
/** what exactly is this? */
|
||||
void setOCP(uint8_t mA) {
|
||||
uint8_t ocpTrim = 27;
|
||||
if (mA <= 120) {ocpTrim = (mA - 45) / 5;}
|
||||
else if (mA <= 240) {ocpTrim = (mA + 30) / 10;}
|
||||
writeRegister(REG_OCP, 0x20 | (0x1F & ocpTrim));
|
||||
}
|
||||
|
||||
/** write value to register */
|
||||
void writeRegister(uint8_t address, uint8_t value) {
|
||||
transfer(address | 0x80, value);
|
||||
}
|
||||
|
||||
/** read value from register */
|
||||
uint8_t readRegister(uint8_t address) {
|
||||
return transfer(address & 0x7f, 0x00);
|
||||
}
|
||||
|
||||
uint8_t transfer(uint8_t address, uint8_t value) {
|
||||
|
||||
MyGPIO::clear(PIN_SLAVE_SEL); // select, active LOW
|
||||
spi.writeByte(address);
|
||||
const uint8_t res = spi.readWriteByte(value);
|
||||
MyGPIO::set(PIN_SLAVE_SEL); // de-select
|
||||
|
||||
return res;
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
371
io/SoftSPI.h
371
io/SoftSPI.h
@@ -10,329 +10,6 @@
|
||||
#pragma GCC push_options
|
||||
#pragma GCC optimize ("O3")
|
||||
|
||||
|
||||
|
||||
/*
|
||||
|
||||
#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 == WROOM32_DEVKIT)
|
||||
|
||||
#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_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::setOutput(SPI_PIN_CLK)
|
||||
|
||||
#define SPI_CS_LO GPIO::clear(SPI_PIN_CS)
|
||||
#define SPI_CS_HI GPIO::set(SPI_PIN_CS)
|
||||
|
||||
#define SPI_CLK_LO GPIO::clear(SPI_PIN_CLK)
|
||||
#define SPI_CLK_HI GPIO::set(SPI_PIN_CLK)
|
||||
|
||||
#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(SPI_PIN_MISO);
|
||||
|
||||
#define SPI_FAST
|
||||
|
||||
#else
|
||||
#error "not supported"
|
||||
#endif
|
||||
|
||||
namespace spi {
|
||||
|
||||
static constexpr const char* NAME = "SoftSPI";
|
||||
|
||||
|
||||
// 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() {
|
||||
//DELAY_US(1);
|
||||
__asm__ __volatile__("nop"); __asm__ __volatile__("nop");
|
||||
}
|
||||
#else
|
||||
static inline void wait() {
|
||||
DELAY_US(2);
|
||||
}
|
||||
static inline void waitLong() {
|
||||
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 IN_FLASH init() {
|
||||
debugMod(NAME, "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 IN_FLASH 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 IRAM_ATTR readByte() {
|
||||
return
|
||||
(readBit() << 7) |
|
||||
(readBit() << 6) |
|
||||
(readBit() << 5) |
|
||||
(readBit() << 4) |
|
||||
(readBit() << 3) |
|
||||
(readBit() << 2) |
|
||||
(readBit() << 1) |
|
||||
(readBit() << 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 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(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_t IN_FLASH 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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
template <int PIN_MISO, int PIN_MOSI, int PIN_CLK, bool fast> class SoftSPI {
|
||||
|
||||
@@ -402,38 +79,6 @@ private:
|
||||
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);
|
||||
@@ -441,22 +86,6 @@ public:
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user