many changes
This commit is contained in:
52
Debug.h
52
Debug.h
@@ -2,7 +2,9 @@
|
|||||||
#define DEBUG_H
|
#define DEBUG_H
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include "Platforms.h"
|
||||||
|
|
||||||
|
/*
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include "ets_sys.h"
|
#include "ets_sys.h"
|
||||||
#include "c_types.h"
|
#include "c_types.h"
|
||||||
@@ -21,26 +23,11 @@ extern "C" {
|
|||||||
|
|
||||||
#include "driver/uart.h"
|
#include "driver/uart.h"
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
void hexdump(const uint8_t* buf, uint8_t len) {
|
|
||||||
for (int i = 0; i < len; ++i) {
|
|
||||||
os_printf("%02x ", buf[i]);
|
|
||||||
}
|
|
||||||
os_printf("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
|
|
||||||
#define debug(str) os_printf(str)
|
|
||||||
#define debugMod(module, str) os_printf("[%s] %s\n", module, str)
|
|
||||||
#define debugMod1(module, str, val) os_printf("[%s] ", module); os_printf(str, val); os_printf("\n");
|
|
||||||
#define debugMod2(module, str, v1, v2) os_printf("[%s] ", module); os_printf(str, v1, v2); os_printf("\n");
|
|
||||||
#define debugMod3(module, str, v1, v2, v3) os_printf("[%s] ", module); os_printf(str, v1, v2, v3); os_printf("\n");
|
|
||||||
#define IF_DEBUG(a) a
|
|
||||||
#define debugShow(buf, len) hexdump(buf,len)
|
|
||||||
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
#if (!defined(DEBUG))
|
||||||
|
|
||||||
#define debug(str)
|
#define debug(str)
|
||||||
#define debugMod(module, str)
|
#define debugMod(module, str)
|
||||||
@@ -50,6 +37,35 @@ void hexdump(const uint8_t* buf, uint8_t len) {
|
|||||||
#define IF_DEBUG(a)
|
#define IF_DEBUG(a)
|
||||||
#define debugShow(a, b)
|
#define debugShow(a, b)
|
||||||
|
|
||||||
|
#elif (PLATFORM == WEMOS_D1_MINI) || (PLATFORM == NODE_MCU)
|
||||||
|
|
||||||
|
#define debug(str) os_printf(str)
|
||||||
|
#define debugMod(module, str) os_printf("[%s] %s\n", module, str)
|
||||||
|
#define debugMod1(module, str, val) os_printf("[%s] ", module); os_printf(str, val); os_printf("\n");
|
||||||
|
#define debugMod2(module, str, v1, v2) os_printf("[%s] ", module); os_printf(str, v1, v2); os_printf("\n");
|
||||||
|
#define debugMod3(module, str, v1, v2, v3) os_printf("[%s] ", module); os_printf(str, v1, v2, v3); os_printf("\n");
|
||||||
|
#define IF_DEBUG(a) a
|
||||||
|
#define debugShow(buf, len) hexdump(buf,len)
|
||||||
|
|
||||||
|
void hexdump(const uint8_t* buf, uint8_t len) {
|
||||||
|
for (int i = 0; i < len; ++i) {
|
||||||
|
os_printf("%02x ", buf[i]);
|
||||||
|
}
|
||||||
|
os_printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif (PLATFORM == WROOM32_DEVKIT)
|
||||||
|
|
||||||
|
#define debug(str) ESP_LOGI("", str);
|
||||||
|
#define debugMod(module, str) ESP_LOGI(module, str);
|
||||||
|
#define debugMod1(module, str, val) ESP_LOGI(module, str, val);
|
||||||
|
#define debugMod2(module, str, v1, v2) ESP_LOGI(module, str, v1, v2);
|
||||||
|
#define debugMod3(module, str, v1, v2, v3) ESP_LOGI(module, str, v1, v2, v3);
|
||||||
|
#define IF_DEBUG(a) a
|
||||||
|
#define debugShow(buf, len) hexdump(buf,len)
|
||||||
|
|
||||||
|
#else
|
||||||
|
#error "unsupported platform"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif // DEBUG_H
|
#endif // DEBUG_H
|
||||||
|
|||||||
34
Platforms.h
34
Platforms.h
@@ -5,8 +5,38 @@
|
|||||||
|
|
||||||
|
|
||||||
// https://blog.anto.io/wp-content/uploads/2016/12/esp32.png
|
// https://blog.anto.io/wp-content/uploads/2016/12/esp32.png
|
||||||
#define NODE32S 32
|
// https://i.pinimg.com/originals/c6/57/83/c657835e84aaf91832a770ea0d7d0767.jpg
|
||||||
|
#define WROOM32_DEVKIT 32
|
||||||
|
|
||||||
|
|
||||||
|
#define ESP8266 (PLATFORM == WEMOS_D1_MINI) || (PLATFORM == NODE_MCU)
|
||||||
|
#define ESP32 (PLATFORM == WROOM32_DEVKIT)
|
||||||
|
|
||||||
#define PLATFORM NODE32S
|
|
||||||
|
#if (PLATFORM == WROOM32_DEVKIT)
|
||||||
|
#define DELAY_US(us) ets_delay_us(us)
|
||||||
|
#define IN_FLASH
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (PLATFORM == WEMOS_D1_MINI) || (PLATFORM == NODE_MCU)
|
||||||
|
#define DELAY_US(us) os_delay_us(us)
|
||||||
|
#define IN_FLASH ICACHE_FLASH_ATTR
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define min(a,b) (a<b) ? (a) : (b)
|
||||||
|
#define max(a,b) (a>b) ? (a) : (b)
|
||||||
|
|
||||||
|
//template <typename T> inline T min(const T a, const T b) {
|
||||||
|
// return (a<b) ? (a) : (b);
|
||||||
|
//}
|
||||||
|
|
||||||
|
//template <typename T> inline T max(const T a, const T b) {
|
||||||
|
// return (a>b) ? (a) : (b);
|
||||||
|
//}
|
||||||
|
|
||||||
|
#if ESP8266
|
||||||
|
#define sprintf os_sprintf
|
||||||
|
#elif ESP32
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#endif
|
||||||
|
|||||||
99
data/Color.h
Normal file
99
data/Color.h
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
struct Color {
|
||||||
|
|
||||||
|
uint8_t r;
|
||||||
|
uint8_t g;
|
||||||
|
uint8_t b;
|
||||||
|
|
||||||
|
/** no-init */
|
||||||
|
Color() {
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
/** Hidden ctor. RGB */
|
||||||
|
Color(const uint8_t r, const uint8_t g, const uint8_t b) : r(r), g(g), b(b) {
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/** get X-percent [0:100] of this color = darker/brighter */
|
||||||
|
Color inline getPercent(const int percent) const {
|
||||||
|
return Color(r*percent/100, g*percent/100, b*percent/100);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** mix the two given colors */
|
||||||
|
static Color mix(const Color c1, const Color c2, int percentC1) {
|
||||||
|
return Color(
|
||||||
|
((c1.r * percentC1) + (c2.r * (100-percentC1))) / 100,
|
||||||
|
((c1.g * percentC1) + (c2.g * (100-percentC1))) / 100,
|
||||||
|
((c1.b * percentC1) + (c2.b * (100-percentC1))) / 100
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline Color fromRGB(const uint8_t r, const uint8_t g, const uint8_t b) {
|
||||||
|
return Color(r,g,b);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline Color fromHSV(const uint8_t h, const uint8_t s, const uint8_t v) {
|
||||||
|
Color c; c.setHSV(h,s,v); return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setHSV(const uint8_t h, const uint8_t s, const uint8_t v) {
|
||||||
|
|
||||||
|
uint8_t region, remainder, p, q, t;
|
||||||
|
|
||||||
|
region = h / 43;
|
||||||
|
remainder = (h - (region * 43)) * 6;
|
||||||
|
|
||||||
|
p = (v * (255 - s)) >> 8;
|
||||||
|
q = (v * (255 - ((s * remainder) >> 8))) >> 8;
|
||||||
|
t = (v * (255 - ((s * (255 - remainder)) >> 8))) >> 8;
|
||||||
|
|
||||||
|
switch (region) {
|
||||||
|
case 0:
|
||||||
|
r = v; g = t; b = p;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
r = q; g = v; b = p;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
r = p; g = v; b = t;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
r = p; g = q; b = v;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
r = t; g = p; b = v;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
r = v; g = p; b = q;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void setRGB(const uint8_t r, const uint8_t g, const uint8_t b) {
|
||||||
|
this->r = r;
|
||||||
|
this->g = g;
|
||||||
|
this->b = b;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setOff() {
|
||||||
|
this->r = 0;
|
||||||
|
this->g = 0;
|
||||||
|
this->b = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** add two colors */
|
||||||
|
Color operator + (const Color o) const {
|
||||||
|
return Color(r+o.r, g+o.g, b+o.g);
|
||||||
|
}
|
||||||
|
|
||||||
|
Color operator * (const float f) const {
|
||||||
|
return Color(r*f, g*f, b*f);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
@@ -2,6 +2,7 @@
|
|||||||
#define RINGBUFFER_H
|
#define RINGBUFFER_H
|
||||||
|
|
||||||
#include "../Debug.h"
|
#include "../Debug.h"
|
||||||
|
#include "../Platforms.h"
|
||||||
|
|
||||||
typedef void (*RingBufferFullCallback)();
|
typedef void (*RingBufferFullCallback)();
|
||||||
|
|
||||||
@@ -16,7 +17,7 @@ private:
|
|||||||
|
|
||||||
volatile size_t head;
|
volatile size_t head;
|
||||||
volatile size_t tail;
|
volatile size_t tail;
|
||||||
volatile mutable size_t used;
|
volatile size_t used;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@@ -34,13 +35,13 @@ public:
|
|||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** add one value to the buffer. blocks until space is available */
|
// /** add one value to the buffer. blocks until space is available */
|
||||||
void addBlocking(const Scalar value) {
|
// void addBlocking(const Scalar value) {
|
||||||
while (used == size) {os_delay_us(1000);}
|
// while (used == size) {os_delay_us(1000);}
|
||||||
data[head] = value;
|
// data[head] = value;
|
||||||
head = (head + 1) % size;
|
// head = (head + 1) % size;
|
||||||
++used;
|
// ++used;
|
||||||
}
|
// }
|
||||||
|
|
||||||
/** add one value to the buffer, if there is enough space */
|
/** add one value to the buffer, if there is enough space */
|
||||||
void addOrIgnore(const Scalar value) {
|
void addOrIgnore(const Scalar value) {
|
||||||
@@ -59,23 +60,23 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** add multiple values to the buffer. blocks until space is available */
|
// /** add multiple values to the buffer. blocks until space is available */
|
||||||
void addBlocking(const Scalar* value, const size_t len) {
|
// void addBlocking(const Scalar* value, const size_t len) {
|
||||||
debugMod1(NAME, "addBlocking(%d)", len);
|
// debugMod1(NAME, "addBlocking(%d)", len);
|
||||||
for (size_t i = 0; i < len; ++i) {
|
// for (size_t i = 0; i < len; ++i) {
|
||||||
addBlocking(value[i]);
|
// addBlocking(value[i]);
|
||||||
}
|
// }
|
||||||
debugMod1(NAME, "used: %d", used);
|
// debugMod1(NAME, "used: %d", used);
|
||||||
}
|
// }
|
||||||
|
|
||||||
/** add multiple values to the buffer, if there is enough space */
|
// /** add multiple values to the buffer, if there is enough space */
|
||||||
void addOrIgnore(const Scalar* value, const size_t len) {
|
// void addOrIgnore(const Scalar* value, const size_t len) {
|
||||||
debugMod1(NAME, "addOrIgnore(%d)", len);
|
// debugMod1(NAME, "addOrIgnore(%d)", len);
|
||||||
for (size_t i = 0; i < len; ++i) {
|
// for (size_t i = 0; i < len; ++i) {
|
||||||
addOrIgnore(value[i]);
|
// addOrIgnore(value[i]);
|
||||||
}
|
// }
|
||||||
debugMod1(NAME, "used: %d", used);
|
// debugMod1(NAME, "used: %d", used);
|
||||||
}
|
// }
|
||||||
|
|
||||||
/** add multiple values to the buffer, if there is enough space */
|
/** add multiple values to the buffer, if there is enough space */
|
||||||
void addOrCallback(const Scalar* value, const size_t len, RingBufferFullCallback cb) {
|
void addOrCallback(const Scalar* value, const size_t len, RingBufferFullCallback cb) {
|
||||||
@@ -86,6 +87,18 @@ public:
|
|||||||
debugMod1(NAME, "used: %d", used);
|
debugMod1(NAME, "used: %d", used);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** add as many entries as possible */
|
||||||
|
size_t addOrIgnore(const Scalar* value, const size_t len) {
|
||||||
|
const size_t toAdd = min(len, getNumFree());
|
||||||
|
for (size_t i = 0; i < toAdd; ++i) {
|
||||||
|
data[head] = value[i];
|
||||||
|
head = (head + 1) % size;
|
||||||
|
}
|
||||||
|
used += toAdd;
|
||||||
|
debugMod3(NAME, "addOrIgnore(%d) added %d bytes. used: %d", len, toAdd, used);
|
||||||
|
return toAdd;
|
||||||
|
}
|
||||||
|
|
||||||
// /** anything available? */
|
// /** anything available? */
|
||||||
// bool hasNext() const {
|
// bool hasNext() const {
|
||||||
// return used != 0;
|
// return used != 0;
|
||||||
@@ -99,7 +112,7 @@ public:
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Scalar& getConst() const {
|
const Scalar& getConst() {
|
||||||
const uint8_t idx = tail;
|
const uint8_t idx = tail;
|
||||||
tail = (tail + 1) % size;
|
tail = (tail + 1) % size;
|
||||||
--used;
|
--used;
|
||||||
|
|||||||
@@ -1,13 +1,60 @@
|
|||||||
#ifndef VS1003_H
|
#ifndef VS1003_H
|
||||||
#define VS1003_H
|
#define VS1003_H
|
||||||
|
|
||||||
#include "../../io/fastGPIO.h"
|
|
||||||
#include "../../io/SoftSPI.h"
|
#include "../../io/SoftSPI.h"
|
||||||
#include "../../Debug.h"
|
#include "../../Debug.h"
|
||||||
//#include "IPlayable.h"
|
#include "../../Platforms.h"
|
||||||
//#include "AudioData.h"
|
|
||||||
#include "../../data/ChunkBuffer.h"
|
|
||||||
|
|
||||||
|
#if (PLATFORM == NODE_MCU) || (PLATFORM == WEMOS_D1_MINI)
|
||||||
|
|
||||||
|
#include "../../io/fastGPIO.h"
|
||||||
|
|
||||||
|
#define SPI_INIT() spi::init();
|
||||||
|
#define SPI_WRITE_8(byte) spi::writeByte(byte)
|
||||||
|
#define SPI_WRITE_16(word) spi::writeWord(word)
|
||||||
|
#define SPI_READ_8(byte) spi::readByte(byte)
|
||||||
|
#define SPI_READ_16(word) spi::readWord(word)
|
||||||
|
#define SPI_READ_WRITE_8(byte) spi::readWriteByte(byte)
|
||||||
|
#define SPI_READ_WRITE_16(word) spi::readWriteWord(word)
|
||||||
|
#define SPI_DELAY() //os_delay_us(10)
|
||||||
|
|
||||||
|
#define CFG_DREG() GPIO16_INPUT_SET
|
||||||
|
#define GET_DREQ() GPIO16_IN // PIN D0
|
||||||
|
|
||||||
|
#define MP3_CTRL_DESELECT() spi::chipDeselect();
|
||||||
|
#define MP3_CTRL_SELECT() spi::chipSelect();
|
||||||
|
|
||||||
|
#define CFG_DATA_SELECT() GPIO5_OUTPUT_SET
|
||||||
|
#define MP3_DATA_DESELECT() GPIO5_H
|
||||||
|
#define MP3_DATA_SELECT() GPIO5_L
|
||||||
|
|
||||||
|
#elif (PLATFORM == WROOM32_DEVKIT)
|
||||||
|
|
||||||
|
#include "driver/gpio.h"
|
||||||
|
|
||||||
|
#define SPI_INIT() spi::init();
|
||||||
|
#define SPI_WRITE_8(byte) spi::writeByte(byte)
|
||||||
|
#define SPI_WRITE_16(word) spi::writeWord(word)
|
||||||
|
#define SPI_READ_8(byte) spi::readByte(byte)
|
||||||
|
#define SPI_READ_16(word) spi::readWord(word)
|
||||||
|
#define SPI_READ_WRITE_8(byte) spi::readWriteByte(byte)
|
||||||
|
#define SPI_READ_WRITE_16(word) spi::readWriteWord(word)
|
||||||
|
#define SPI_DELAY() //os_delay_us(10)
|
||||||
|
|
||||||
|
#define CFG_DREG() gpio_set_direction(GPIO_NUM_26, GPIO_MODE_INPUT)
|
||||||
|
#define GET_DREQ() gpio_get_level(GPIO_NUM_26)
|
||||||
|
|
||||||
|
#define MP3_CTRL_DESELECT() spi::chipDeselect();
|
||||||
|
#define MP3_CTRL_SELECT() spi::chipSelect();
|
||||||
|
|
||||||
|
#define CFG_DATA_SELECT() gpio_set_direction(GPIO_NUM_33, GPIO_MODE_OUTPUT)
|
||||||
|
#define MP3_DATA_DESELECT() gpio_set_level(GPIO_NUM_33, 1)
|
||||||
|
#define MP3_DATA_SELECT() gpio_set_level(GPIO_NUM_33, 0)
|
||||||
|
|
||||||
|
#else
|
||||||
|
#error "no platform"
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* control a VS1003 audio chip attached to the SPI port
|
* control a VS1003 audio chip attached to the SPI port
|
||||||
@@ -18,24 +65,6 @@ private:
|
|||||||
|
|
||||||
static constexpr const char* NAME = "VS1003";
|
static constexpr const char* NAME = "VS1003";
|
||||||
|
|
||||||
//SoftSPI spi;
|
|
||||||
#define SPI_INIT() spi::init();
|
|
||||||
#define SPI_WRITE_8(byte) spi::writeByte(byte)
|
|
||||||
#define SPI_WRITE_16(word) spi::writeWord(word)
|
|
||||||
#define SPI_READ_8(byte) spi::readByte(byte)
|
|
||||||
#define SPI_READ_16(word) spi::readWord(word)
|
|
||||||
#define SPI_READ_WRITE_8(byte) spi::readWriteByte(byte)
|
|
||||||
#define SPI_READ_WRITE_16(word) spi::readWriteWord(word)
|
|
||||||
//#define SPI_DELAY() os_delay_us(10)
|
|
||||||
#define SPI_DELAY() //os_delay_us(10)
|
|
||||||
|
|
||||||
#define GET_DREQ() GPIO16_IN // PIN D0
|
|
||||||
|
|
||||||
#define MP3_CTRL_DESELECT() spi::chipDeselect();
|
|
||||||
#define MP3_CTRL_SELECT() spi::chipSelect();
|
|
||||||
#define MP3_DATA_DESELECT() GPIO5_H
|
|
||||||
#define MP3_DATA_SELECT() GPIO5_L
|
|
||||||
|
|
||||||
enum OP {
|
enum OP {
|
||||||
WRITE = 0x2,
|
WRITE = 0x2,
|
||||||
READ = 0x3,
|
READ = 0x3,
|
||||||
@@ -107,8 +136,8 @@ public:
|
|||||||
|
|
||||||
SPI_INIT();
|
SPI_INIT();
|
||||||
|
|
||||||
GPIO5_OUTPUT_SET; // Pin D1 - XDCS
|
CFG_DATA_SELECT(); // XDCS
|
||||||
GPIO16_INPUT_SET; // Pin D0 - DREQ
|
CFG_DREG(); // DREQ
|
||||||
|
|
||||||
this->state = PlayState::STOPPED;
|
this->state = PlayState::STOPPED;
|
||||||
|
|
||||||
@@ -134,6 +163,14 @@ public:
|
|||||||
return (255 - (values & 0xFF));
|
return (255 - (values & 0xFF));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void dbg() {
|
||||||
|
debugMod1(NAME, "mode: %d", readRegister(Register::SCI_MODE));
|
||||||
|
debugMod1(NAME, "vol: %d", readRegister(Register::SCI_VOL));
|
||||||
|
debugMod1(NAME, "status: %d", readRegister(Register::SCI_STATUS));
|
||||||
|
debugMod1(NAME, "clk: %d", readRegister(Register::SCI_CLOCKF));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// void play(AudioData ad) {
|
// void play(AudioData ad) {
|
||||||
// this->playable = ad;
|
// this->playable = ad;
|
||||||
// this->state = PlayState::PLAYING;
|
// this->state = PlayState::PLAYING;
|
||||||
@@ -145,24 +182,25 @@ public:
|
|||||||
// this->state = PlayState::PLAYING;
|
// this->state = PlayState::PLAYING;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
void ICACHE_FLASH_ATTR record(RecordSource source) {
|
/*
|
||||||
|
void IN_FLASH record(RecordSource source) {
|
||||||
|
|
||||||
state = PlayState::RECORDING;
|
state = PlayState::RECORDING;
|
||||||
writeRegister(Register::SCI_CLOCKF, 0x4430); /* 2.0x 12.288MHz */
|
writeRegister(Register::SCI_CLOCKF, 0x4430); // 2.0x 12.288MHz
|
||||||
os_delay_us(100);
|
DELAY_US(100);
|
||||||
|
|
||||||
writeRegister(Register::SCI_AICTRL0, 12); /* Div -> 12=8kHz 8=12kHz 6=16kHz */
|
writeRegister(Register::SCI_AICTRL0, 12); // Div -> 12=8kHz 8=12kHz 6=16kHz
|
||||||
os_delay_us(100);
|
DELAY_US(100);
|
||||||
|
|
||||||
writeRegister(Register::SCI_AICTRL1, 0); /* Auto gain */
|
writeRegister(Register::SCI_AICTRL1, 0); // Auto gain
|
||||||
os_delay_us(100);
|
DELAY_US(100);
|
||||||
|
|
||||||
setVolume(255);
|
setVolume(255);
|
||||||
|
|
||||||
os_printf("mode: %d", readRegister(Register::SCI_MODE));
|
os_printf("mode: %d", readRegister(Register::SCI_MODE));
|
||||||
|
|
||||||
writeRegister(Register::SCI_MODE, readRegister(Register::SCI_MODE) | (int)Mode::SM_ADPCM | (int)Mode::SM_RESET);
|
writeRegister(Register::SCI_MODE, readRegister(Register::SCI_MODE) | (int)Mode::SM_ADPCM | (int)Mode::SM_RESET);
|
||||||
os_delay_us(100);
|
DELAY_US(100);
|
||||||
|
|
||||||
os_printf("mode: %d", readRegister(Register::SCI_MODE));
|
os_printf("mode: %d", readRegister(Register::SCI_MODE));
|
||||||
|
|
||||||
@@ -174,11 +212,12 @@ public:
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
awaitDREQ();
|
awaitDREQ();
|
||||||
os_delay_us(100);
|
DELAY_US(100);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
PlayState ICACHE_FLASH_ATTR getState() const {
|
PlayState IN_FLASH getState() const {
|
||||||
return this->state;
|
return this->state;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -187,7 +226,7 @@ public:
|
|||||||
this->state = PlayState::PLAYING;
|
this->state = PlayState::PLAYING;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ICACHE_FLASH_ATTR run() {
|
size_t IN_FLASH run() {
|
||||||
if(this->state == PlayState::PLAYING) {
|
if(this->state == PlayState::PLAYING) {
|
||||||
if (playBuf.empty()) {
|
if (playBuf.empty()) {
|
||||||
//uint8_t stopSequence[4] = {0};
|
//uint8_t stopSequence[4] = {0};
|
||||||
@@ -196,11 +235,13 @@ public:
|
|||||||
} else {
|
} else {
|
||||||
//const ChunkBuffer::Data chunk = playBuf.get(32);
|
//const ChunkBuffer::Data chunk = playBuf.get(32);
|
||||||
//playChunk32(chunk.ptr, chunk.size);
|
//playChunk32(chunk.ptr, chunk.size);
|
||||||
sendPlayBuffer();
|
return sendPlayBuffer();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
uint32_t getRecordData(uint8_t* buffer, uint32_t maxLength) {
|
uint32_t getRecordData(uint8_t* buffer, uint32_t maxLength) {
|
||||||
|
|
||||||
uint32_t available = this->getNumAvailableRecordBytes();
|
uint32_t available = this->getNumAvailableRecordBytes();
|
||||||
@@ -237,6 +278,15 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
uint16_t getSampleRate() const {
|
||||||
|
return readRegister(Register::SCI_AUDATA) & 0xFFFE; // exclude last bit (mono/stereo)
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isStereo() const {
|
||||||
|
return readRegister(Register::SCI_AUDATA) & 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
PlayBuf& getPlayBuffer() {
|
PlayBuf& getPlayBuffer() {
|
||||||
@@ -255,7 +305,7 @@ private:
|
|||||||
return (uint32_t)readRegister(Register::SCI_HDAT1) * sizeof(uint16_t);
|
return (uint32_t)readRegister(Register::SCI_HDAT1) * sizeof(uint16_t);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ICACHE_FLASH_ATTR playChunk32(const uint8_t* buffer, const uint32_t len) const {
|
void IN_FLASH playChunk32(const uint8_t* buffer, const uint32_t len) const {
|
||||||
debugMod1(NAME, "playChunk32() len:%d", len);
|
debugMod1(NAME, "playChunk32() len:%d", len);
|
||||||
MP3_CTRL_DESELECT();
|
MP3_CTRL_DESELECT();
|
||||||
MP3_DATA_SELECT();
|
MP3_DATA_SELECT();
|
||||||
@@ -267,10 +317,10 @@ private:
|
|||||||
MP3_DATA_DESELECT();
|
MP3_DATA_DESELECT();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ICACHE_FLASH_ATTR sendPlayBuffer() {
|
size_t IN_FLASH sendPlayBuffer() {
|
||||||
MP3_CTRL_DESELECT();
|
MP3_CTRL_DESELECT();
|
||||||
MP3_DATA_SELECT();
|
MP3_DATA_SELECT();
|
||||||
int written = 0;
|
size_t written = 0;
|
||||||
while(canConsume() && !playBuf.empty()) {
|
while(canConsume() && !playBuf.empty()) {
|
||||||
const uint8_t byte = playBuf.get();
|
const uint8_t byte = playBuf.get();
|
||||||
if (byte == -1) {break;}
|
if (byte == -1) {break;}
|
||||||
@@ -279,6 +329,7 @@ private:
|
|||||||
}
|
}
|
||||||
if (written) {debugMod1(NAME, "sendPlayBuffer(): %d bytes", written);}
|
if (written) {debugMod1(NAME, "sendPlayBuffer(): %d bytes", written);}
|
||||||
MP3_DATA_DESELECT();
|
MP3_DATA_DESELECT();
|
||||||
|
return written;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -342,11 +393,11 @@ private:
|
|||||||
debugMod(NAME, "reset()");
|
debugMod(NAME, "reset()");
|
||||||
|
|
||||||
writeRegister(SCI_MODE, (2052 | (uint16_t)modeMask)); // TODO: remove SM_TESTS
|
writeRegister(SCI_MODE, (2052 | (uint16_t)modeMask)); // TODO: remove SM_TESTS
|
||||||
os_delay_us(1);
|
DELAY_US(1);
|
||||||
awaitDREQ();
|
awaitDREQ();
|
||||||
writeRegister(SCI_CLOCKF, 0x9800);
|
writeRegister(SCI_CLOCKF, 0x9800);
|
||||||
setVolume(0);
|
setVolume(0);
|
||||||
os_delay_us(1);
|
DELAY_US(1);
|
||||||
|
|
||||||
MP3_DATA_SELECT();
|
MP3_DATA_SELECT();
|
||||||
SPI_WRITE_8(0);
|
SPI_WRITE_8(0);
|
||||||
@@ -355,7 +406,7 @@ private:
|
|||||||
SPI_WRITE_8(0);
|
SPI_WRITE_8(0);
|
||||||
MP3_DATA_DESELECT();
|
MP3_DATA_DESELECT();
|
||||||
|
|
||||||
os_delay_us(100);
|
DELAY_US(100);
|
||||||
MP3_CTRL_DESELECT();
|
MP3_CTRL_DESELECT();
|
||||||
|
|
||||||
debugMod(NAME, "reset() complete");
|
debugMod(NAME, "reset() complete");
|
||||||
|
|||||||
@@ -1,109 +1,18 @@
|
|||||||
#ifndef WS2812B_H
|
#ifndef WS2812B_H
|
||||||
#define WS2812B_H
|
#define WS2812B_H
|
||||||
|
|
||||||
#include "../../io/fastGPIO.h"
|
|
||||||
|
|
||||||
struct Color {
|
#include "../../data/Color.h"
|
||||||
|
#include "../../Platforms.h"
|
||||||
uint8_t r;
|
|
||||||
uint8_t g;
|
|
||||||
uint8_t b;
|
|
||||||
|
|
||||||
/** no-init */
|
|
||||||
Color() {
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
/** Hidden ctor. RGB */
|
|
||||||
Color(const uint8_t r, const uint8_t g, const uint8_t b) : r(r), g(g), b(b) {
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
/** get X-percent [0:100] of this color = darker/brighter */
|
|
||||||
Color inline getPercent(const int percent) const {
|
|
||||||
return Color(r*percent/100, g*percent/100, b*percent/100);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** mix the two given colors */
|
|
||||||
static Color mix(const Color c1, const Color c2, int percentC1) {
|
|
||||||
return Color(
|
|
||||||
((c1.r * percentC1) + (c2.r * (100-percentC1))) / 100,
|
|
||||||
((c1.g * percentC1) + (c2.g * (100-percentC1))) / 100,
|
|
||||||
((c1.b * percentC1) + (c2.b * (100-percentC1))) / 100
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline Color fromRGB(const uint8_t r, const uint8_t g, const uint8_t b) {
|
|
||||||
return Color(r,g,b);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline Color fromHSV(const uint8_t h, const uint8_t s, const uint8_t v) {
|
|
||||||
Color c; c.setHSV(h,s,v); return c;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setHSV(const uint8_t h, const uint8_t s, const uint8_t v) {
|
|
||||||
|
|
||||||
uint8_t region, remainder, p, q, t;
|
|
||||||
|
|
||||||
region = h / 43;
|
|
||||||
remainder = (h - (region * 43)) * 6;
|
|
||||||
|
|
||||||
p = (v * (255 - s)) >> 8;
|
|
||||||
q = (v * (255 - ((s * remainder) >> 8))) >> 8;
|
|
||||||
t = (v * (255 - ((s * (255 - remainder)) >> 8))) >> 8;
|
|
||||||
|
|
||||||
switch (region) {
|
|
||||||
case 0:
|
|
||||||
r = v; g = t; b = p;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
r = q; g = v; b = p;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
r = p; g = v; b = t;
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
r = p; g = q; b = v;
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
r = t; g = p; b = v;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
r = v; g = p; b = q;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void setRGB(const uint8_t r, const uint8_t g, const uint8_t b) {
|
|
||||||
this->r = r;
|
|
||||||
this->g = g;
|
|
||||||
this->b = b;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setOff() {
|
|
||||||
this->r = 0;
|
|
||||||
this->g = 0;
|
|
||||||
this->b = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** add two colors */
|
|
||||||
Color operator + (const Color o) const {
|
|
||||||
return Color(r+o.r, g+o.g, b+o.g);
|
|
||||||
}
|
|
||||||
|
|
||||||
Color operator * (const float f) const {
|
|
||||||
return Color(r*f, g*f, b*f);
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
#if ESP8266
|
||||||
|
|
||||||
template <int numLEDs> class WS2812B {
|
#include "../../io/fastGPIO.h"
|
||||||
|
|
||||||
|
template <int numLEDs> class WS2812B {
|
||||||
|
|
||||||
#define LED_SET_PIN_TO_OUTPUT GPIO5_OUTPUT_SET
|
#define LED_SET_PIN_TO_OUTPUT GPIO5_OUTPUT_SET
|
||||||
#define LED_SET_PIN_H GPIO5_H
|
#define LED_SET_PIN_H GPIO5_H
|
||||||
@@ -194,14 +103,14 @@ template <int numLEDs> class WS2812B {
|
|||||||
private:
|
private:
|
||||||
|
|
||||||
inline void sendByte(uint8_t b) {
|
inline void sendByte(uint8_t b) {
|
||||||
// for (uint8_t i = 0; i < 8; ++i) {
|
// for (uint8_t i = 0; i < 8; ++i) {
|
||||||
// if (b & 0b10000000) {
|
// if (b & 0b10000000) {
|
||||||
// send1();
|
// send1();
|
||||||
// } else {
|
// } else {
|
||||||
// send0();
|
// send0();
|
||||||
// }
|
// }
|
||||||
// b <<= 1;
|
// b <<= 1;
|
||||||
// }
|
// }
|
||||||
if (b & 0b10000000) {send1();} else {send0();}
|
if (b & 0b10000000) {send1();} else {send0();}
|
||||||
if (b & 0b01000000) {send1();} else {send0();}
|
if (b & 0b01000000) {send1();} else {send0();}
|
||||||
if (b & 0b00100000) {send1();} else {send0();}
|
if (b & 0b00100000) {send1();} else {send0();}
|
||||||
@@ -278,7 +187,7 @@ template <int numLEDs> class WS2812B {
|
|||||||
delay100();
|
delay100();
|
||||||
delay100();
|
delay100();
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
__attribute__((always_inline)) inline void delay800() {
|
__attribute__((always_inline)) inline void delay800() {
|
||||||
delay100();
|
delay100();
|
||||||
@@ -301,6 +210,667 @@ template <int numLEDs> class WS2812B {
|
|||||||
// for (uint16_t i = 0; i < ticks; ++i) {asm("nop");}
|
// for (uint16_t i = 0; i < ticks; ++i) {asm("nop");}
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#elif ESP32aaa
|
||||||
|
|
||||||
|
//#include <driver/gpio.h>
|
||||||
|
#include <rom/ets_sys.h>
|
||||||
|
#include <xtensa/core-macros.h>
|
||||||
|
#include <driver/rmt.h>
|
||||||
|
#include <soc/rmt_struct.h>
|
||||||
|
|
||||||
|
template <int numLEDs, gpio_num_t outPin> class WS2812B {
|
||||||
|
|
||||||
|
static constexpr const char* TAG = "WS2812";
|
||||||
|
static constexpr rmt_channel_t chan = RMT_CHANNEL_0;
|
||||||
|
|
||||||
|
//#define portDISABLE_INTERRUPTS() do { XTOS_SET_INTLEVEL(XCHAL_EXCM_LEVEL); portbenchmarkINTERRUPT_DISABLE(); } while (0)
|
||||||
|
//#define portENABLE_INTERRUPTS() do { portbenchmarkINTERRUPT_RESTORE(0); XTOS_SET_INTLEVEL(0); } while (0)
|
||||||
|
//#define ENABLE_INTERRUPTS() portENABLE_INTERRUPTS()
|
||||||
|
//#define DISABLE_INTERRUPTS() portDISABLE_INTERRUPTS()
|
||||||
|
|
||||||
|
static constexpr int numBits = (3*8) * 2; // (r,g,b) each 8 bit NOTE! must be < 64 to fit into the buffer!
|
||||||
|
//static constexpr int numItems = 256;//(numLEDs*3)*8;
|
||||||
|
//static constexpr int numItems = (numLEDs*3)*8;
|
||||||
|
rmt_item32_t items[numBits+1]; // + one entry has two bits + 0-terminator (just like within strings)
|
||||||
|
|
||||||
|
/** enable/disable each led */
|
||||||
|
bool enabled[numLEDs] = {true};
|
||||||
|
|
||||||
|
/** color-value for each attached LED */
|
||||||
|
Color colors[numLEDs];
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/** ctor */
|
||||||
|
WS2812B() {
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
void init() {
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "init()");
|
||||||
|
|
||||||
|
rmt_config_t cfg;
|
||||||
|
cfg.rmt_mode = RMT_MODE_TX;
|
||||||
|
cfg.channel = chan;
|
||||||
|
cfg.gpio_num = outPin;
|
||||||
|
cfg.mem_block_num = 1;//chan+1;//8-chan;//chan+1;//8 - chan; //chan+1;//
|
||||||
|
cfg.clk_div = 8;
|
||||||
|
cfg.tx_config.loop_en = false;
|
||||||
|
cfg.tx_config.carrier_en = false;
|
||||||
|
cfg.tx_config.idle_output_en = true;
|
||||||
|
cfg.tx_config.idle_level = (rmt_idle_level_t)0;
|
||||||
|
cfg.tx_config.carrier_freq_hz = 10000;
|
||||||
|
cfg.tx_config.carrier_level = (rmt_carrier_level_t)1;
|
||||||
|
cfg.tx_config.carrier_duty_percent = 50;
|
||||||
|
|
||||||
|
ESP_ERROR_CHECK(rmt_config(&cfg));
|
||||||
|
ESP_ERROR_CHECK(rmt_driver_install(chan, 0, 0));
|
||||||
|
|
||||||
|
// setup constant values once
|
||||||
|
for (int idx = 0; idx < numBits; ++idx) {
|
||||||
|
items[idx].duration0 = 0;
|
||||||
|
items[idx].level0 = 1;
|
||||||
|
items[idx].duration1 = 0;
|
||||||
|
items[idx].level1 = 0;
|
||||||
|
}
|
||||||
|
items[numBits].val = 0; // 0 terminator
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "init OK!");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/** set the color for the given LED */
|
||||||
|
void setColor(const uint8_t idx, const Color rgb) {
|
||||||
|
colors[idx] = rgb;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** set the color for all LEDs */
|
||||||
|
void setColor(const Color rgb) {
|
||||||
|
for (int idx = 0; idx < numLEDs; ++idx) {
|
||||||
|
colors[idx] = rgb;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** enable/disable the given LED */
|
||||||
|
void setEnabled(const uint8_t idx, const bool en) {
|
||||||
|
enabled[idx] = en;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** enable/disable all LEDs */
|
||||||
|
void setEnabled(const bool en) {
|
||||||
|
for (int idx = 0; idx < numLEDs; ++idx) {
|
||||||
|
enabled[idx] = en;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** is the given LED enabled? */
|
||||||
|
bool isEnabled(const uint8_t idx) const {
|
||||||
|
return enabled[idx];
|
||||||
|
}
|
||||||
|
|
||||||
|
Color& getColor(const uint8_t idx) {
|
||||||
|
return colors[idx];
|
||||||
|
}
|
||||||
|
|
||||||
|
int nextLED;
|
||||||
|
|
||||||
|
/** flush configured changes */
|
||||||
|
IRAM_ATTR void flush() {
|
||||||
|
|
||||||
|
nextLED = 0;
|
||||||
|
ESP_LOGI(TAG, "sending %d LEDs", numLEDs);
|
||||||
|
|
||||||
|
// important! otherwise often interrupted within
|
||||||
|
portDISABLE_INTERRUPTS();
|
||||||
|
|
||||||
|
waitForTX();
|
||||||
|
|
||||||
|
const size_t toWrite = 8+8+8+1;// 8-bit R, 8-bit G, 8-bit B, null-terminator
|
||||||
|
|
||||||
|
// add null terminator
|
||||||
|
items[toWrite-1].val = 0;
|
||||||
|
|
||||||
|
// process each LED
|
||||||
|
for (int i = 0; i < numLEDs; i+=1) {
|
||||||
|
|
||||||
|
int idx = 0;
|
||||||
|
if (enabled[i]) {
|
||||||
|
emplaceByte(colors[i].g, idx);
|
||||||
|
emplaceByte(colors[i].r, idx);
|
||||||
|
emplaceByte(colors[i].b, idx);
|
||||||
|
} else {
|
||||||
|
emplaceByte(0, idx);
|
||||||
|
emplaceByte(0, idx);
|
||||||
|
emplaceByte(0, idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
// wait for sending to complete using the RMT Unit's status
|
||||||
|
waitForTX();
|
||||||
|
|
||||||
|
ESP_ERROR_CHECK(rmt_fill_tx_items(this->chan, items, toWrite, 0));
|
||||||
|
ESP_ERROR_CHECK(rmt_tx_start(this->chan, true));
|
||||||
|
|
||||||
|
// reset for next round
|
||||||
|
//idx = 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//waitForTX();
|
||||||
|
|
||||||
|
portENABLE_INTERRUPTS();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
IRAM_ATTR void waitForTX() {
|
||||||
|
|
||||||
|
uint32_t status; // status while sending: 16797696 ??
|
||||||
|
for (int i = 0; i < 2000; ++i) {
|
||||||
|
rmt_get_status(this->chan, &status);
|
||||||
|
if (status == 0) {break;}
|
||||||
|
//if (status != 16797696) {break;}
|
||||||
|
//if ( (status & (1<<24)) == 0 ) {break;} // somewhat OK
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// for (int i = 0; i < 1000; ++i) {
|
||||||
|
// asm volatile("nop");
|
||||||
|
// }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/** send one whole byte */
|
||||||
|
inline void emplaceByte(const uint8_t b, int& idx) {
|
||||||
|
if (b & 0b10000000) {emplace1(idx);} else {emplace0(idx);}
|
||||||
|
if (b & 0b01000000) {emplace1(idx);} else {emplace0(idx);}
|
||||||
|
if (b & 0b00100000) {emplace1(idx);} else {emplace0(idx);}
|
||||||
|
if (b & 0b00010000) {emplace1(idx);} else {emplace0(idx);}
|
||||||
|
if (b & 0b00001000) {emplace1(idx);} else {emplace0(idx);}
|
||||||
|
if (b & 0b00000100) {emplace1(idx);} else {emplace0(idx);}
|
||||||
|
if (b & 0b00000010) {emplace1(idx);} else {emplace0(idx);}
|
||||||
|
if (b & 0b00000001) {emplace1(idx);} else {emplace0(idx);}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** emplace a 0 (short 1 pulse, long 0 pulse) */
|
||||||
|
inline void emplace0(int& idx) {
|
||||||
|
items[idx].duration0 = 2;//1;
|
||||||
|
//items[idx].level0 = 1;
|
||||||
|
items[idx].duration1 = 8;//7;
|
||||||
|
//items[idx].level1 = 0;
|
||||||
|
++idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** emplace a 1 (long 1 pulse, short 0 pulse) */
|
||||||
|
inline void emplace1(int& idx) {
|
||||||
|
items[idx].duration0 = 7;//6;
|
||||||
|
//items[idx].level0 = 1;
|
||||||
|
items[idx].duration1 = 3;//2;
|
||||||
|
//items[idx].level1 = 0;
|
||||||
|
++idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#elif ESP32
|
||||||
|
|
||||||
|
#include <driver/gpio.h>
|
||||||
|
#include <rom/ets_sys.h>
|
||||||
|
#include <xtensa/core-macros.h>
|
||||||
|
#include "driver/timer.h"
|
||||||
|
|
||||||
|
static constexpr timer_group_t grp = TIMER_GROUP_0;
|
||||||
|
static constexpr timer_idx_t idx = TIMER_0;
|
||||||
|
|
||||||
|
template <int numLEDs, gpio_num_t outPin> class WS2812B;
|
||||||
|
|
||||||
|
static IRAM_ATTR void myISR(void* arg) {
|
||||||
|
printf("interrupt\n");
|
||||||
|
//WS2812B* leds = (WS2812B*) arg;
|
||||||
|
//timer_pause(grp, idx);
|
||||||
|
//leds->flushOLD();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <int numLEDs, gpio_num_t outPin> class WS2812B {
|
||||||
|
|
||||||
|
static constexpr const char* TAG = "WS2812";
|
||||||
|
|
||||||
|
/** enable/disable each led */
|
||||||
|
bool enabled[numLEDs] = {true};
|
||||||
|
|
||||||
|
/** color-value for each attached LED */
|
||||||
|
Color colors[numLEDs];
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/** ctor */
|
||||||
|
WS2812B() {
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
void init() {
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "init()");
|
||||||
|
|
||||||
|
gpio_set_direction(outPin, GPIO_MODE_OUTPUT);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/** set the color for the given LED */
|
||||||
|
void setColor(const uint8_t idx, const Color rgb) {
|
||||||
|
colors[idx] = rgb;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** set the color for all LEDs */
|
||||||
|
void setColor(const Color rgb) {
|
||||||
|
for (int idx = 0; idx < numLEDs; ++idx) {
|
||||||
|
colors[idx] = rgb;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** enable/disable the given LED */
|
||||||
|
void setEnabled(const uint8_t idx, const bool en) {
|
||||||
|
enabled[idx] = en;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** enable/disable all LEDs */
|
||||||
|
void setEnabled(const bool en) {
|
||||||
|
for (int idx = 0; idx < numLEDs; ++idx) {
|
||||||
|
enabled[idx] = en;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** is the given LED enabled? */
|
||||||
|
bool isEnabled(const uint8_t idx) const {
|
||||||
|
return enabled[idx];
|
||||||
|
}
|
||||||
|
|
||||||
|
Color& getColor(const uint8_t idx) {
|
||||||
|
return colors[idx];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
timer_config_t config;
|
||||||
|
|
||||||
|
/** flush configured changes */
|
||||||
|
IRAM_ATTR void flush() {
|
||||||
|
|
||||||
|
printf("flush()\n");
|
||||||
|
|
||||||
|
config.alarm_en = 1;
|
||||||
|
config.auto_reload = 1;
|
||||||
|
config.counter_dir = TIMER_COUNT_UP;
|
||||||
|
config.divider = 2;
|
||||||
|
config.intr_type = TIMER_INTR_LEVEL;
|
||||||
|
config.counter_en = TIMER_PAUSE;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
ESP_ERROR_CHECK(timer_init(grp, idx, &config));
|
||||||
|
|
||||||
|
ESP_ERROR_CHECK(timer_set_counter_value(grp, idx, 0));
|
||||||
|
ESP_ERROR_CHECK(timer_set_alarm_value(grp, idx, 2));
|
||||||
|
ESP_ERROR_CHECK(timer_enable_intr(grp, idx));
|
||||||
|
ESP_ERROR_CHECK(timer_isr_register(grp, idx, myISR, (void*)this, ESP_INTR_FLAG_IRAM, NULL));
|
||||||
|
|
||||||
|
printf("start()\n");
|
||||||
|
ESP_ERROR_CHECK(timer_start(grp, idx));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
IRAM_ATTR void flushOLD() {
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "sending %d LEDs", numLEDs);
|
||||||
|
|
||||||
|
// important! otherwise often interrupted within
|
||||||
|
portDISABLE_INTERRUPTS();
|
||||||
|
|
||||||
|
//portMUX_TYPE myMutex = portMUX_INITIALIZER_UNLOCKED;
|
||||||
|
//portENTER_CRITICAL(&myMutex);
|
||||||
|
|
||||||
|
|
||||||
|
// process each LED
|
||||||
|
for (int i = 0; i < numLEDs; ++i) {
|
||||||
|
|
||||||
|
portDISABLE_INTERRUPTS();
|
||||||
|
const volatile Color c = colors[i];
|
||||||
|
|
||||||
|
if (enabled[i]) {
|
||||||
|
sendByte(c.g);
|
||||||
|
sendByte(c.r);
|
||||||
|
sendByte(c.b);
|
||||||
|
} else {
|
||||||
|
sendByte(0);
|
||||||
|
sendByte(0);
|
||||||
|
sendByte(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//portEXIT_CRITICAL(&myMutex);
|
||||||
|
|
||||||
|
portENABLE_INTERRUPTS();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
/** send one whole byte */
|
||||||
|
inline void sendByte(const uint8_t b) {
|
||||||
|
if (b & 0b10000000) {send1();} else {send0();}
|
||||||
|
if (b & 0b01000000) {send1();} else {send0();}
|
||||||
|
if (b & 0b00100000) {send1();} else {send0();}
|
||||||
|
if (b & 0b00010000) {send1();} else {send0();}
|
||||||
|
if (b & 0b00001000) {send1();} else {send0();}
|
||||||
|
if (b & 0b00000100) {send1();} else {send0();}
|
||||||
|
if (b & 0b00000010) {send1();} else {send0();}
|
||||||
|
if (b & 0b00000001) {send1();} else {send0();}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** send a 0 (short 1 pulse, long 0 pulse) */
|
||||||
|
inline void send0() {
|
||||||
|
gpio_set_level(outPin, 1);
|
||||||
|
delayShort();
|
||||||
|
gpio_set_level(outPin, 0);
|
||||||
|
delayLong();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** send a 1 (long 1 pulse, short 0 pulse) */
|
||||||
|
inline void send1() {
|
||||||
|
gpio_set_level(outPin, 1);
|
||||||
|
delayLong();
|
||||||
|
gpio_set_level(outPin, 0);
|
||||||
|
delayShort();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void delayShort() {
|
||||||
|
volatile int i;
|
||||||
|
i = 0; i = 1; i = 2; i = 3;
|
||||||
|
(void) i;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void delayLong() {
|
||||||
|
volatile int j;
|
||||||
|
j = 0; j = 1; j = 2; j = 3;
|
||||||
|
j = 4; j = 5; j = 6; j = 7;
|
||||||
|
j = 8; j = 9; j = 1; j = 2;
|
||||||
|
(void) j;
|
||||||
|
// for (size_t i = 0; i < 16; ++i) {
|
||||||
|
// asm volatile("nop");
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#elif othertest
|
||||||
|
|
||||||
|
//#include <driver/gpio.h>
|
||||||
|
#include <rom/ets_sys.h>
|
||||||
|
#include <xtensa/core-macros.h>
|
||||||
|
#include <driver/rmt.h>
|
||||||
|
#include <soc/rmt_struct.h>
|
||||||
|
|
||||||
|
template <int numLEDs, gpio_num_t outPin> class WS2812B {
|
||||||
|
|
||||||
|
static constexpr const char* TAG = "WS2812";
|
||||||
|
static constexpr rmt_channel_t chan = RMT_CHANNEL_0;
|
||||||
|
|
||||||
|
//#define portDISABLE_INTERRUPTS() do { XTOS_SET_INTLEVEL(XCHAL_EXCM_LEVEL); portbenchmarkINTERRUPT_DISABLE(); } while (0)
|
||||||
|
//#define portENABLE_INTERRUPTS() do { portbenchmarkINTERRUPT_RESTORE(0); XTOS_SET_INTLEVEL(0); } while (0)
|
||||||
|
//#define ENABLE_INTERRUPTS() portENABLE_INTERRUPTS()
|
||||||
|
//#define DISABLE_INTERRUPTS() portDISABLE_INTERRUPTS()
|
||||||
|
|
||||||
|
static constexpr int numBits = (3*8) * 2; // (r,g,b) each 8 bit NOTE! must be < 64 to fit into the buffer!
|
||||||
|
//static constexpr int numItems = 256;//(numLEDs*3)*8;
|
||||||
|
//static constexpr int numItems = (numLEDs*3)*8;
|
||||||
|
rmt_item32_t items[numBits+1]; // + one entry has two bits + 0-terminator (just like within strings)
|
||||||
|
|
||||||
|
/** enable/disable each led */
|
||||||
|
bool enabled[numLEDs] = {true};
|
||||||
|
|
||||||
|
/** color-value for each attached LED */
|
||||||
|
Color colors[numLEDs];
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/** ctor */
|
||||||
|
WS2812B() {
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
void init() {
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "init()");
|
||||||
|
|
||||||
|
rmt_config_t cfg;
|
||||||
|
cfg.rmt_mode = RMT_MODE_TX;
|
||||||
|
cfg.channel = chan;
|
||||||
|
cfg.gpio_num = outPin;
|
||||||
|
cfg.mem_block_num = 1;//chan+1;//8-chan;//chan+1;//8 - chan; //chan+1;//
|
||||||
|
cfg.clk_div = 8;
|
||||||
|
cfg.tx_config.loop_en = false;
|
||||||
|
cfg.tx_config.carrier_en = false;
|
||||||
|
cfg.tx_config.idle_output_en = true;
|
||||||
|
cfg.tx_config.idle_level = (rmt_idle_level_t)0;
|
||||||
|
cfg.tx_config.carrier_freq_hz = 10000;
|
||||||
|
cfg.tx_config.carrier_level = (rmt_carrier_level_t)1;
|
||||||
|
cfg.tx_config.carrier_duty_percent = 50;
|
||||||
|
|
||||||
|
ESP_ERROR_CHECK(rmt_config(&cfg));
|
||||||
|
|
||||||
|
// disable when using custom ISR
|
||||||
|
//ESP_ERROR_CHECK(rmt_driver_install(chan, 0, 0));
|
||||||
|
|
||||||
|
// setup constant values once
|
||||||
|
for (int idx = 0; idx < numBits; ++idx) {
|
||||||
|
items[idx].duration0 = 0;
|
||||||
|
items[idx].level0 = 1;
|
||||||
|
items[idx].duration1 = 0;
|
||||||
|
items[idx].level1 = 0;
|
||||||
|
}
|
||||||
|
items[numBits].val = 0; // 0 terminator
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "init OK!");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/** set the color for the given LED */
|
||||||
|
void setColor(const uint8_t idx, const Color rgb) {
|
||||||
|
colors[idx] = rgb;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** set the color for all LEDs */
|
||||||
|
void setColor(const Color rgb) {
|
||||||
|
for (int idx = 0; idx < numLEDs; ++idx) {
|
||||||
|
colors[idx] = rgb;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** enable/disable the given LED */
|
||||||
|
void setEnabled(const uint8_t idx, const bool en) {
|
||||||
|
enabled[idx] = en;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** enable/disable all LEDs */
|
||||||
|
void setEnabled(const bool en) {
|
||||||
|
for (int idx = 0; idx < numLEDs; ++idx) {
|
||||||
|
enabled[idx] = en;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** is the given LED enabled? */
|
||||||
|
bool isEnabled(const uint8_t idx) const {
|
||||||
|
return enabled[idx];
|
||||||
|
}
|
||||||
|
|
||||||
|
Color& getColor(const uint8_t idx) {
|
||||||
|
return colors[idx];
|
||||||
|
}
|
||||||
|
|
||||||
|
int nextLED;
|
||||||
|
|
||||||
|
/** flush configured changes */
|
||||||
|
/*
|
||||||
|
void flush() {
|
||||||
|
|
||||||
|
nextLED = 0;
|
||||||
|
ESP_LOGI(TAG, "sending %d LEDs", numLEDs);
|
||||||
|
|
||||||
|
// important! otherwise often interrupted within
|
||||||
|
portDISABLE_INTERRUPTS();
|
||||||
|
|
||||||
|
for (int i = 0; i < 1024; ++i) {
|
||||||
|
asm volatile("nop");
|
||||||
|
}
|
||||||
|
|
||||||
|
//waitForTX();
|
||||||
|
|
||||||
|
const size_t toWrite = 8+8+8+1;// 8-bit R, 8-bit G, 8-bit B, null-terminator
|
||||||
|
|
||||||
|
// add null terminator
|
||||||
|
items[toWrite-1].val = 0;
|
||||||
|
|
||||||
|
// process each LED
|
||||||
|
for (int i = 0; i < numLEDs; i+=2) {
|
||||||
|
|
||||||
|
enqueueNext();
|
||||||
|
|
||||||
|
// add null terminator
|
||||||
|
//items[idx].val = 0;
|
||||||
|
|
||||||
|
// wait for sending to complete using the RMT Unit's status
|
||||||
|
waitForTX();
|
||||||
|
|
||||||
|
ESP_ERROR_CHECK(rmt_fill_tx_items(this->chan, items, toWrite, 0));
|
||||||
|
ESP_ERROR_CHECK(rmt_tx_start(this->chan, true));
|
||||||
|
|
||||||
|
// reset for next round
|
||||||
|
//idx = 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//waitForTX();
|
||||||
|
|
||||||
|
portENABLE_INTERRUPTS();
|
||||||
|
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
static constexpr int toWrite = 8+8+8+1;
|
||||||
|
rmt_isr_handle_t isrHandle;
|
||||||
|
|
||||||
|
void flush() {
|
||||||
|
|
||||||
|
nextLED = 0;
|
||||||
|
ESP_LOGI(TAG, "sending %d LEDs", numLEDs);
|
||||||
|
|
||||||
|
enqueueNext();
|
||||||
|
|
||||||
|
ESP_ERROR_CHECK(rmt_isr_register(onISR, this, ESP_INTR_FLAG_LEVEL1, &isrHandle));
|
||||||
|
ESP_ERROR_CHECK(rmt_set_tx_thr_intr_en(this->chan, true, toWrite/2));
|
||||||
|
//ESP_ERROR_CHECK(rmt_set_tx_intr_en(this->chan, true));
|
||||||
|
|
||||||
|
printf("_start\n");
|
||||||
|
ESP_ERROR_CHECK(rmt_tx_start(this->chan, true));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
static IRAM_ATTR void onISR(void* arg) {
|
||||||
|
printf(".\n");
|
||||||
|
WS2812B* led = (WS2812B*) arg;
|
||||||
|
if (led->nextLED < numLEDs) {
|
||||||
|
led->enqueueNext();
|
||||||
|
} else {
|
||||||
|
rmt_tx_stop(led->chan);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void IRAM_ATTR enqueueNext() {
|
||||||
|
|
||||||
|
printf("e\n");
|
||||||
|
int idx = 0;
|
||||||
|
|
||||||
|
if (enabled[nextLED]) {
|
||||||
|
emplaceByte(colors[nextLED].g, idx);
|
||||||
|
emplaceByte(colors[nextLED].r, idx);
|
||||||
|
emplaceByte(colors[nextLED].b, idx);
|
||||||
|
} else {
|
||||||
|
emplaceByte(0, idx);
|
||||||
|
emplaceByte(0, idx);
|
||||||
|
emplaceByte(0, idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
ESP_ERROR_CHECK(rmt_fill_tx_items(this->chan, items, toWrite, 0));
|
||||||
|
|
||||||
|
++nextLED;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void waitForTX() {
|
||||||
|
|
||||||
|
uint32_t status; // status while sending: 16797696 ??
|
||||||
|
for (int i = 0; i < 2000; ++i) {
|
||||||
|
rmt_get_status(this->chan, &status);
|
||||||
|
if (status == 0) {break;}
|
||||||
|
//if (status != 16797696) {break;}
|
||||||
|
//if ( (status & (1<<24)) == 0 ) {break;} // somewhat OK
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// for (int i = 0; i < 1000; ++i) {
|
||||||
|
// asm volatile("nop");
|
||||||
|
// }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/** send one whole byte */
|
||||||
|
inline void emplaceByte(const uint8_t b, int& idx) {
|
||||||
|
if (b & 0b10000000) {emplace1(idx);} else {emplace0(idx);}
|
||||||
|
if (b & 0b01000000) {emplace1(idx);} else {emplace0(idx);}
|
||||||
|
if (b & 0b00100000) {emplace1(idx);} else {emplace0(idx);}
|
||||||
|
if (b & 0b00010000) {emplace1(idx);} else {emplace0(idx);}
|
||||||
|
if (b & 0b00001000) {emplace1(idx);} else {emplace0(idx);}
|
||||||
|
if (b & 0b00000100) {emplace1(idx);} else {emplace0(idx);}
|
||||||
|
if (b & 0b00000010) {emplace1(idx);} else {emplace0(idx);}
|
||||||
|
if (b & 0b00000001) {emplace1(idx);} else {emplace0(idx);}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** emplace a 0 (short 1 pulse, long 0 pulse) */
|
||||||
|
inline void emplace0(int& idx) {
|
||||||
|
items[idx].duration0 = 2;//1;
|
||||||
|
//items[idx].level0 = 1;
|
||||||
|
items[idx].duration1 = 8;//7;
|
||||||
|
//items[idx].level1 = 0;
|
||||||
|
++idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** emplace a 1 (long 1 pulse, short 0 pulse) */
|
||||||
|
inline void emplace1(int& idx) {
|
||||||
|
items[idx].duration0 = 7;//6;
|
||||||
|
//items[idx].level0 = 1;
|
||||||
|
items[idx].duration1 = 3;//2;
|
||||||
|
//items[idx].level1 = 0;
|
||||||
|
++idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif // WS2812B_H
|
#endif // WS2812B_H
|
||||||
|
|||||||
60
io/SoftSPI.h
60
io/SoftSPI.h
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
//#include "IO.h"
|
//#include "IO.h"
|
||||||
#include "../Platforms.h"
|
#include "../Platforms.h"
|
||||||
|
#include "../Debug.h"
|
||||||
|
|
||||||
|
|
||||||
#if (PLATFORM == NODE_MCU) || (PLATFORM == WEMOS_D1_MINI)
|
#if (PLATFORM == NODE_MCU) || (PLATFORM == WEMOS_D1_MINI)
|
||||||
@@ -28,31 +29,43 @@
|
|||||||
|
|
||||||
#define SPI_FAST
|
#define SPI_FAST
|
||||||
|
|
||||||
#elif (PLATFORM == NODE32S)
|
#elif (PLATFORM == WROOM32_DEVKIT)
|
||||||
|
|
||||||
#define SPI_CS_OUTPUT GPIO15_OUTPUT_SET
|
#include "driver/gpio.h"
|
||||||
#define SPI_MOSI_OUTPUT GPIO13_OUTPUT_SET
|
#include <stdint.h>
|
||||||
#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_PIN_MISO GPIO_NUM_35
|
||||||
#define SPI_CS_HI GPIO15_H
|
#define SPI_PIN_MOSI GPIO_NUM_32
|
||||||
|
#define SPI_PIN_CLK GPIO_NUM_27
|
||||||
|
#define SPI_PIN_CS GPIO_NUM_25
|
||||||
|
|
||||||
#define SPI_CLK_LO GPIO14_L
|
#define SPI_CS_OUTPUT gpio_set_direction(SPI_PIN_CS, GPIO_MODE_OUTPUT)
|
||||||
#define SPI_CLK_HI GPIO14_H
|
#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_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_MOSI_LO GPIO13_L
|
#define SPI_CS_LO gpio_set_level(SPI_PIN_CS, 0)
|
||||||
#define SPI_MOSI_HI GPIO13_H
|
#define SPI_CS_HI gpio_set_level(SPI_PIN_CS, 1)
|
||||||
|
|
||||||
#define SPI_MISO_READ GPIO12_IN
|
#define SPI_CLK_LO gpio_set_level(SPI_PIN_CLK, 0)
|
||||||
|
#define SPI_CLK_HI gpio_set_level(SPI_PIN_CLK, 1)
|
||||||
|
|
||||||
|
#define SPI_MOSI_LO gpio_set_level(SPI_PIN_MOSI, 0)
|
||||||
|
#define SPI_MOSI_HI gpio_set_level(SPI_PIN_MOSI, 1)
|
||||||
|
|
||||||
|
#define SPI_MISO_READ gpio_get_level(SPI_PIN_MISO)
|
||||||
|
|
||||||
#define SPI_FAST
|
#define SPI_FAST
|
||||||
|
|
||||||
|
#else
|
||||||
|
#error "not supported"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace spi {
|
namespace spi {
|
||||||
|
|
||||||
|
static constexpr const char* NAME = "SoftSPI";
|
||||||
|
|
||||||
// MTDI GPIO12 MISO (DIN) D6
|
// MTDI GPIO12 MISO (DIN) D6
|
||||||
// MTCK GPIO13 MOSI (DOUT) D7
|
// MTCK GPIO13 MOSI (DOUT) D7
|
||||||
// MTMS GPIO14 CLOCK D5
|
// MTMS GPIO14 CLOCK D5
|
||||||
@@ -86,14 +99,14 @@ namespace spi {
|
|||||||
__asm__ __volatile__("nop");
|
__asm__ __volatile__("nop");
|
||||||
}
|
}
|
||||||
static inline void waitLong() {
|
static inline void waitLong() {
|
||||||
os_delay_us(1);
|
DELAY_US(1);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
static inline void wait() {
|
static inline void wait() {
|
||||||
os_delay_us(2);
|
DELAY_US(2);
|
||||||
}
|
}
|
||||||
static inline void waitLong() {
|
static inline void waitLong() {
|
||||||
os_delay_us(50);
|
DELAY_US(50);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -150,7 +163,8 @@ namespace spi {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void ICACHE_FLASH_ATTR init() {
|
static void IN_FLASH init() {
|
||||||
|
debugMod(NAME, "init()");
|
||||||
SPI_MISO_INPUT; SPI_MISO_NO_PULLUP; // D6: MISO
|
SPI_MISO_INPUT; SPI_MISO_NO_PULLUP; // D6: MISO
|
||||||
SPI_MOSI_OUTPUT; // D7: MOSI
|
SPI_MOSI_OUTPUT; // D7: MOSI
|
||||||
SPI_CLK_OUTPUT; // D5: CLK
|
SPI_CLK_OUTPUT; // D5: CLK
|
||||||
@@ -159,7 +173,7 @@ namespace spi {
|
|||||||
|
|
||||||
|
|
||||||
/** read 16 bits */
|
/** read 16 bits */
|
||||||
static uint16_t ICACHE_FLASH_ATTR readWord() {
|
static uint16_t IN_FLASH readWord() {
|
||||||
return
|
return
|
||||||
(readBit() << 15) |
|
(readBit() << 15) |
|
||||||
(readBit() << 14) |
|
(readBit() << 14) |
|
||||||
@@ -180,7 +194,7 @@ namespace spi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** read 8 bits */
|
/** read 8 bits */
|
||||||
static uint8_t ICACHE_FLASH_ATTR readByte() {
|
static uint8_t IN_FLASH readByte() {
|
||||||
return
|
return
|
||||||
(readBit() << 7) |
|
(readBit() << 7) |
|
||||||
(readBit() << 6) |
|
(readBit() << 6) |
|
||||||
@@ -194,7 +208,7 @@ namespace spi {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void ICACHE_FLASH_ATTR writeWord(const uint16_t word) {
|
static void IN_FLASH writeWord(const uint16_t word) {
|
||||||
writeBit(word & BIT(15));
|
writeBit(word & BIT(15));
|
||||||
writeBit(word & BIT(14));
|
writeBit(word & BIT(14));
|
||||||
writeBit(word & BIT(13));
|
writeBit(word & BIT(13));
|
||||||
@@ -213,7 +227,7 @@ namespace spi {
|
|||||||
writeBit(word & BIT( 0));
|
writeBit(word & BIT( 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ICACHE_FLASH_ATTR writeByte(const uint8_t byte) {
|
static void IN_FLASH writeByte(const uint8_t byte) {
|
||||||
writeBit(byte & BIT( 7));
|
writeBit(byte & BIT( 7));
|
||||||
writeBit(byte & BIT( 6));
|
writeBit(byte & BIT( 6));
|
||||||
writeBit(byte & BIT( 5));
|
writeBit(byte & BIT( 5));
|
||||||
@@ -224,7 +238,7 @@ namespace spi {
|
|||||||
writeBit(byte & BIT( 0));
|
writeBit(byte & BIT( 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint16 ICACHE_FLASH_ATTR readWriteWord(const uint16_t word) {
|
static uint16_t IN_FLASH readWriteWord(const uint16_t word) {
|
||||||
return
|
return
|
||||||
(readWriteBit(word & BIT(15)) << 15) |
|
(readWriteBit(word & BIT(15)) << 15) |
|
||||||
(readWriteBit(word & BIT(14)) << 14) |
|
(readWriteBit(word & BIT(14)) << 14) |
|
||||||
@@ -244,7 +258,7 @@ namespace spi {
|
|||||||
(readWriteBit(word & BIT( 0)) << 0);
|
(readWriteBit(word & BIT( 0)) << 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint8 ICACHE_FLASH_ATTR readWriteByte(const uint8_t byte) {
|
static uint8_t IN_FLASH readWriteByte(const uint8_t byte) {
|
||||||
return
|
return
|
||||||
(readWriteBit(byte & BIT( 7)) << 7) |
|
(readWriteBit(byte & BIT( 7)) << 7) |
|
||||||
(readWriteBit(byte & BIT( 6)) << 6) |
|
(readWriteBit(byte & BIT( 6)) << 6) |
|
||||||
|
|||||||
69
net/DNS.h
Normal file
69
net/DNS.h
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
#ifndef DNS_H
|
||||||
|
#define DNS_H
|
||||||
|
|
||||||
|
#include "../Platforms.h"
|
||||||
|
#include "../Debug.h"
|
||||||
|
|
||||||
|
typedef void (*DNSResolveCallback)(const char* name, const ip_addr_t* ip, void* arg);
|
||||||
|
|
||||||
|
#if ESP8266
|
||||||
|
class DNS {
|
||||||
|
|
||||||
|
static constexpr const char* NAME = "DNS";
|
||||||
|
|
||||||
|
espconn dns;
|
||||||
|
ip_addr_t ip;
|
||||||
|
|
||||||
|
DNSResolveCallback callback;
|
||||||
|
void* arg;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/** resolve hostname. creates callback */
|
||||||
|
void resolveHost(const char* c, DNSResolveCallback callback, void* arg) {
|
||||||
|
debugMod1(NAME, "dns lookup: %s", c);
|
||||||
|
this->callback = callback;
|
||||||
|
this->arg = arg;
|
||||||
|
dns.reverse = (void*) this;
|
||||||
|
espconn_gethostbyname(&dns, c, &ip, _onHostResolved);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _onHostResolved(const char* name, const ip_addr_t* ipaddr, void* arg) {
|
||||||
|
debugMod1(NAME, "dns resolved: %s", c);
|
||||||
|
DNS* dns = (DNS*) arg;
|
||||||
|
dns->callback(name, ipaddr, dns->arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
#elif ESP32
|
||||||
|
|
||||||
|
#include <lwip/dns.h>
|
||||||
|
|
||||||
|
class DNS {
|
||||||
|
|
||||||
|
static constexpr const char* NAME = "DNS";
|
||||||
|
ip_addr_t ip;
|
||||||
|
DNSResolveCallback callback;
|
||||||
|
void* arg;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/** resolve hostname. creates callback */
|
||||||
|
void resolveHost(const char* host, DNSResolveCallback callback, void* arg) {
|
||||||
|
debugMod1(NAME, "dns lookup: %s", host);
|
||||||
|
this->callback = callback;
|
||||||
|
this->arg = arg;
|
||||||
|
dns_gethostbyname(host, &ip, _onHostResolved, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _onHostResolved(const char* name, const ip_addr_t* ipaddr, void* arg) {
|
||||||
|
debugMod1(NAME, "dns resolved: %s", name);
|
||||||
|
DNS* dns = (DNS*) arg;
|
||||||
|
dns->callback(name, ipaddr, dns->arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // DNS_H
|
||||||
33
net/HTTP.h
33
net/HTTP.h
@@ -1,7 +1,11 @@
|
|||||||
#ifndef HTTP_H
|
#ifndef HTTP_H
|
||||||
#define HTTP_H
|
#define HTTP_H
|
||||||
|
|
||||||
|
|
||||||
|
#include "../Platforms.h"
|
||||||
|
|
||||||
#include "TCP.h"
|
#include "TCP.h"
|
||||||
|
#include "DNS.h"
|
||||||
#include "../Debug.h"
|
#include "../Debug.h"
|
||||||
|
|
||||||
class HTTPClient;
|
class HTTPClient;
|
||||||
@@ -10,13 +14,13 @@ typedef void (*HTTPCBodyDataCallback)(HTTPClient* httpc, const uint8_t* data, ui
|
|||||||
typedef void (*HTTPCConnectCallback)(HTTPClient* httpc);
|
typedef void (*HTTPCConnectCallback)(HTTPClient* httpc);
|
||||||
typedef void (*HTTPCDisconnectCallback)(HTTPClient* httpc);
|
typedef void (*HTTPCDisconnectCallback)(HTTPClient* httpc);
|
||||||
|
|
||||||
|
|
||||||
class HTTPClient {
|
class HTTPClient {
|
||||||
|
|
||||||
static constexpr const char* NAME = "HTTPC";
|
static constexpr const char* NAME = "HTTPC";
|
||||||
TCP tcp;
|
TCP tcp;
|
||||||
|
|
||||||
espconn dns;
|
DNS dns;
|
||||||
|
|
||||||
ip_addr_t ip;
|
ip_addr_t ip;
|
||||||
char host[64];
|
char host[64];
|
||||||
char query[128];
|
char query[128];
|
||||||
@@ -70,7 +74,7 @@ public:
|
|||||||
|
|
||||||
debugMod3(NAME, "connect(%s) -> host: '%s' query: '%s'", url, this->host, this->query);
|
debugMod3(NAME, "connect(%s) -> host: '%s' query: '%s'", url, this->host, this->query);
|
||||||
|
|
||||||
resolveHost(this->host);
|
dns.resolveHost(this->host, _onHostResolved, (void*)this);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,6 +84,10 @@ public:
|
|||||||
numBreaks = 0;
|
numBreaks = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void consumed(uint16_t len) {
|
||||||
|
tcp.consumed(len);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
/** from TCP: connected */
|
/** from TCP: connected */
|
||||||
@@ -130,26 +138,23 @@ private:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
/** resolve hostname. creates callback */
|
|
||||||
void resolveHost(const char* c) {
|
|
||||||
debugMod1(NAME, "dns lookup: %s", c);
|
|
||||||
dns.reverse = (void*) this;
|
|
||||||
espconn_gethostbyname(&dns, c, &ip, _onHostResolved);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** send the request header */
|
/** send the request header */
|
||||||
void sendRequest() {
|
void sendRequest() {
|
||||||
char buf[128];
|
char buf[128];
|
||||||
const int len = os_sprintf(buf, "GET %s HTTP/1.1\r\nicy-metadata:1\r\n\r\n", this->query);
|
const int len = sprintf(buf, "GET %s HTTP/1.1\r\n\r\n", this->query);
|
||||||
debugMod(NAME, buf);
|
//const int len = sprintf(buf, "GET %s HTTP/1.1\r\nicy-metadata:1\r\n\r\n", this->query);
|
||||||
|
printf(buf);
|
||||||
|
//debugMod(NAME, (const char*) buf);
|
||||||
tcp.send((const uint8_t*)buf, len);
|
tcp.send((const uint8_t*)buf, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _onHostResolved(const char* name, ip_addr_t* ipaddr, void* arg ) {
|
static void _onHostResolved(const char* name, const ip_addr_t* ipaddr, void* arg ) {
|
||||||
HTTPClient* http = (HTTPClient*) ((espconn*)arg)->reverse;
|
HTTPClient* http = (HTTPClient*) arg;
|
||||||
if (ipaddr) {
|
if (ipaddr) {
|
||||||
//debugMod1(NAME, "dns lookup returned: %s", tmp.toString());
|
//debugMod1(NAME, "dns lookup returned: %s", tmp.toString());
|
||||||
http->tcp.connect(IP(*ipaddr), 80);
|
http->tcp.connect(IP4(*ipaddr), 80);
|
||||||
} else {
|
} else {
|
||||||
debugMod1(NAME, "dns lookup failed: %s", name);
|
debugMod1(NAME, "dns lookup failed: %s", name);
|
||||||
}
|
}
|
||||||
|
|||||||
65
net/IP.h
65
net/IP.h
@@ -1,12 +1,16 @@
|
|||||||
#ifndef IP_H
|
#ifndef IP_H
|
||||||
#define IP_H
|
#define IP_H
|
||||||
|
|
||||||
|
#include "../Platforms.h"
|
||||||
|
|
||||||
#define Port uint16_t
|
#define Port uint16_t
|
||||||
|
|
||||||
struct IP {
|
#if ESP8266
|
||||||
|
|
||||||
|
struct IP4 {
|
||||||
|
|
||||||
//uint32_t val;
|
//uint32_t val;
|
||||||
ip_addr addr;
|
ip_addr_t addr;
|
||||||
|
|
||||||
/** empty ctor */
|
/** empty ctor */
|
||||||
explicit IP() {
|
explicit IP() {
|
||||||
@@ -41,6 +45,61 @@ struct IP {
|
|||||||
return ipaddr_ntoa(&addr);
|
return ipaddr_ntoa(&addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#elif ESP32
|
||||||
|
|
||||||
|
#include <lwip/ip.h>
|
||||||
|
|
||||||
|
struct IP4 {
|
||||||
|
|
||||||
|
ip_addr_t addr;
|
||||||
|
|
||||||
|
/** empty ctor */
|
||||||
|
explicit IP4() {
|
||||||
|
addr.type = IPADDR_TYPE_V4;
|
||||||
|
addr.u_addr.ip4.addr = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** ctor with IP-string */
|
||||||
|
explicit IP4(const char* ipStr) {
|
||||||
|
addr.type = IPADDR_TYPE_V4;
|
||||||
|
set(ipStr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** ctor with ip4_addr */
|
||||||
|
explicit IP4(ip4_addr _addr) {
|
||||||
|
addr.type = IPADDR_TYPE_V4;
|
||||||
|
addr.u_addr.ip4 = _addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** ctor with ip_addr_t */
|
||||||
|
explicit IP4(ip_addr_t _addr) {
|
||||||
|
addr = _addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** set the IP by string: x.x.x.x */
|
||||||
|
void set(const char* ipStr) {
|
||||||
|
//addr.u_addr.ip4 = ip4addr_aton(ipStr);
|
||||||
|
ip4addr_aton(ipStr, &addr.u_addr.ip4);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** convert to ip_addr/ip_addr_t */
|
||||||
|
const ip_addr_t* getPtr() const {
|
||||||
|
return &addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** convert to string */
|
||||||
|
const char* toString() const {
|
||||||
|
//static char str[16];
|
||||||
|
//ipaddr_aton(str, (ip_addr*)&addr);
|
||||||
|
//return str;
|
||||||
|
return ipaddr_ntoa(&addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif // IP_H
|
#endif // IP_H
|
||||||
|
|||||||
199
net/TCP.h
199
net/TCP.h
@@ -1,10 +1,8 @@
|
|||||||
#ifndef TCP_H
|
#ifndef TCP_H
|
||||||
#define TCP_H
|
#define TCP_H
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
#include "mem.h"
|
#include "../Platforms.h"
|
||||||
#include "espconn.h"
|
|
||||||
}
|
|
||||||
|
|
||||||
class TCP;
|
class TCP;
|
||||||
|
|
||||||
@@ -15,9 +13,16 @@ typedef void (*TCPDisconnectCallback)(TCP* tcp);
|
|||||||
#include "../Debug.h"
|
#include "../Debug.h"
|
||||||
#include "IP.h"
|
#include "IP.h"
|
||||||
|
|
||||||
class TCP {
|
#if ESP8266
|
||||||
|
|
||||||
private:
|
extern "C" {
|
||||||
|
#include "mem.h"
|
||||||
|
#include "espconn.h"
|
||||||
|
}
|
||||||
|
|
||||||
|
class TCP {
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
static constexpr const char* NAME = "TCP";
|
static constexpr const char* NAME = "TCP";
|
||||||
|
|
||||||
@@ -30,7 +35,7 @@ private:
|
|||||||
TCPDisconnectCallback onDisconnect = nullptr;
|
TCPDisconnectCallback onDisconnect = nullptr;
|
||||||
void* userData = nullptr;
|
void* userData = nullptr;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
TCP() {
|
TCP() {
|
||||||
init();
|
init();
|
||||||
@@ -104,7 +109,7 @@ public:
|
|||||||
return this->userData;
|
return this->userData;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
/** called for incoming data */
|
/** called for incoming data */
|
||||||
static void _onData(void* ptr, char* data, unsigned short len) {
|
static void _onData(void* ptr, char* data, unsigned short len) {
|
||||||
@@ -149,7 +154,7 @@ private:
|
|||||||
espconn_regist_recvcb(con, _onData);
|
espconn_regist_recvcb(con, _onData);
|
||||||
espconn_regist_connectcb(con, _onConnect);
|
espconn_regist_connectcb(con, _onConnect);
|
||||||
espconn_regist_disconcb(con, _onDisconnect);
|
espconn_regist_disconcb(con, _onDisconnect);
|
||||||
// espconn_regist_reconcb(con, _onDisconnect);
|
// espconn_regist_reconcb(con, _onDisconnect);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -165,6 +170,180 @@ private:
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#elif ESP32
|
||||||
|
|
||||||
|
#include "lwip/err.h"
|
||||||
|
#include "lwip/tcp.h"
|
||||||
|
#include "lwip/ip_addr.h"
|
||||||
|
|
||||||
|
class TCP {
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
static constexpr const char* NAME = "TCP";
|
||||||
|
|
||||||
|
struct tcp_pcb* pcb;
|
||||||
|
|
||||||
|
bool connected = false;
|
||||||
|
|
||||||
|
TCPDataCallback onData = nullptr;
|
||||||
|
TCPConnectCallback onConnect = nullptr;
|
||||||
|
TCPDisconnectCallback onDisconnect = nullptr;
|
||||||
|
void* userData = nullptr;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
TCP() {
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** dtor */
|
||||||
|
~TCP() {
|
||||||
|
cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** send data to the other side */
|
||||||
|
bool send(const uint8_t* data, const size_t dataLen) {
|
||||||
|
err_t res = tcp_write(pcb, data, dataLen, TCP_WRITE_FLAG_COPY);
|
||||||
|
return (res == ERR_OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** connect to the given IP and port */
|
||||||
|
void connect(const IP4 ip, const Port port) {
|
||||||
|
debugMod2(NAME, "connect(%s, %d)", ip.toString(), port);
|
||||||
|
disconnect();
|
||||||
|
tcp_connect(pcb, ip.getPtr(), port, _onConnectCallback);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** terminate connection */
|
||||||
|
void disconnect() {
|
||||||
|
if (!connected) {return;}
|
||||||
|
tcp_close(pcb);
|
||||||
|
connected = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void hold() {
|
||||||
|
// if (connected) {
|
||||||
|
// espconn_recv_hold(con);
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
void unhold() {
|
||||||
|
// if (connected) {
|
||||||
|
// espconn_recv_unhold(con);
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
/** set the callback to call whenever data is received */
|
||||||
|
void setDataCallback(TCPDataCallback callback) {
|
||||||
|
this->onData = callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** set the callback to call when connection is established */
|
||||||
|
void setConnectCallback(TCPConnectCallback callback) {
|
||||||
|
this->onConnect = callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** set the callback to call when connection is lost */
|
||||||
|
void setDisconnectCallback(TCPDisconnectCallback callback) {
|
||||||
|
this->onDisconnect = callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** attach user-data to this object. can bed used within callbacks */
|
||||||
|
void setUserData(void* ptr) {
|
||||||
|
this->userData = ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** get previously attached user data */
|
||||||
|
void* getUserData() const {
|
||||||
|
return this->userData;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** inform backend we consumed some data */
|
||||||
|
void consumed(uint16_t len) {
|
||||||
|
if (len) {
|
||||||
|
tcp_recved(pcb, len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
/** called for incoming data */
|
||||||
|
static err_t _onData(void* arg, struct tcp_pcb* tpcb, struct pbuf* p, err_t err) {
|
||||||
|
|
||||||
|
TCP* tcp = (TCP*) arg;
|
||||||
|
|
||||||
|
// if p == nullptr -> disconnect -> inform listener
|
||||||
|
if (!p) {
|
||||||
|
if (tcp->onDisconnect) {tcp->onDisconnect(tcp);}
|
||||||
|
return ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// process pBuf (might be a chain of buffers)
|
||||||
|
do {
|
||||||
|
|
||||||
|
// pass data to listener
|
||||||
|
if (tcp->onData) {tcp->onData(tcp, (const uint8_t*)p->payload, p->len);}
|
||||||
|
|
||||||
|
// next pBuf in chain (if any)
|
||||||
|
pbuf* next = p->next;
|
||||||
|
|
||||||
|
// free current buffer (we consumed it completely)
|
||||||
|
pbuf_free(p);
|
||||||
|
|
||||||
|
// proceed?
|
||||||
|
p = next;
|
||||||
|
|
||||||
|
} while (p);
|
||||||
|
|
||||||
|
// everything fine
|
||||||
|
return ERR_OK;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/** called when connection failed */
|
||||||
|
static err_t _onConnectCallback(void* arg, struct tcp_pcb* tpcb, err_t err) {
|
||||||
|
TCP* tcp = (TCP*) arg;
|
||||||
|
if (err == ERR_OK) {
|
||||||
|
if (tcp->onConnect) {tcp->onConnect(tcp);}
|
||||||
|
tcp->connected = true;
|
||||||
|
} else {
|
||||||
|
if (tcp->onDisconnect) {tcp->onDisconnect(tcp);}
|
||||||
|
tcp->connected = false;
|
||||||
|
}
|
||||||
|
return ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** initialize the UDP "connection" */
|
||||||
|
void init() {
|
||||||
|
|
||||||
|
debugMod(NAME, "init()");
|
||||||
|
|
||||||
|
pcb = tcp_new();
|
||||||
|
if (!pcb) {debugMod(NAME, "error creating TCP socket");}
|
||||||
|
|
||||||
|
// user-pointer
|
||||||
|
pcb->callback_arg = (void*) this;
|
||||||
|
|
||||||
|
tcp_recv(pcb, _onData);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/** cleanup everything */
|
||||||
|
void cleanup() {
|
||||||
|
|
||||||
|
debugMod(NAME, "cleanup()");
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif // TCP_H
|
#endif // TCP_H
|
||||||
|
|||||||
Reference in New Issue
Block a user