many changes

This commit is contained in:
kazu
2018-09-22 15:44:26 +02:00
parent 528a00b0e9
commit 90e9fee101
11 changed files with 1581 additions and 476 deletions

52
Debug.h
View File

@@ -2,7 +2,9 @@
#define DEBUG_H
#include <cstdint>
#include "Platforms.h"
/*
extern "C" {
#include "ets_sys.h"
#include "c_types.h"
@@ -21,26 +23,11 @@ extern "C" {
#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 debugMod(module, str)
@@ -50,6 +37,35 @@ void hexdump(const uint8_t* buf, uint8_t len) {
#define IF_DEBUG(a)
#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 // DEBUG_H

View File

@@ -5,8 +5,38 @@
// 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
View 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);
}
};

View File

@@ -2,6 +2,7 @@
#define RINGBUFFER_H
#include "../Debug.h"
#include "../Platforms.h"
typedef void (*RingBufferFullCallback)();
@@ -16,7 +17,7 @@ private:
volatile size_t head;
volatile size_t tail;
volatile mutable size_t used;
volatile size_t used;
public:
@@ -34,13 +35,13 @@ public:
init();
}
/** add one value to the buffer. blocks until space is available */
void addBlocking(const Scalar value) {
while (used == size) {os_delay_us(1000);}
data[head] = value;
head = (head + 1) % size;
++used;
}
// /** add one value to the buffer. blocks until space is available */
// void addBlocking(const Scalar value) {
// while (used == size) {os_delay_us(1000);}
// data[head] = value;
// head = (head + 1) % size;
// ++used;
// }
/** add one value to the buffer, if there is enough space */
void addOrIgnore(const Scalar value) {
@@ -59,23 +60,23 @@ public:
}
/** add multiple values to the buffer. blocks until space is available */
void addBlocking(const Scalar* value, const size_t len) {
debugMod1(NAME, "addBlocking(%d)", len);
for (size_t i = 0; i < len; ++i) {
addBlocking(value[i]);
}
debugMod1(NAME, "used: %d", used);
}
// /** add multiple values to the buffer. blocks until space is available */
// void addBlocking(const Scalar* value, const size_t len) {
// debugMod1(NAME, "addBlocking(%d)", len);
// for (size_t i = 0; i < len; ++i) {
// addBlocking(value[i]);
// }
// debugMod1(NAME, "used: %d", used);
// }
/** add multiple values to the buffer, if there is enough space */
void addOrIgnore(const Scalar* value, const size_t len) {
debugMod1(NAME, "addOrIgnore(%d)", len);
for (size_t i = 0; i < len; ++i) {
addOrIgnore(value[i]);
}
debugMod1(NAME, "used: %d", used);
}
// /** add multiple values to the buffer, if there is enough space */
// void addOrIgnore(const Scalar* value, const size_t len) {
// debugMod1(NAME, "addOrIgnore(%d)", len);
// for (size_t i = 0; i < len; ++i) {
// addOrIgnore(value[i]);
// }
// debugMod1(NAME, "used: %d", used);
// }
/** add multiple values to the buffer, if there is enough space */
void addOrCallback(const Scalar* value, const size_t len, RingBufferFullCallback cb) {
@@ -86,6 +87,18 @@ public:
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? */
// bool hasNext() const {
// return used != 0;
@@ -99,7 +112,7 @@ public:
return res;
}
const Scalar& getConst() const {
const Scalar& getConst() {
const uint8_t idx = tail;
tail = (tail + 1) % size;
--used;

View File

@@ -1,13 +1,60 @@
#ifndef VS1003_H
#define VS1003_H
#include "../../io/fastGPIO.h"
#include "../../io/SoftSPI.h"
#include "../../Debug.h"
//#include "IPlayable.h"
//#include "AudioData.h"
#include "../../data/ChunkBuffer.h"
#include "../../Platforms.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
@@ -18,24 +65,6 @@ private:
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 {
WRITE = 0x2,
READ = 0x3,
@@ -107,8 +136,8 @@ public:
SPI_INIT();
GPIO5_OUTPUT_SET; // Pin D1 - XDCS
GPIO16_INPUT_SET; // Pin D0 - DREQ
CFG_DATA_SELECT(); // XDCS
CFG_DREG(); // DREQ
this->state = PlayState::STOPPED;
@@ -134,6 +163,14 @@ public:
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) {
// this->playable = ad;
// this->state = PlayState::PLAYING;
@@ -145,24 +182,25 @@ public:
// this->state = PlayState::PLAYING;
// }
void ICACHE_FLASH_ATTR record(RecordSource source) {
/*
void IN_FLASH record(RecordSource source) {
state = PlayState::RECORDING;
writeRegister(Register::SCI_CLOCKF, 0x4430); /* 2.0x 12.288MHz */
os_delay_us(100);
writeRegister(Register::SCI_CLOCKF, 0x4430); // 2.0x 12.288MHz
DELAY_US(100);
writeRegister(Register::SCI_AICTRL0, 12); /* Div -> 12=8kHz 8=12kHz 6=16kHz */
os_delay_us(100);
writeRegister(Register::SCI_AICTRL0, 12); // Div -> 12=8kHz 8=12kHz 6=16kHz
DELAY_US(100);
writeRegister(Register::SCI_AICTRL1, 0); /* Auto gain */
os_delay_us(100);
writeRegister(Register::SCI_AICTRL1, 0); // Auto gain
DELAY_US(100);
setVolume(255);
os_printf("mode: %d", readRegister(Register::SCI_MODE));
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));
@@ -174,11 +212,12 @@ public:
// }
awaitDREQ();
os_delay_us(100);
DELAY_US(100);
}
*/
PlayState ICACHE_FLASH_ATTR getState() const {
PlayState IN_FLASH getState() const {
return this->state;
}
@@ -187,7 +226,7 @@ public:
this->state = PlayState::PLAYING;
}
void ICACHE_FLASH_ATTR run() {
size_t IN_FLASH run() {
if(this->state == PlayState::PLAYING) {
if (playBuf.empty()) {
//uint8_t stopSequence[4] = {0};
@@ -196,11 +235,13 @@ public:
} else {
//const ChunkBuffer::Data chunk = playBuf.get(32);
//playChunk32(chunk.ptr, chunk.size);
sendPlayBuffer();
return sendPlayBuffer();
}
}
return 0;
}
/*
uint32_t getRecordData(uint8_t* buffer, uint32_t maxLength) {
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() {
@@ -255,7 +305,7 @@ private:
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);
MP3_CTRL_DESELECT();
MP3_DATA_SELECT();
@@ -267,10 +317,10 @@ private:
MP3_DATA_DESELECT();
}
void ICACHE_FLASH_ATTR sendPlayBuffer() {
size_t IN_FLASH sendPlayBuffer() {
MP3_CTRL_DESELECT();
MP3_DATA_SELECT();
int written = 0;
size_t written = 0;
while(canConsume() && !playBuf.empty()) {
const uint8_t byte = playBuf.get();
if (byte == -1) {break;}
@@ -279,6 +329,7 @@ private:
}
if (written) {debugMod1(NAME, "sendPlayBuffer(): %d bytes", written);}
MP3_DATA_DESELECT();
return written;
}
/**
@@ -342,11 +393,11 @@ private:
debugMod(NAME, "reset()");
writeRegister(SCI_MODE, (2052 | (uint16_t)modeMask)); // TODO: remove SM_TESTS
os_delay_us(1);
DELAY_US(1);
awaitDREQ();
writeRegister(SCI_CLOCKF, 0x9800);
setVolume(0);
os_delay_us(1);
DELAY_US(1);
MP3_DATA_SELECT();
SPI_WRITE_8(0);
@@ -355,7 +406,7 @@ private:
SPI_WRITE_8(0);
MP3_DATA_DESELECT();
os_delay_us(100);
DELAY_US(100);
MP3_CTRL_DESELECT();
debugMod(NAME, "reset() complete");

File diff suppressed because it is too large Load Diff

View File

@@ -3,6 +3,7 @@
//#include "IO.h"
#include "../Platforms.h"
#include "../Debug.h"
#if (PLATFORM == NODE_MCU) || (PLATFORM == WEMOS_D1_MINI)
@@ -28,31 +29,43 @@
#define SPI_FAST
#elif (PLATFORM == NODE32S)
#elif (PLATFORM == WROOM32_DEVKIT)
#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
#include "driver/gpio.h"
#include <stdint.h>
#define SPI_CS_LO GPIO15_L
#define SPI_CS_HI GPIO15_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_CLK_LO GPIO14_L
#define SPI_CLK_HI GPIO14_H
#define SPI_CS_OUTPUT gpio_set_direction(SPI_PIN_CS, GPIO_MODE_OUTPUT)
#define SPI_MOSI_OUTPUT gpio_set_direction(SPI_PIN_MOSI, GPIO_MODE_OUTPUT)
#define SPI_MISO_INPUT gpio_set_direction(SPI_PIN_MISO, GPIO_MODE_INPUT)
#define SPI_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_MOSI_HI GPIO13_H
#define SPI_CS_LO gpio_set_level(SPI_PIN_CS, 0)
#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
#else
#error "not supported"
#endif
namespace spi {
static constexpr const char* NAME = "SoftSPI";
// MTDI GPIO12 MISO (DIN) D6
// MTCK GPIO13 MOSI (DOUT) D7
// MTMS GPIO14 CLOCK D5
@@ -86,14 +99,14 @@ namespace spi {
__asm__ __volatile__("nop");
}
static inline void waitLong() {
os_delay_us(1);
DELAY_US(1);
}
#else
static inline void wait() {
os_delay_us(2);
DELAY_US(2);
}
static inline void waitLong() {
os_delay_us(50);
DELAY_US(50);
}
#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_MOSI_OUTPUT; // D7: MOSI
SPI_CLK_OUTPUT; // D5: CLK
@@ -159,7 +173,7 @@ namespace spi {
/** read 16 bits */
static uint16_t ICACHE_FLASH_ATTR readWord() {
static uint16_t IN_FLASH readWord() {
return
(readBit() << 15) |
(readBit() << 14) |
@@ -180,7 +194,7 @@ namespace spi {
}
/** read 8 bits */
static uint8_t ICACHE_FLASH_ATTR readByte() {
static uint8_t IN_FLASH readByte() {
return
(readBit() << 7) |
(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(14));
writeBit(word & BIT(13));
@@ -213,7 +227,7 @@ namespace spi {
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( 6));
writeBit(byte & BIT( 5));
@@ -224,7 +238,7 @@ namespace spi {
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
(readWriteBit(word & BIT(15)) << 15) |
(readWriteBit(word & BIT(14)) << 14) |
@@ -244,7 +258,7 @@ namespace spi {
(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
(readWriteBit(byte & BIT( 7)) << 7) |
(readWriteBit(byte & BIT( 6)) << 6) |

69
net/DNS.h Normal file
View 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

View File

@@ -1,7 +1,11 @@
#ifndef HTTP_H
#define HTTP_H
#include "../Platforms.h"
#include "TCP.h"
#include "DNS.h"
#include "../Debug.h"
class HTTPClient;
@@ -10,13 +14,13 @@ typedef void (*HTTPCBodyDataCallback)(HTTPClient* httpc, const uint8_t* data, ui
typedef void (*HTTPCConnectCallback)(HTTPClient* httpc);
typedef void (*HTTPCDisconnectCallback)(HTTPClient* httpc);
class HTTPClient {
static constexpr const char* NAME = "HTTPC";
TCP tcp;
espconn dns;
DNS dns;
ip_addr_t ip;
char host[64];
char query[128];
@@ -70,7 +74,7 @@ public:
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;
}
void consumed(uint16_t len) {
tcp.consumed(len);
}
private:
/** from TCP: connected */
@@ -130,26 +138,23 @@ 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 */
void sendRequest() {
char buf[128];
const int len = os_sprintf(buf, "GET %s HTTP/1.1\r\nicy-metadata:1\r\n\r\n", this->query);
debugMod(NAME, buf);
const int len = sprintf(buf, "GET %s HTTP/1.1\r\n\r\n", this->query);
//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);
}
static void _onHostResolved(const char* name, ip_addr_t* ipaddr, void* arg ) {
HTTPClient* http = (HTTPClient*) ((espconn*)arg)->reverse;
static void _onHostResolved(const char* name, const ip_addr_t* ipaddr, void* arg ) {
HTTPClient* http = (HTTPClient*) arg;
if (ipaddr) {
//debugMod1(NAME, "dns lookup returned: %s", tmp.toString());
http->tcp.connect(IP(*ipaddr), 80);
http->tcp.connect(IP4(*ipaddr), 80);
} else {
debugMod1(NAME, "dns lookup failed: %s", name);
}

121
net/IP.h
View File

@@ -1,46 +1,105 @@
#ifndef IP_H
#define IP_H
#include "../Platforms.h"
#define Port uint16_t
struct IP {
#if ESP8266
//uint32_t val;
ip_addr addr;
struct IP4 {
/** empty ctor */
explicit IP() {
addr.addr = 0;
}
//uint32_t val;
ip_addr_t addr;
/** ctor with IP-string */
explicit IP(const char* ipStr) {
set(ipStr);
}
/** empty ctor */
explicit IP() {
addr.addr = 0;
}
/** ctor with ip_addr_t */
explicit IP(ip_addr addr) : addr(addr) {
;
}
/** ctor with IP-string */
explicit IP(const char* ipStr) {
set(ipStr);
}
/** set the IP by string: x.x.x.x */
void set(const char* ipStr) {
addr.addr = ipaddr_addr(ipStr);
}
/** ctor with ip_addr_t */
explicit IP(ip_addr addr) : addr(addr) {
;
}
/** convert to ip_addr/ip_addr_t */
const ip_addr* getPtr() const {
return &addr;
}
/** set the IP by string: x.x.x.x */
void set(const char* ipStr) {
addr.addr = ipaddr_addr(ipStr);
}
/** convert to string */
const char* toString() const {
//static char str[16];
//ipaddr_aton(str, (ip_addr*)&addr);
//return str;
return ipaddr_ntoa(&addr);
}
/** convert to ip_addr/ip_addr_t */
const ip_addr* 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);
}
};
#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

419
net/TCP.h
View File

@@ -1,10 +1,8 @@
#ifndef TCP_H
#define TCP_H
extern "C" {
#include "mem.h"
#include "espconn.h"
}
#include "../Platforms.h"
class TCP;
@@ -15,156 +13,337 @@ typedef void (*TCPDisconnectCallback)(TCP* tcp);
#include "../Debug.h"
#include "IP.h"
class TCP {
#if ESP8266
private:
static constexpr const char* NAME = "TCP";
espconn* con;
esp_tcp tcp;
bool connected = false;
TCPDataCallback onData = nullptr;
TCPConnectCallback onConnect = nullptr;
TCPDisconnectCallback onDisconnect = nullptr;
void* userData = nullptr;
public:
TCP() {
init();
extern "C" {
#include "mem.h"
#include "espconn.h"
}
/** dtor */
~TCP() {
cleanup();
}
class TCP {
private:
/** send data to the other side */
bool send(const uint8_t* data, const size_t dataLen) {
const int res = espconn_sent(con, (unsigned char*)data, dataLen);
return (res == 0);
}
static constexpr const char* NAME = "TCP";
/** connect to the given IP and port */
void connect(const IP ip, const Port port) {
disconnect();
debugMod2(NAME, "connect(%s, %d)", ip.toString(), port);
con->proto.tcp->remote_port = port;
con->proto.tcp->local_port = espconn_port();
os_memcpy(con->proto.tcp->remote_ip, ip.getPtr(), 4);
espconn_connect(con);
connected = true;
}
espconn* con;
esp_tcp tcp;
bool connected = false;
TCPDataCallback onData = nullptr;
TCPConnectCallback onConnect = nullptr;
TCPDisconnectCallback onDisconnect = nullptr;
void* userData = nullptr;
/** terminate connection */
void disconnect() {
if (!connected) {return;}
espconn_disconnect(con);
connected = false;
}
public:
void hold() {
if (connected) {
espconn_recv_hold(con);
TCP() {
init();
}
}
void unhold() {
if (connected) {
espconn_recv_unhold(con);
/** dtor */
~TCP() {
cleanup();
}
}
/** 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;
}
/** send data to the other side */
bool send(const uint8_t* data, const size_t dataLen) {
const int res = espconn_sent(con, (unsigned char*)data, dataLen);
return (res == 0);
}
/** set the callback to call when connection is lost */
void setDisconnectCallback(TCPDisconnectCallback callback) {
this->onDisconnect = callback;
}
/** connect to the given IP and port */
void connect(const IP ip, const Port port) {
disconnect();
debugMod2(NAME, "connect(%s, %d)", ip.toString(), port);
con->proto.tcp->remote_port = port;
con->proto.tcp->local_port = espconn_port();
os_memcpy(con->proto.tcp->remote_ip, ip.getPtr(), 4);
espconn_connect(con);
connected = true;
}
/** 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;
}
/** terminate connection */
void disconnect() {
if (!connected) {return;}
espconn_disconnect(con);
connected = false;
}
private:
void hold() {
if (connected) {
espconn_recv_hold(con);
}
}
/** called for incoming data */
static void _onData(void* ptr, char* data, unsigned short len) {
TCP* tcp = (TCP*) ((espconn*)ptr)->reverse;
if (tcp->onData) {tcp->onData(tcp, (const uint8_t*)data, len);}
}
void unhold() {
if (connected) {
espconn_recv_unhold(con);
}
}
/** called when connection is established */
static void _onConnect(void* ptr) {
TCP* tcp = (TCP*) ((espconn*)ptr)->reverse;
if (tcp->onConnect) {tcp->onConnect(tcp);}
tcp->connected = true;
}
/** set the callback to call whenever data is received */
void setDataCallback(TCPDataCallback callback) {
this->onData = callback;
}
/** called when connection is lost */
static void _onDisconnect(void* ptr) {
TCP* tcp = (TCP*) ((espconn*)ptr)->reverse;
if (tcp->onDisconnect) {tcp->onDisconnect(tcp);}
tcp->connected = false;
}
/** 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;
}
private:
/** called for incoming data */
static void _onData(void* ptr, char* data, unsigned short len) {
TCP* tcp = (TCP*) ((espconn*)ptr)->reverse;
if (tcp->onData) {tcp->onData(tcp, (const uint8_t*)data, len);}
}
/** called when connection is established */
static void _onConnect(void* ptr) {
TCP* tcp = (TCP*) ((espconn*)ptr)->reverse;
if (tcp->onConnect) {tcp->onConnect(tcp);}
tcp->connected = true;
}
/** called when connection is lost */
static void _onDisconnect(void* ptr) {
TCP* tcp = (TCP*) ((espconn*)ptr)->reverse;
if (tcp->onDisconnect) {tcp->onDisconnect(tcp);}
tcp->connected = false;
}
/** initialize the UDP "connection" */
void init() {
/** initialize the UDP "connection" */
void init() {
debugMod(NAME, "init()");
debugMod(NAME, "init()");
// allocate connection-objects
con = (espconn*) os_zalloc(sizeof(espconn));
ets_memset( con, 0, sizeof( espconn ) );
// allocate connection-objects
con = (espconn*) os_zalloc(sizeof(espconn));
ets_memset( con, 0, sizeof( espconn ) );
// configure
con->type = ESPCONN_TCP;
con->state = ESPCONN_NONE;
// configure
con->type = ESPCONN_TCP;
con->state = ESPCONN_NONE;
//con->proto.tcp = (esp_tcp*) os_zalloc(sizeof(esp_tcp));
con->proto.tcp = &tcp;
//con->proto.tcp = (esp_tcp*) os_zalloc(sizeof(esp_tcp));
con->proto.tcp = &tcp;
// attach ourselves for the callback
con->reverse = (void*) this; // user-data to refer to this class
espconn_regist_recvcb(con, _onData);
espconn_regist_connectcb(con, _onConnect);
espconn_regist_disconcb(con, _onDisconnect);
// espconn_regist_reconcb(con, _onDisconnect);
// attach ourselves for the callback
con->reverse = (void*) this; // user-data to refer to this class
espconn_regist_recvcb(con, _onData);
espconn_regist_connectcb(con, _onConnect);
espconn_regist_disconcb(con, _onDisconnect);
// espconn_regist_reconcb(con, _onDisconnect);
}
}
/** cleanup everything */
void cleanup() {
/** cleanup everything */
void cleanup() {
debugMod(NAME, "cleanup()");
debugMod(NAME, "cleanup()");
espconn_delete(con);
//os_free(con->proto.tcp);
os_free(con);
con = nullptr;
espconn_delete(con);
//os_free(con->proto.tcp);
os_free(con);
con = nullptr;
}
}
};
};
#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