From 2d37fb67c5e35414fa329deaba8e508f6096830d Mon Sep 17 00:00:00 2001 From: Markus Sattler Date: Sat, 9 May 2015 16:19:32 +0200 Subject: [PATCH 1/7] many speed optimizations in Adafruit_ILI9341 lib (3x times faster) add new SPI function: void write(uint8_t data); void write16(uint16_t data); void write16(uint16_t data, bool msb); void writeBytes(uint8_t * data, uint32_t size); void writePattern(uint8_t * data, uint8_t size, uint32_t repeat); Adafruit_ILI9341: | Benchmark | Old (ms) | New (ms) | Speedup | | ------------------------- | -------- | -------- | ----------- | | Screen fill | 1248369 | 278707 | +347,91% | | Text | 86102 | 53785 | +60,09% | | Lines | 825400 | 536374 | +53,89% | | Horiz/Vert Lines | 101875 | 24653 | +313,24% | | Rectangles (outline) | 65720 | 17295 | +279,99% | | Rectangles (filled) | 2592250 | 579157 | +347,59% | | Circles (filled) | 411475 | 179454 | +129,29% | | Circles (outline) | 360002 | 233584 | +54,12% | | Triangles (outline) | 261772 | 170118 | +53,88% | | Triangles (filled) | 866951 | 246237 | +252,08% | | Rounded rects (outline) | 154131 | 81570 | +88,96% | | Rounded rects (filled) | 2828112 | 660983 | +327,86% | | | | | | | Total | 9802159 | 3061917 | +220,13% | --- .../esp8266com/esp8266/libraries/SPI/SPI.cpp | 122 +++++- .../esp8266com/esp8266/libraries/SPI/SPI.h | 10 + .../Adafruit_ILI9341/Adafruit_ILI9341.cpp | 387 ++++++++++-------- libraries/Adafruit_ILI9341/Adafruit_ILI9341.h | 61 ++- 4 files changed, 379 insertions(+), 201 deletions(-) diff --git a/hardware/esp8266com/esp8266/libraries/SPI/SPI.cpp b/hardware/esp8266com/esp8266/libraries/SPI/SPI.cpp index d9f9ea1eb..6b3d29784 100644 --- a/hardware/esp8266com/esp8266/libraries/SPI/SPI.cpp +++ b/hardware/esp8266com/esp8266/libraries/SPI/SPI.cpp @@ -36,6 +36,7 @@ typedef union { SPIClass SPI; SPIClass::SPIClass() { + useHwCs = false; } void SPIClass::begin() { @@ -54,9 +55,26 @@ void SPIClass::end() { pinMode(SCK, INPUT); pinMode(MISO, INPUT); pinMode(MOSI, INPUT); + if(useHwCs) { + pinMode(SS, INPUT); + } +} + +void SPIClass::setHwCs(bool use) { + if(use) { + pinMode(SS, SPECIAL); ///< GPIO15 + SPI1U |= (SPIUCSSETUP | SPIUCSHOLD); + } else { + if(useHwCs) { + pinMode(SS, INPUT); + SPI1U &= ~(SPIUCSSETUP | SPIUCSHOLD); + } + } + useHwCs = use; } void SPIClass::beginTransaction(SPISettings settings) { + while(SPI1CMD & SPIBUSY) {} setFrequency(settings._clock); setBitOrder(settings._bitOrder); setDataMode(settings._dataMode); @@ -199,12 +217,10 @@ void SPIClass::setClockDivider(uint32_t clockDiv) { } uint8_t SPIClass::transfer(uint8_t data) { - while(SPI1CMD & SPIBUSY) - ; + while(SPI1CMD & SPIBUSY) {} SPI1W0 = data; SPI1CMD |= SPIBUSY; - while(SPI1CMD & SPIBUSY) - ; + while(SPI1CMD & SPIBUSY) {} return (uint8_t) (SPI1W0 & 0xff); } @@ -230,3 +246,101 @@ uint16_t SPIClass::transfer16(uint16_t data) { return out.val; } +void SPIClass::write(uint8_t data) { + while(SPI1CMD & SPIBUSY) {} + SPI1W0 = data; + SPI1CMD |= SPIBUSY; + while(SPI1CMD & SPIBUSY) {} +} + +void SPIClass::write16(uint16_t data) { + write16(data, (SPI1C & (SPICWBO | SPICRBO))); +} + +void SPIClass::write16(uint16_t data, bool msb) { + while(SPI1CMD & SPIBUSY) {} + // Set to 16Bits transfer + SPI1U1 = (SPI1U1 & ~((SPIMMOSI << SPILMOSI))) | ((16 - 1) << SPILMOSI); + if(msb) { + // MSBFIRST Byte first + SPI1W0 = (data >> 8) | (data << 8); + SPI1CMD |= SPIBUSY; + } else { + // LSBFIRST Byte first + SPI1W0 = data; + SPI1CMD |= SPIBUSY; + } + while(SPI1CMD & SPIBUSY) {} + // reset to 8Bit mode + SPI1U1 = (SPI1U1 & ~((SPIMMOSI << SPILMOSI))) | ((8 - 1) << SPILMOSI); +} + +void SPIClass::writeBytes(uint8_t * data, uint32_t size) { + while(size) { + if(size > 64) { + writeBytes_(data, 64); + size -= 64; + data += 64; + } else { + writeBytes_(data, size); + size = 0; + } + } +} + +void SPIClass::writeBytes_(uint8_t * data, uint8_t size) { + while(SPI1CMD & SPIBUSY) {} + // Set Bits to transfer + SPI1U1 = (SPI1U1 & ~((SPIMMOSI << SPILMOSI))) | ((size * 8 - 1) << SPILMOSI); + + volatile uint32_t * fifoPtr = &SPI1W0; + uint32_t * dataPtr = (uint32_t*) data; + uint8_t dataSize = ((size + 3) / 4); + + while(dataSize--) { + *fifoPtr = *dataPtr; + dataPtr++; + fifoPtr++; + } + + SPI1CMD |= SPIBUSY; + while(SPI1CMD & SPIBUSY) {} + // reset to 8Bit mode + SPI1U1 = (SPI1U1 & ~((SPIMMOSI << SPILMOSI))) | ((8 - 1) << SPILMOSI); +} + +void SPIClass::writePattern(uint8_t * data, uint8_t size, uint32_t repeat) { + if(size > 64) return; //max Hardware FIFO + + uint32_t byte = (size * repeat); + uint8_t r = (64 / size); + + while(byte) { + if(byte > 64) { + writePattern_(data, size, r); + byte -= 64; + } else { + writePattern_(data, size, (byte / size)); + byte = 0; + } + } +} + +void SPIClass::writePattern_(uint8_t * data, uint8_t size, uint8_t repeat) { + uint8_t bytes = (size * repeat); + uint8_t buffer[64]; + uint8_t * bufferPtr = &buffer[0]; + uint8_t * dataPtr; + uint8_t dataSize = bytes; + for(uint8_t i = 0; i < repeat; i++) { + dataSize = size; + dataPtr = data; + while(dataSize--) { + *bufferPtr = *dataPtr; + dataPtr++; + bufferPtr++; + } + } + + writeBytes(&buffer[0], bytes); +} diff --git a/hardware/esp8266com/esp8266/libraries/SPI/SPI.h b/hardware/esp8266com/esp8266/libraries/SPI/SPI.h index 3a37c52e1..1030eeaa9 100644 --- a/hardware/esp8266com/esp8266/libraries/SPI/SPI.h +++ b/hardware/esp8266com/esp8266/libraries/SPI/SPI.h @@ -64,6 +64,7 @@ public: SPIClass(); void begin(); void end(); + void setHwCs(bool use); void setBitOrder(uint8_t bitOrder); void setDataMode(uint8_t dataMode); void setFrequency(uint32_t freq); @@ -71,7 +72,16 @@ public: void beginTransaction(SPISettings settings); uint8_t transfer(uint8_t data); uint16_t transfer16(uint16_t data); + void write(uint8_t data); + void write16(uint16_t data); + void write16(uint16_t data, bool msb); + void writeBytes(uint8_t * data, uint32_t size); + void writePattern(uint8_t * data, uint8_t size, uint32_t repeat); void endTransaction(void); +private: + bool useHwCs; + void writeBytes_(uint8_t * data, uint8_t size); + void writePattern_(uint8_t * data, uint8_t size, uint8_t repeat); }; extern SPIClass SPI; diff --git a/libraries/Adafruit_ILI9341/Adafruit_ILI9341.cpp b/libraries/Adafruit_ILI9341/Adafruit_ILI9341.cpp index c6be8c177..caac3a11e 100644 --- a/libraries/Adafruit_ILI9341/Adafruit_ILI9341.cpp +++ b/libraries/Adafruit_ILI9341/Adafruit_ILI9341.cpp @@ -11,6 +11,8 @@ Written by Limor Fried/Ladyada for Adafruit Industries. MIT license, all text above must be included in any redistribution + + Modified 09 May 2015 by Markus Sattler - rewrite the code add ESP8266 support and many optimizations now 220% fastet (320% total) ****************************************************/ #include "Adafruit_ILI9341.h" @@ -40,8 +42,8 @@ Adafruit_ILI9341::Adafruit_ILI9341(int8_t cs, int8_t dc, int8_t mosi, // Constructor when using hardware SPI. Faster, but must use SPI pins // specific to each board type (e.g. 11,13 for Uno, 51,52 for Mega, etc.) -Adafruit_ILI9341::Adafruit_ILI9341(int8_t cs, int8_t dc, int8_t rst) : Adafruit_GFX(ILI9341_TFTWIDTH, ILI9341_TFTHEIGHT) { - _cs = cs; +#ifdef USE_HW_CS +Adafruit_ILI9341::Adafruit_ILI9341(int8_t dc, int8_t rst) : Adafruit_GFX(ILI9341_TFTWIDTH, ILI9341_TFTHEIGHT) { _dc = dc; _rst = rst; hwSPI = true; @@ -49,6 +51,24 @@ Adafruit_ILI9341::Adafruit_ILI9341(int8_t cs, int8_t dc, int8_t rst) : Adafruit_ _mosi = _sclk = 0; #endif } +#else + Adafruit_ILI9341::Adafruit_ILI9341(int8_t cs, int8_t dc, int8_t rst) : Adafruit_GFX(ILI9341_TFTWIDTH, ILI9341_TFTHEIGHT) { + _cs = cs; + _dc = dc; + _rst = rst; + hwSPI = true; + #ifndef ESP8266 + _mosi = _sclk = 0; + #endif + } +#endif + + +#ifdef ESP8266 +void Adafruit_ILI9341::spiwrite16(uint16_t c) { + SPI.write16(c, true); +} +#endif void Adafruit_ILI9341::spiwrite(uint8_t c) { @@ -63,7 +83,7 @@ void Adafruit_ILI9341::spiwrite(uint8_t c) { while(!(SPSR & _BV(SPIF))); SPCR = backupSPCR; #elif defined(TEENSYDUINO) || defined(ESP8266) - SPI.transfer(c); + SPI.write(c); #elif defined (__arm__) SPI.setClockDivider(11); // 8-ish MHz (full! speed!) SPI.setBitOrder(MSBFIRST); @@ -90,62 +110,129 @@ void Adafruit_ILI9341::spiwrite(uint8_t c) { #endif } +void Adafruit_ILI9341::spiwriteBytes(uint8_t * data, uint8_t size) { +#ifdef ESP8266 + SPI.writeBytes(data, size); +#else + while(size--) { + spiwrite(*data); + data++; + } +#endif +} -void Adafruit_ILI9341::writecommand(uint8_t c) { +void Adafruit_ILI9341::spiwritePattern(uint8_t * data, uint8_t size, uint32_t repeat) { +#ifdef ESP8266 + SPI.writePattern(data, size, repeat); +#else + uint8_t * ptr; + uint8_t i; + while(repeat--) { + ptr = data; + i = size; + while(i--) { + spiwrite(*ptr); + ptr++; + } + } +#endif +} + + +inline void Adafruit_ILI9341::spiCsLow(void) { #ifdef USE_DIGITAL_WRITE - digitalWrite(_dc, LOW); digitalWrite(_cs, LOW); #else #ifdef ESP8266 - GPOC = digitalPinToBitMask(_dc); +#ifndef USE_HW_CS GPOC = digitalPinToBitMask(_cs); -#else - *dcport &= ~dcpinmask; - //*clkport &= ~clkpinmask; // clkport is a NULL pointer when hwSPI==true - //digitalWrite(_sclk, LOW); - *csport &= ~cspinmask; #endif -#endif - spiwrite(c); -#ifdef USE_DIGITAL_WRITE - digitalWrite(_cs, HIGH); #else -#ifdef ESP8266 - GPOS = digitalPinToBitMask(_cs); -#else - *csport |= cspinmask; + *csport &= ~cspinmask; #endif #endif } -void Adafruit_ILI9341::writedata(uint8_t c) { -#ifdef USE_DIGITAL_WRITE - digitalWrite(_dc, HIGH); - digitalWrite(_cs, LOW); -#else -#ifdef ESP8266 - GPOS = digitalPinToBitMask(_dc); - GPOC = digitalPinToBitMask(_cs); -#else - *dcport |= dcpinmask; - - //*clkport &= ~clkpinmask; // clkport is a NULL pointer when hwSPI==true - //digitalWrite(_sclk, LOW); - *csport &= ~cspinmask; -#endif -#endif - spiwrite(c); +inline void Adafruit_ILI9341::spiCsHigh(void) { #ifdef USE_DIGITAL_WRITE digitalWrite(_cs, HIGH); #else #ifdef ESP8266 - GPOS = digitalPinToBitMask(_cs); +#ifndef USE_HW_CS + GPOS = digitalPinToBitMask(_cs); +#endif #else - *csport |= cspinmask; + *csport |= cspinmask; #endif #endif +} + +inline void Adafruit_ILI9341::spiDcLow(void){ +#ifdef USE_DIGITAL_WRITE + digitalWrite(_dc, LOW); +#else +#ifdef ESP8266 +#ifndef USE_HW_CS + GPOC = digitalPinToBitMask(_dc); +#endif +#else + *dcport &= ~dcpinmask; +#endif +#endif +} + +inline void Adafruit_ILI9341::spiDcHigh(void) { +#ifdef USE_DIGITAL_WRITE + digitalWrite(_dc, HIGH); +#else +#ifdef ESP8266 + GPOS = digitalPinToBitMask(_dc); +#else + *dcport |= dcpinmask; +#endif +#endif +} + +void Adafruit_ILI9341::writecommand(uint8_t c) { + spiDcLow(); + spiCsLow(); + + spiwrite(c); + + spiCsHigh(); +} + +void Adafruit_ILI9341::writedata(uint8_t c) { + spiDcHigh(); + spiCsLow(); + + spiwrite(c); + + spiCsHigh(); } +void Adafruit_ILI9341::writedata(uint8_t * data, uint8_t size) { + spiDcHigh(); + spiCsLow(); + + spiwriteBytes(data, size); + + spiCsHigh(); +} + +void Adafruit_ILI9341::writeCmdData(uint8_t cmd, uint8_t * data, uint8_t size) { + spiDcLow(); + spiCsLow(); + + spiwrite(cmd); + + spiDcHigh(); + + spiwriteBytes(data, size); + + spiCsHigh(); +} + // If the SPI library has transaction support, these functions // establish settings and protect from interference from other // libraries. Otherwise, they simply do nothing. @@ -153,7 +240,7 @@ void Adafruit_ILI9341::writedata(uint8_t c) { static inline void spi_begin(void) __attribute__((always_inline)); static inline void spi_begin(void) { #ifdef ESP8266 - SPI.beginTransaction(SPISettings(80000000, MSBFIRST, SPI_MODE0)); + SPI.beginTransaction(SPISettings(F_CPU, MSBFIRST, SPI_MODE0)); #else SPI.beginTransaction(SPISettings(8000000, MSBFIRST, SPI_MODE0)); #endif @@ -208,7 +295,9 @@ void Adafruit_ILI9341::begin(void) { } pinMode(_dc, OUTPUT); +#ifndef USE_HW_CS pinMode(_cs, OUTPUT); +#endif #ifndef ESP8266 #ifndef USE_DIGITAL_WRITE csport = portOutputRegister(digitalPinToPort(_cs)); @@ -236,6 +325,9 @@ void Adafruit_ILI9341::begin(void) { SPI.setDataMode(SPI_MODE0); #elif defined (ESP8266) SPI.begin(); +#ifdef USE_HW_CS + SPI.setHwCs(true); +#endif #endif #ifndef ESP8266 } else { @@ -388,20 +480,13 @@ void Adafruit_ILI9341::begin(void) { } -void Adafruit_ILI9341::setAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1, - uint16_t y1) { +void Adafruit_ILI9341::setAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) { - writecommand(ILI9341_CASET); // Column addr set - writedata(x0 >> 8); - writedata(x0 & 0xFF); // XSTART - writedata(x1 >> 8); - writedata(x1 & 0xFF); // XEND + uint8_t buffC[] = {(uint8_t)(x0 >> 8), (uint8_t)x0, (uint8_t)(x1 >> 8), (uint8_t)x1}; + uint8_t buffP[] = {(uint8_t)(y0 >> 8), (uint8_t)y0, (uint8_t)(y1 >> 8), (uint8_t)y1}; - writecommand(ILI9341_PASET); // Row addr set - writedata(y0>>8); - writedata(y0); // YSTART - writedata(y1>>8); - writedata(y1); // YEND + writeCmdData(ILI9341_CASET, &buffC[0], sizeof(buffC)); // Column addr set + writeCmdData(ILI9341_PASET, &buffP[0], sizeof(buffP)); // Column addr set writecommand(ILI9341_RAMWR); // write to RAM } @@ -409,29 +494,19 @@ void Adafruit_ILI9341::setAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1, void Adafruit_ILI9341::pushColor(uint16_t color) { if (hwSPI) spi_begin(); -#ifdef USE_DIGITAL_WRITE - digitalWrite(_dc, HIGH); - digitalWrite(_cs, LOW); -#else + + spiDcHigh(); + spiCsLow(); + #ifdef ESP8266 - GPOS = digitalPinToBitMask(_dc); - GPOC = digitalPinToBitMask(_cs); + spiwrite16(color); #else - *dcport |= dcpinmask; - *csport &= ~cspinmask; -#endif -#endif spiwrite(color >> 8); spiwrite(color); -#ifdef USE_DIGITAL_WRITE - digitalWrite(_cs, HIGH); -#else -#ifdef ESP8266 - GPOS = digitalPinToBitMask(_cs); -#else - *csport |= cspinmask; -#endif #endif + + spiCsHigh(); + if (hwSPI) spi_end(); } @@ -441,30 +516,18 @@ void Adafruit_ILI9341::drawPixel(int16_t x, int16_t y, uint16_t color) { if (hwSPI) spi_begin(); setAddrWindow(x,y,x+1,y+1); -#ifdef USE_DIGITAL_WRITE - digitalWrite(_dc, HIGH); - digitalWrite(_cs, LOW); -#else -#ifdef ESP8266 - GPOS = digitalPinToBitMask(_dc); - GPOC = digitalPinToBitMask(_cs); -#else - *dcport |= dcpinmask; - *csport &= ~cspinmask; -#endif -#endif + spiDcHigh(); + spiCsLow(); +#ifdef ESP8266 + spiwrite16(color); +#else spiwrite(color >> 8); spiwrite(color); -#ifdef USE_DIGITAL_WRITE - digitalWrite(_cs, HIGH); -#else -#ifdef ESP8266 - GPOS = digitalPinToBitMask(_cs); -#else - *csport |= cspinmask; -#endif #endif + + spiCsHigh(); + if (hwSPI) spi_end(); } @@ -480,35 +543,18 @@ void Adafruit_ILI9341::drawFastVLine(int16_t x, int16_t y, int16_t h, if (hwSPI) spi_begin(); setAddrWindow(x, y, x, y+h-1); - +#ifndef ESP8266 uint8_t hi = color >> 8, lo = color; - -#ifdef USE_DIGITAL_WRITE - digitalWrite(_dc, HIGH); - digitalWrite(_cs, LOW); -#else -#ifdef ESP8266 - GPOS = digitalPinToBitMask(_dc); - GPOC = digitalPinToBitMask(_cs); -#else - *dcport |= dcpinmask; - *csport &= ~cspinmask; -#endif #endif - while (h--) { - spiwrite(hi); - spiwrite(lo); - } -#ifdef USE_DIGITAL_WRITE - digitalWrite(_cs, HIGH); -#else -#ifdef ESP8266 - GPOS = digitalPinToBitMask(_cs); -#else - *csport |= cspinmask; -#endif -#endif + spiDcHigh(); + spiCsLow(); + + uint8_t colorBin[] = { (uint8_t) (color >> 8), (uint8_t) color }; + spiwritePattern(&colorBin[0], 2, h); + + spiCsHigh(); + if (hwSPI) spi_end(); } @@ -522,32 +568,14 @@ void Adafruit_ILI9341::drawFastHLine(int16_t x, int16_t y, int16_t w, if (hwSPI) spi_begin(); setAddrWindow(x, y, x+w-1, y); - uint8_t hi = color >> 8, lo = color; -#ifdef USE_DIGITAL_WRITE - digitalWrite(_dc, HIGH); - digitalWrite(_cs, LOW); -#else -#ifdef ESP8266 - GPOS = digitalPinToBitMask(_dc); - GPOC = digitalPinToBitMask(_cs); -#else - *dcport |= dcpinmask; - *csport &= ~cspinmask; -#endif -#endif - while (w--) { - spiwrite(hi); - spiwrite(lo); - } -#ifdef USE_DIGITAL_WRITE - digitalWrite(_cs, HIGH); -#else -#ifdef ESP8266 - GPOS = digitalPinToBitMask(_cs); -#else - *csport |= cspinmask; -#endif -#endif + spiDcHigh(); + spiCsLow(); + + uint8_t colorBin[] = { (uint8_t) (color >> 8), (uint8_t) color }; + spiwritePattern(&colorBin[0], 2, w); + + spiCsHigh(); + if (hwSPI) spi_end(); } @@ -556,48 +584,33 @@ void Adafruit_ILI9341::fillScreen(uint16_t color) { } // fill a rectangle -void Adafruit_ILI9341::fillRect(int16_t x, int16_t y, int16_t w, int16_t h, - uint16_t color) { +void Adafruit_ILI9341::fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color) { - // rudimentary clipping (drawChar w/big text requires this) - if((x >= _width) || (y >= _height)) return; - if((x + w - 1) >= _width) w = _width - x; - if((y + h - 1) >= _height) h = _height - y; + // rudimentary clipping (drawChar w/big text requires this) + if((x >= _width) || (y >= _height)) + return; + if((x + w - 1) >= _width) + w = _width - x; + if((y + h - 1) >= _height) + h = _height - y; - if (hwSPI) spi_begin(); - setAddrWindow(x, y, x+w-1, y+h-1); - - uint8_t hi = color >> 8, lo = color; - -#ifdef USE_DIGITAL_WRITE - digitalWrite(_dc, HIGH); - digitalWrite(_cs, LOW); -#else -#ifdef ESP8266 - GPOS = digitalPinToBitMask(_dc); - GPOC = digitalPinToBitMask(_cs); -#else - *dcport |= dcpinmask; - *csport &= ~cspinmask; -#endif -#endif - - for(y=h; y>0; y--) { - for(x=w; x>0; x--) { - spiwrite(hi); - spiwrite(lo); + if(hwSPI) { + spi_begin(); + } + + setAddrWindow(x, y, x + w - 1, y + h - 1); + + spiDcHigh(); + spiCsLow(); + + uint8_t colorBin[] = { (uint8_t) (color >> 8), (uint8_t) color }; + spiwritePattern(&colorBin[0], 2, (w * h)); + + spiCsHigh(); + + if(hwSPI) { + spi_end(); } - } -#ifdef USE_DIGITAL_WRITE - digitalWrite(_cs, HIGH); -#else -#ifdef ESP8266 - GPOS = digitalPinToBitMask(_cs); -#else - *csport |= cspinmask; -#endif -#endif - if (hwSPI) spi_end(); } @@ -697,10 +710,13 @@ uint8_t Adafruit_ILI9341::spiread(void) { uint8_t Adafruit_ILI9341::readdata(void) { digitalWrite(_dc, HIGH); +#ifndef USE_HW_CS digitalWrite(_cs, LOW); +#endif uint8_t r = spiread(); +#ifndef USE_HW_CS digitalWrite(_cs, HIGH); - +#endif return r; } @@ -708,22 +724,29 @@ uint8_t Adafruit_ILI9341::spiread(void) { uint8_t Adafruit_ILI9341::readcommand8(uint8_t c, uint8_t index) { if (hwSPI) spi_begin(); digitalWrite(_dc, LOW); // command +#ifndef USE_HW_CS digitalWrite(_cs, LOW); +#endif spiwrite(0xD9); // woo sekret command? digitalWrite(_dc, HIGH); // data spiwrite(0x10 + index); +#ifndef USE_HW_CS digitalWrite(_cs, HIGH); - +#endif digitalWrite(_dc, LOW); #ifndef ESP8266 digitalWrite(_sclk, LOW); #endif +#ifndef USE_HW_CS digitalWrite(_cs, LOW); +#endif spiwrite(c); digitalWrite(_dc, HIGH); uint8_t r = spiread(); +#ifndef USE_HW_CS digitalWrite(_cs, HIGH); +#endif if (hwSPI) spi_end(); return r; } diff --git a/libraries/Adafruit_ILI9341/Adafruit_ILI9341.h b/libraries/Adafruit_ILI9341/Adafruit_ILI9341.h index 2bfe69725..28ff9b6bb 100644 --- a/libraries/Adafruit_ILI9341/Adafruit_ILI9341.h +++ b/libraries/Adafruit_ILI9341/Adafruit_ILI9341.h @@ -111,6 +111,10 @@ #define ILI9341_PINK 0xF81F //#define USE_DIGITAL_WRITE +#ifdef ESP8266 +//not working +//#define USE_HW_CS +#endif class Adafruit_ILI9341 : public Adafruit_GFX { @@ -119,8 +123,11 @@ class Adafruit_ILI9341 : public Adafruit_GFX { Adafruit_ILI9341(int8_t _CS, int8_t _DC, int8_t _MOSI, int8_t _SCLK, int8_t _RST, int8_t _MISO); #endif +#ifdef USE_HW_CS + Adafruit_ILI9341(int8_t _DC, int8_t _RST = -1); +#else Adafruit_ILI9341(int8_t _CS, int8_t _DC, int8_t _RST = -1); - +#endif void begin(void), setAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1), pushColor(uint16_t color), @@ -134,22 +141,43 @@ class Adafruit_ILI9341 : public Adafruit_GFX { invertDisplay(boolean i); uint16_t color565(uint8_t r, uint8_t g, uint8_t b); - /* These are not for current use, 8-bit protocol only! */ - uint8_t readdata(void), - readcommand8(uint8_t reg, uint8_t index = 0); - /* - uint16_t readcommand16(uint8_t); - uint32_t readcommand32(uint8_t); - void dummyclock(void); - */ + void commandList(uint8_t *addr); - void spiwrite(uint8_t), - writecommand(uint8_t c), - writedata(uint8_t d), - commandList(uint8_t *addr); - uint8_t spiread(void); + /* These are not for current use, 8-bit protocol only! */ + uint8_t readdata(void), + readcommand8(uint8_t reg, uint8_t index = 0); + /* + uint16_t readcommand16(uint8_t); + uint32_t readcommand32(uint8_t); + void dummyclock(void); + */ + + void writecommand(uint8_t c); + void writedata(uint8_t d); + void writedata(uint8_t * data, uint8_t size); + void writeCmdData(uint8_t cmd, uint8_t * data, uint8_t size); private: + + uint8_t spiread(void); + +#ifdef ESP8266 + inline void spiwrite(uint8_t data); + inline void spiwrite16(uint16_t data); + inline void spiwriteBytes(uint8_t * data, uint8_t size); + inline void spiwritePattern(uint8_t * data, uint8_t size, uint32_t repeat); +#else + void spiwrite(uint8_t); + void spiwrite16(uint16_t data); + void spiwriteBytes(uint8_t * data, uint8_t size); + void spiwritePattern(uint8_t * data, uint8_t size, uint8_t repeat); +#endif + + inline void spiCsHigh(void); + inline void spiCsLow(void); + inline void spiDcHigh(void); + inline void spiDcLow(void); + uint8_t tabcolor; boolean hwSPI; @@ -163,7 +191,10 @@ class Adafruit_ILI9341 : public Adafruit_GFX { uint32_t _cs, _dc, _rst, _mosi, _miso, _sclk; uint32_t mosipinmask, clkpinmask, cspinmask, dcpinmask; #elif defined (ESP8266) - uint32_t _cs, _dc, _rst; +#ifndef USE_HW_CS + int8_t _cs; +#endif + int8_t _dc, _rst; #endif }; From 04cc6a858b7b8e4a2267952be22d64e072eb78f4 Mon Sep 17 00:00:00 2001 From: Markus Sattler Date: Sat, 9 May 2015 18:56:29 +0200 Subject: [PATCH 2/7] Adafruit_ILI9341 +7% speed now at 327,45% total --- .../Adafruit_ILI9341/Adafruit_ILI9341.cpp | 121 +++++++++++------- libraries/Adafruit_ILI9341/Adafruit_ILI9341.h | 4 + 2 files changed, 76 insertions(+), 49 deletions(-) diff --git a/libraries/Adafruit_ILI9341/Adafruit_ILI9341.cpp b/libraries/Adafruit_ILI9341/Adafruit_ILI9341.cpp index caac3a11e..d2d40d473 100644 --- a/libraries/Adafruit_ILI9341/Adafruit_ILI9341.cpp +++ b/libraries/Adafruit_ILI9341/Adafruit_ILI9341.cpp @@ -479,16 +479,31 @@ void Adafruit_ILI9341::begin(void) { } - void Adafruit_ILI9341::setAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) { + spiCsLow(); + setAddrWindow_(x0, y0, x1, y1); + spiCsHigh(); +} - uint8_t buffC[] = {(uint8_t)(x0 >> 8), (uint8_t)x0, (uint8_t)(x1 >> 8), (uint8_t)x1}; - uint8_t buffP[] = {(uint8_t)(y0 >> 8), (uint8_t)y0, (uint8_t)(y1 >> 8), (uint8_t)y1}; +void Adafruit_ILI9341::setAddrWindow_(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) { - writeCmdData(ILI9341_CASET, &buffC[0], sizeof(buffC)); // Column addr set - writeCmdData(ILI9341_PASET, &buffP[0], sizeof(buffP)); // Column addr set + uint8_t buffC[] = { (uint8_t) (x0 >> 8), (uint8_t) x0, (uint8_t) (x1 >> 8), (uint8_t) x1 }; + uint8_t buffP[] = { (uint8_t) (y0 >> 8), (uint8_t) y0, (uint8_t) (y1 >> 8), (uint8_t) y1 }; + + spiDcLow(); + spiwrite(ILI9341_CASET); + spiDcHigh(); + spiwriteBytes(&buffC[0], sizeof(buffC)); + + spiDcLow(); + spiwrite(ILI9341_PASET); + spiDcHigh(); + spiwriteBytes(&buffP[0], sizeof(buffP)); + + spiDcLow(); + spiwrite(ILI9341_RAMWR); + spiDcHigh(); - writecommand(ILI9341_RAMWR); // write to RAM } @@ -512,71 +527,80 @@ void Adafruit_ILI9341::pushColor(uint16_t color) { void Adafruit_ILI9341::drawPixel(int16_t x, int16_t y, uint16_t color) { - if((x < 0) ||(x >= _width) || (y < 0) || (y >= _height)) return; + if((x < 0) || (x >= _width) || (y < 0) || (y >= _height)) { + return; + } - if (hwSPI) spi_begin(); - setAddrWindow(x,y,x+1,y+1); - spiDcHigh(); - spiCsLow(); + if(hwSPI) { + spi_begin(); + } + + spiCsLow(); + + setAddrWindow_(x, y, x + 1, y + 1); #ifdef ESP8266 - spiwrite16(color); + spiwrite16(color); #else - spiwrite(color >> 8); - spiwrite(color); + spiwrite(color >> 8); + spiwrite(color); #endif - spiCsHigh(); + spiCsHigh(); - if (hwSPI) spi_end(); + if(hwSPI) { + spi_end(); + } } -void Adafruit_ILI9341::drawFastVLine(int16_t x, int16_t y, int16_t h, - uint16_t color) { +void Adafruit_ILI9341::drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color) { - // Rudimentary clipping - if((x >= _width) || (y >= _height)) return; + // Rudimentary clipping + if((x >= _width) || (y >= _height)) return; + if((y + h - 1) >= _height) h = _height - y; - if((y+h-1) >= _height) - h = _height-y; + if(hwSPI) { + spi_begin(); + } - if (hwSPI) spi_begin(); - setAddrWindow(x, y, x, y+h-1); -#ifndef ESP8266 - uint8_t hi = color >> 8, lo = color; -#endif + spiCsLow(); - spiDcHigh(); - spiCsLow(); + setAddrWindow_(x, y, x, (y + h - 1)); - uint8_t colorBin[] = { (uint8_t) (color >> 8), (uint8_t) color }; - spiwritePattern(&colorBin[0], 2, h); + uint8_t colorBin[] = { (uint8_t) (color >> 8), (uint8_t) color }; + spiwritePattern(&colorBin[0], 2, h); - spiCsHigh(); + spiCsHigh(); - if (hwSPI) spi_end(); + if(hwSPI) { + spi_end(); + } } +void Adafruit_ILI9341::drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color) { -void Adafruit_ILI9341::drawFastHLine(int16_t x, int16_t y, int16_t w, - uint16_t color) { + // Rudimentary clipping + if((x >= _width) || (y >= _height)) return; + if((x+w-1) >= _width) w = _width-x; - // Rudimentary clipping - if((x >= _width) || (y >= _height)) return; - if((x+w-1) >= _width) w = _width-x; - if (hwSPI) spi_begin(); - setAddrWindow(x, y, x+w-1, y); + if(hwSPI) { + spi_begin(); + } - spiDcHigh(); - spiCsLow(); + spiDcHigh(); + spiCsLow(); - uint8_t colorBin[] = { (uint8_t) (color >> 8), (uint8_t) color }; - spiwritePattern(&colorBin[0], 2, w); + setAddrWindow_(x, y, (x + w - 1), y); - spiCsHigh(); + uint8_t colorBin[] = { (uint8_t) (color >> 8), (uint8_t) color }; + spiwritePattern(&colorBin[0], 2, w); - if (hwSPI) spi_end(); + spiCsHigh(); + + if(hwSPI) { + spi_end(); + } } void Adafruit_ILI9341::fillScreen(uint16_t color) { @@ -598,11 +622,10 @@ void Adafruit_ILI9341::fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint spi_begin(); } - setAddrWindow(x, y, x + w - 1, y + h - 1); - - spiDcHigh(); spiCsLow(); + setAddrWindow_(x, y, x + w - 1, y + h - 1); + uint8_t colorBin[] = { (uint8_t) (color >> 8), (uint8_t) color }; spiwritePattern(&colorBin[0], 2, (w * h)); diff --git a/libraries/Adafruit_ILI9341/Adafruit_ILI9341.h b/libraries/Adafruit_ILI9341/Adafruit_ILI9341.h index 28ff9b6bb..394aff376 100644 --- a/libraries/Adafruit_ILI9341/Adafruit_ILI9341.h +++ b/libraries/Adafruit_ILI9341/Adafruit_ILI9341.h @@ -161,16 +161,20 @@ class Adafruit_ILI9341 : public Adafruit_GFX { uint8_t spiread(void); + #ifdef ESP8266 inline void spiwrite(uint8_t data); inline void spiwrite16(uint16_t data); inline void spiwriteBytes(uint8_t * data, uint8_t size); inline void spiwritePattern(uint8_t * data, uint8_t size, uint32_t repeat); + + inline void setAddrWindow_(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1); #else void spiwrite(uint8_t); void spiwrite16(uint16_t data); void spiwriteBytes(uint8_t * data, uint8_t size); void spiwritePattern(uint8_t * data, uint8_t size, uint8_t repeat); + void setAddrWindow_(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1); #endif inline void spiCsHigh(void); From 934434d5f906bbd2582793a7f95ab3f9e090e8d5 Mon Sep 17 00:00:00 2001 From: Markus Sattler Date: Sun, 10 May 2015 17:34:16 +0200 Subject: [PATCH 3/7] SD: - optimize SPI usage 148% write speed (24kB/s -> 37kB/s) and 127% read speed (121kB/s -> 155kB/s) at 8MHz - add clock frequency as parameter for begin(csPin, frequency) - SD @80MHz write: 84kB/s read: 231kB/s SPI add functions: - void write32(uint32_t data); - void write32(uint32_t data, bool msb); - void transferBytes(uint8_t * out, uint8_t * in, uint32_t size); Adafruit_ILI9341: - code clean --- .../esp8266com/esp8266/libraries/SPI/SPI.cpp | 98 ++++++- .../esp8266com/esp8266/libraries/SPI/SPI.h | 5 + .../Adafruit_ILI9341/Adafruit_ILI9341.cpp | 263 +++++++----------- libraries/Adafruit_ILI9341/Adafruit_ILI9341.h | 12 +- libraries/SD/src/SD.cpp | 12 +- libraries/SD/src/SD.h | 4 +- libraries/SD/src/utility/Sd2Card.cpp | 36 ++- 7 files changed, 248 insertions(+), 182 deletions(-) diff --git a/hardware/esp8266com/esp8266/libraries/SPI/SPI.cpp b/hardware/esp8266com/esp8266/libraries/SPI/SPI.cpp index 6b3d29784..be4627740 100644 --- a/hardware/esp8266com/esp8266/libraries/SPI/SPI.cpp +++ b/hardware/esp8266com/esp8266/libraries/SPI/SPI.cpp @@ -216,8 +216,16 @@ void SPIClass::setClockDivider(uint32_t clockDiv) { SPI1CLK = clockDiv; } +inline void SPIClass::setDataBits(uint16_t bits) { + const uint32_t mask = ~((SPIMMOSI << SPILMOSI) | (SPIMMISO << SPILMISO)); + bits--; + SPI1U1 = ((SPI1U1 & mask) | ((bits << SPILMOSI) | (bits << SPILMISO))); +} + uint8_t SPIClass::transfer(uint8_t data) { while(SPI1CMD & SPIBUSY) {} + // reset to 8Bit mode + setDataBits(8); SPI1W0 = data; SPI1CMD |= SPIBUSY; while(SPI1CMD & SPIBUSY) {} @@ -248,19 +256,21 @@ uint16_t SPIClass::transfer16(uint16_t data) { void SPIClass::write(uint8_t data) { while(SPI1CMD & SPIBUSY) {} + // reset to 8Bit mode + setDataBits(8); SPI1W0 = data; SPI1CMD |= SPIBUSY; while(SPI1CMD & SPIBUSY) {} } void SPIClass::write16(uint16_t data) { - write16(data, (SPI1C & (SPICWBO | SPICRBO))); + write16(data, !(SPI1C & (SPICWBO | SPICRBO))); } void SPIClass::write16(uint16_t data, bool msb) { while(SPI1CMD & SPIBUSY) {} // Set to 16Bits transfer - SPI1U1 = (SPI1U1 & ~((SPIMMOSI << SPILMOSI))) | ((16 - 1) << SPILMOSI); + setDataBits(16); if(msb) { // MSBFIRST Byte first SPI1W0 = (data >> 8) | (data << 8); @@ -271,8 +281,31 @@ void SPIClass::write16(uint16_t data, bool msb) { SPI1CMD |= SPIBUSY; } while(SPI1CMD & SPIBUSY) {} - // reset to 8Bit mode - SPI1U1 = (SPI1U1 & ~((SPIMMOSI << SPILMOSI))) | ((8 - 1) << SPILMOSI); +} + +void SPIClass::write32(uint32_t data) { + write32(data, !(SPI1C & (SPICWBO | SPICRBO))); +} + +void SPIClass::write32(uint32_t data, bool msb) { + while(SPI1CMD & SPIBUSY) {} + // Set to 32Bits transfer + setDataBits(32); + if(msb) { + union { + uint32_t l; + uint8_t b[4]; + } data_; + data_.l = data; + // MSBFIRST Byte first + SPI1W0 = (data_.b[3] | (data_.b[2] << 8) | (data_.b[1] << 16) | (data_.b[0] << 24)); + SPI1CMD |= SPIBUSY; + } else { + // LSBFIRST Byte first + SPI1W0 = data; + SPI1CMD |= SPIBUSY; + } + while(SPI1CMD & SPIBUSY) {} } void SPIClass::writeBytes(uint8_t * data, uint32_t size) { @@ -291,7 +324,7 @@ void SPIClass::writeBytes(uint8_t * data, uint32_t size) { void SPIClass::writeBytes_(uint8_t * data, uint8_t size) { while(SPI1CMD & SPIBUSY) {} // Set Bits to transfer - SPI1U1 = (SPI1U1 & ~((SPIMMOSI << SPILMOSI))) | ((size * 8 - 1) << SPILMOSI); + setDataBits(size * 8); volatile uint32_t * fifoPtr = &SPI1W0; uint32_t * dataPtr = (uint32_t*) data; @@ -305,8 +338,6 @@ void SPIClass::writeBytes_(uint8_t * data, uint8_t size) { SPI1CMD |= SPIBUSY; while(SPI1CMD & SPIBUSY) {} - // reset to 8Bit mode - SPI1U1 = (SPI1U1 & ~((SPIMMOSI << SPILMOSI))) | ((8 - 1) << SPILMOSI); } void SPIClass::writePattern(uint8_t * data, uint8_t size, uint32_t repeat) { @@ -344,3 +375,56 @@ void SPIClass::writePattern_(uint8_t * data, uint8_t size, uint8_t repeat) { writeBytes(&buffer[0], bytes); } + +void SPIClass::transferBytes(uint8_t * out, uint8_t * in, uint32_t size) { + while(size) { + if(size > 64) { + transferBytes_(out, in, 64); + size -= 64; + if(out) out += 64; + if(in) in += 64; + } else { + transferBytes_(out, in, size); + size = 0; + } + } +} + +void SPIClass::transferBytes_(uint8_t * out, uint8_t * in, uint8_t size) { + while(SPI1CMD & SPIBUSY) {} + // Set in/out Bits to transfer + + setDataBits(size * 8); + + volatile uint32_t * fifoPtr = &SPI1W0; + uint8_t dataSize = ((size + 3) / 4); + + if(out) { + uint32_t * dataPtr = (uint32_t*) out; + while(dataSize--) { + *fifoPtr = *dataPtr; + dataPtr++; + fifoPtr++; + } + } else { + // no out data only read fill with dummy data! + while(dataSize--) { + *fifoPtr = 0xFFFFFFFF; + fifoPtr++; + } + } + + SPI1CMD |= SPIBUSY; + while(SPI1CMD & SPIBUSY) {} + + if(in) { + volatile uint8_t * fifoPtr8 = (volatile uint8_t *) &SPI1W0; + dataSize = size; + while(dataSize--) { + *in = *fifoPtr8; + in++; + fifoPtr8++; + } + } +} + diff --git a/hardware/esp8266com/esp8266/libraries/SPI/SPI.h b/hardware/esp8266com/esp8266/libraries/SPI/SPI.h index 1030eeaa9..e67b5b0d5 100644 --- a/hardware/esp8266com/esp8266/libraries/SPI/SPI.h +++ b/hardware/esp8266com/esp8266/libraries/SPI/SPI.h @@ -75,13 +75,18 @@ public: void write(uint8_t data); void write16(uint16_t data); void write16(uint16_t data, bool msb); + void write32(uint32_t data); + void write32(uint32_t data, bool msb); void writeBytes(uint8_t * data, uint32_t size); void writePattern(uint8_t * data, uint8_t size, uint32_t repeat); + void transferBytes(uint8_t * out, uint8_t * in, uint32_t size); void endTransaction(void); private: bool useHwCs; void writeBytes_(uint8_t * data, uint8_t size); void writePattern_(uint8_t * data, uint8_t size, uint8_t repeat); + void transferBytes_(uint8_t * out, uint8_t * in, uint8_t size); + inline void setDataBits(uint16_t bits); }; extern SPIClass SPI; diff --git a/libraries/Adafruit_ILI9341/Adafruit_ILI9341.cpp b/libraries/Adafruit_ILI9341/Adafruit_ILI9341.cpp index d2d40d473..239a414ac 100644 --- a/libraries/Adafruit_ILI9341/Adafruit_ILI9341.cpp +++ b/libraries/Adafruit_ILI9341/Adafruit_ILI9341.cpp @@ -26,6 +26,16 @@ #include "wiring_private.h" #include +#ifdef ESP8266 +#define hwSPI true +#endif + +#define writeCmdDataTmp(cmd, ...) { \ + const uint8_t tmp##cmd##_[] = { __VA_ARGS__ }; \ + writeCmdData(cmd, (uint8_t *) &tmp##cmd##_[0], sizeof(tmp##cmd##_)); \ +} + + #ifndef ESP8266 // Constructor when using software SPI. All output pins are configurable. Adafruit_ILI9341::Adafruit_ILI9341(int8_t cs, int8_t dc, int8_t mosi, @@ -42,12 +52,15 @@ Adafruit_ILI9341::Adafruit_ILI9341(int8_t cs, int8_t dc, int8_t mosi, // Constructor when using hardware SPI. Faster, but must use SPI pins // specific to each board type (e.g. 11,13 for Uno, 51,52 for Mega, etc.) -#ifdef USE_HW_CS +#if defined(ILI9341_USE_HW_CS) || defined(ILI9341_USE_NO_CS) Adafruit_ILI9341::Adafruit_ILI9341(int8_t dc, int8_t rst) : Adafruit_GFX(ILI9341_TFTWIDTH, ILI9341_TFTHEIGHT) { _dc = dc; _rst = rst; hwSPI = true; -#ifndef ESP8266 +#ifdef ESP8266 + _dcMask = digitalPinToBitMask(_dc); + _rstMask = digitalPinToBitMask(_rst); +#else _mosi = _sclk = 0; #endif } @@ -56,8 +69,12 @@ Adafruit_ILI9341::Adafruit_ILI9341(int8_t dc, int8_t rst) : Adafruit_GFX(ILI9341 _cs = cs; _dc = dc; _rst = rst; + #ifdef ESP8266 + _csMask = digitalPinToBitMask(_cs); + _dcMask = digitalPinToBitMask(_dc); + _rstMask = digitalPinToBitMask(_rst); + #else hwSPI = true; - #ifndef ESP8266 _mosi = _sclk = 0; #endif } @@ -140,12 +157,12 @@ void Adafruit_ILI9341::spiwritePattern(uint8_t * data, uint8_t size, uint32_t re inline void Adafruit_ILI9341::spiCsLow(void) { -#ifdef USE_DIGITAL_WRITE +#ifdef ILI9341_USE_DIGITAL_WRITE digitalWrite(_cs, LOW); #else #ifdef ESP8266 -#ifndef USE_HW_CS - GPOC = digitalPinToBitMask(_cs); +#if !defined(ILI9341_USE_HW_CS) && !defined(ILI9341_USE_NO_CS) + GPOC = _csMask; #endif #else *csport &= ~cspinmask; @@ -154,12 +171,12 @@ inline void Adafruit_ILI9341::spiCsLow(void) { } inline void Adafruit_ILI9341::spiCsHigh(void) { -#ifdef USE_DIGITAL_WRITE +#ifdef ILI9341_USE_DIGITAL_WRITE digitalWrite(_cs, HIGH); #else #ifdef ESP8266 -#ifndef USE_HW_CS - GPOS = digitalPinToBitMask(_cs); +#if !defined(ILI9341_USE_HW_CS) && !defined(ILI9341_USE_NO_CS) + GPOS = _csMask; #endif #else *csport |= cspinmask; @@ -168,12 +185,12 @@ inline void Adafruit_ILI9341::spiCsHigh(void) { } inline void Adafruit_ILI9341::spiDcLow(void){ -#ifdef USE_DIGITAL_WRITE +#ifdef ILI9341_USE_DIGITAL_WRITE digitalWrite(_dc, LOW); #else #ifdef ESP8266 #ifndef USE_HW_CS - GPOC = digitalPinToBitMask(_dc); + GPOC = _dcMask; #endif #else *dcport &= ~dcpinmask; @@ -182,11 +199,11 @@ inline void Adafruit_ILI9341::spiDcLow(void){ } inline void Adafruit_ILI9341::spiDcHigh(void) { -#ifdef USE_DIGITAL_WRITE +#ifdef ILI9341_USE_DIGITAL_WRITE digitalWrite(_dc, HIGH); #else #ifdef ESP8266 - GPOS = digitalPinToBitMask(_dc); + GPOS = _dcMask; #else *dcport |= dcpinmask; #endif @@ -237,13 +254,16 @@ void Adafruit_ILI9341::writeCmdData(uint8_t cmd, uint8_t * data, uint8_t size) { // establish settings and protect from interference from other // libraries. Otherwise, they simply do nothing. #ifdef SPI_HAS_TRANSACTION + +#ifdef ESP8266 +SPISettings spiSettings = SPISettings(F_CPU, MSBFIRST, SPI_MODE0); +#else +SPISettings spiSettings = SPISettings(8000000, MSBFIRST, SPI_MODE0); +#endif + static inline void spi_begin(void) __attribute__((always_inline)); static inline void spi_begin(void) { -#ifdef ESP8266 - SPI.beginTransaction(SPISettings(F_CPU, MSBFIRST, SPI_MODE0)); -#else - SPI.beginTransaction(SPISettings(8000000, MSBFIRST, SPI_MODE0)); -#endif + SPI.beginTransaction(spiSettings); } static inline void spi_end(void) __attribute__((always_inline)); static inline void spi_end(void) { @@ -289,7 +309,7 @@ void Adafruit_ILI9341::commandList(uint8_t *addr) { void Adafruit_ILI9341::begin(void) { - if (_rst > 0) { + if (_rst > NOT_A_PIN) { pinMode(_rst, OUTPUT); digitalWrite(_rst, LOW); } @@ -299,7 +319,7 @@ void Adafruit_ILI9341::begin(void) { pinMode(_cs, OUTPUT); #endif #ifndef ESP8266 -#ifndef USE_DIGITAL_WRITE +#ifndef ILI9341_USE_DIGITAL_WRITE csport = portOutputRegister(digitalPinToPort(_cs)); cspinmask = digitalPinToBitMask(_cs); dcport = portOutputRegister(digitalPinToPort(_dc)); @@ -343,7 +363,7 @@ void Adafruit_ILI9341::begin(void) { } #endif // toggle RST low to reset - if (_rst > 0) { + if (_rst > NOT_A_PIN) { digitalWrite(_rst, HIGH); delay(5); digitalWrite(_rst, LOW); @@ -367,108 +387,47 @@ void Adafruit_ILI9341::begin(void) { //if(cmdList) commandList(cmdList); if (hwSPI) spi_begin(); - writecommand(0xEF); - writedata(0x03); - writedata(0x80); - writedata(0x02); - writecommand(0xCF); - writedata(0x00); - writedata(0XC1); - writedata(0X30); + writeCmdDataTmp(0xEF, 0x03, 0x80, 0x02); + writeCmdDataTmp(0xCF, 0x00, 0XC1, 0X30); + writeCmdDataTmp(0xED, 0x64, 0x03, 0X12, 0X81); + writeCmdDataTmp(0xE8, 0x85, 0x00, 0x78); + writeCmdDataTmp(0xCB, 0x39, 0x2C, 0x00, 0x34, 0x02); + writeCmdDataTmp(0xF7, 0x20); + writeCmdDataTmp(0xEA, 0x00, 0x00); - writecommand(0xED); - writedata(0x64); - writedata(0x03); - writedata(0X12); - writedata(0X81); - - writecommand(0xE8); - writedata(0x85); - writedata(0x00); - writedata(0x78); + //Powercontrol + //VRH[5:0] + writeCmdDataTmp(ILI9341_PWCTR1, 0x23); - writecommand(0xCB); - writedata(0x39); - writedata(0x2C); - writedata(0x00); - writedata(0x34); - writedata(0x02); - - writecommand(0xF7); - writedata(0x20); + //Powercontrol + //SAP[2:0];BT[3:0] + writeCmdDataTmp(ILI9341_PWCTR2, 0x10); - writecommand(0xEA); - writedata(0x00); - writedata(0x00); - - writecommand(ILI9341_PWCTR1); //Power control - writedata(0x23); //VRH[5:0] - - writecommand(ILI9341_PWCTR2); //Power control - writedata(0x10); //SAP[2:0];BT[3:0] - - writecommand(ILI9341_VMCTR1); //VCM control - writedata(0x3e); //对比度调节 - writedata(0x28); + //VCMcontrol + writeCmdDataTmp(ILI9341_VMCTR1, 0x3e, 0x28); + + //VCMcontrol2 + writeCmdDataTmp(ILI9341_VMCTR2, 0x86); + + //MemoryAccessControl + writeCmdDataTmp(ILI9341_MADCTL, 0x48); + + writeCmdDataTmp(ILI9341_PIXFMT, 0x55); + writeCmdDataTmp(ILI9341_FRMCTR1, 0x00, 0x18); + + //DisplayFunctionControl + writeCmdDataTmp(ILI9341_DFUNCTR, 0x08, 0x82, 0x27); + + //3GammaFunctionDisable + writeCmdDataTmp(0xF2, 0x00); - writecommand(ILI9341_VMCTR2); //VCM control2 - writedata(0x86); //-- - - writecommand(ILI9341_MADCTL); // Memory Access Control - writedata(0x48); - - writecommand(ILI9341_PIXFMT); - writedata(0x55); + //Gammacurveselected + writeCmdDataTmp(ILI9341_GAMMASET, 0x01); - writecommand(ILI9341_FRMCTR1); - writedata(0x00); - writedata(0x18); - - writecommand(ILI9341_DFUNCTR); // Display Function Control - writedata(0x08); - writedata(0x82); - writedata(0x27); - - writecommand(0xF2); // 3Gamma Function Disable - writedata(0x00); - - writecommand(ILI9341_GAMMASET); //Gamma curve selected - writedata(0x01); - - writecommand(ILI9341_GMCTRP1); //Set Gamma - writedata(0x0F); - writedata(0x31); - writedata(0x2B); - writedata(0x0C); - writedata(0x0E); - writedata(0x08); - writedata(0x4E); - writedata(0xF1); - writedata(0x37); - writedata(0x07); - writedata(0x10); - writedata(0x03); - writedata(0x0E); - writedata(0x09); - writedata(0x00); - - writecommand(ILI9341_GMCTRN1); //Set Gamma - writedata(0x00); - writedata(0x0E); - writedata(0x14); - writedata(0x03); - writedata(0x11); - writedata(0x07); - writedata(0x31); - writedata(0xC1); - writedata(0x48); - writedata(0x08); - writedata(0x0F); - writedata(0x0C); - writedata(0x31); - writedata(0x36); - writedata(0x0F); + //SetGamma + writeCmdDataTmp(ILI9341_GMCTRP1, 0x0F, 0x31, 0x2B, 0x0C, 0x0E, 0x08, 0x4E, 0xF1, 0x37, 0x07, 0x10, 0x03, 0x0E, 0x09, 0x00); + writeCmdDataTmp(ILI9341_GMCTRN1, 0x00, 0x0E, 0x14, 0x03, 0x11, 0x07, 0x31, 0xC1, 0x48, 0x08, 0x0F, 0x0C, 0x31, 0x36, 0x0F); writecommand(ILI9341_SLPOUT); //Exit Sleep if (hwSPI) spi_end(); @@ -604,7 +563,7 @@ void Adafruit_ILI9341::drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t c } void Adafruit_ILI9341::fillScreen(uint16_t color) { - fillRect(0, 0, _width, _height, color); + fillRect(0, 0, _width, _height, color); } // fill a rectangle @@ -711,9 +670,7 @@ uint8_t Adafruit_ILI9341::spiread(void) { SPI.setDataMode(SPI_MODE0); r = SPI.transfer(0x00); #else - spi_begin(); r = SPI.transfer(0x00); - spi_end(); #endif } else { #ifndef ESP8266 @@ -731,50 +688,40 @@ uint8_t Adafruit_ILI9341::spiread(void) { return r; } - uint8_t Adafruit_ILI9341::readdata(void) { - digitalWrite(_dc, HIGH); -#ifndef USE_HW_CS - digitalWrite(_cs, LOW); -#endif - uint8_t r = spiread(); -#ifndef USE_HW_CS - digitalWrite(_cs, HIGH); -#endif - return r; +uint8_t Adafruit_ILI9341::readdata(void) { + if(hwSPI) spi_begin(); + spiCsLow(); + spiDcLow(); + uint8_t r = spiread(); + spiCsHigh(); + if(hwSPI) spi_end(); + return r; } - uint8_t Adafruit_ILI9341::readcommand8(uint8_t c, uint8_t index) { - if (hwSPI) spi_begin(); - digitalWrite(_dc, LOW); // command -#ifndef USE_HW_CS - digitalWrite(_cs, LOW); -#endif - spiwrite(0xD9); // woo sekret command? - digitalWrite(_dc, HIGH); // data - spiwrite(0x10 + index); -#ifndef USE_HW_CS - digitalWrite(_cs, HIGH); -#endif - digitalWrite(_dc, LOW); + if(hwSPI) spi_begin(); + + spiCsLow(); + spiDcLow(); + + spiwrite(0xD9); // woo sekret command? + spiDcHigh(); + spiwrite(0x10 + index); + #ifndef ESP8266 - digitalWrite(_sclk, LOW); + digitalWrite(_sclk, LOW); #endif -#ifndef USE_HW_CS - digitalWrite(_cs, LOW); -#endif - spiwrite(c); - - digitalWrite(_dc, HIGH); - uint8_t r = spiread(); -#ifndef USE_HW_CS - digitalWrite(_cs, HIGH); -#endif - if (hwSPI) spi_end(); - return r; + + spiDcLow(); + spiwrite(c); + + spiDcHigh(); + uint8_t r = spiread(); + spiCsHigh(); + + if(hwSPI) spi_end(); + return r; } - - /* diff --git a/libraries/Adafruit_ILI9341/Adafruit_ILI9341.h b/libraries/Adafruit_ILI9341/Adafruit_ILI9341.h index 394aff376..9b33b9b98 100644 --- a/libraries/Adafruit_ILI9341/Adafruit_ILI9341.h +++ b/libraries/Adafruit_ILI9341/Adafruit_ILI9341.h @@ -110,10 +110,11 @@ #define ILI9341_GREENYELLOW 0xAFE5 /* 173, 255, 47 */ #define ILI9341_PINK 0xF81F -//#define USE_DIGITAL_WRITE +//#define ILI9341_USE_DIGITAL_WRITE +//#define ILI9341_USE_NO_CS #ifdef ESP8266 //not working -//#define USE_HW_CS +//#define ILI9341_USE_HW_CS #endif class Adafruit_ILI9341 : public Adafruit_GFX { @@ -123,7 +124,7 @@ class Adafruit_ILI9341 : public Adafruit_GFX { Adafruit_ILI9341(int8_t _CS, int8_t _DC, int8_t _MOSI, int8_t _SCLK, int8_t _RST, int8_t _MISO); #endif -#ifdef USE_HW_CS +#if defined(USE_HW_CS) || defined(USE_NO_CS) Adafruit_ILI9341(int8_t _DC, int8_t _RST = -1); #else Adafruit_ILI9341(int8_t _CS, int8_t _DC, int8_t _RST = -1); @@ -183,8 +184,9 @@ class Adafruit_ILI9341 : public Adafruit_GFX { inline void spiDcLow(void); uint8_t tabcolor; - +#ifndef ESP8266 boolean hwSPI; +#endif #if defined (__AVR__) || defined(TEENSYDUINO) uint8_t mySPCR; volatile uint8_t *mosiport, *clkport, *dcport, *rsport, *csport; @@ -197,8 +199,10 @@ class Adafruit_ILI9341 : public Adafruit_GFX { #elif defined (ESP8266) #ifndef USE_HW_CS int8_t _cs; + uint32_t _csMask; #endif int8_t _dc, _rst; + uint32_t _dcMask, _rstMask; #endif }; diff --git a/libraries/SD/src/SD.cpp b/libraries/SD/src/SD.cpp index 65d32741c..d426dbe8e 100644 --- a/libraries/SD/src/SD.cpp +++ b/libraries/SD/src/SD.cpp @@ -326,13 +326,7 @@ boolean callback_rmdir(SdFile& parentDir, char *filePathComponent, return true; } - - -/* Implementation of class used to create `SDCard` object. */ - - - -boolean SDClass::begin(uint8_t csPin) { +boolean SDClass::begin(uint8_t csPin, uint32_t sckRateID) { /* Performs the initialisation required by the sdfatlib library. @@ -340,13 +334,11 @@ boolean SDClass::begin(uint8_t csPin) { Return true if initialization succeeds, false otherwise. */ - return card.init(SPI_HALF_SPEED, csPin) && + return card.init(sckRateID, csPin) && volume.init(card) && root.openRoot(volume); } - - // this little helper is used to traverse paths SdFile SDClass::getParentDir(const char *filepath, int *index) { // get parent directory diff --git a/libraries/SD/src/SD.h b/libraries/SD/src/SD.h index 7435cf577..e229cf8ad 100644 --- a/libraries/SD/src/SD.h +++ b/libraries/SD/src/SD.h @@ -65,8 +65,8 @@ private: public: // This needs to be called to set up the connection to the SD card // before other methods are used. - boolean begin(uint8_t csPin = SD_CHIP_SELECT_PIN); - + boolean begin(uint8_t csPin = SD_CHIP_SELECT_PIN, uint32_t sckRateID = SPI_FULL_SPEED); + // Open the specified file/directory with the supplied mode (e.g. read or // write, etc). Returns a File object for interacting with the file. // Note that currently only one file can be open at a time. diff --git a/libraries/SD/src/utility/Sd2Card.cpp b/libraries/SD/src/utility/Sd2Card.cpp index 98a02ba42..2d7618d65 100644 --- a/libraries/SD/src/utility/Sd2Card.cpp +++ b/libraries/SD/src/utility/Sd2Card.cpp @@ -33,9 +33,13 @@ static void spiSend(uint8_t b) { SPDR = b; while (!(SPSR & (1 << SPIF))) ; +#else +#ifdef ESP8266 + SPI.write(b); #else SPI.transfer(b); #endif +#endif } /** Receive a byte from the card */ static uint8_t spiRec(void) { @@ -116,8 +120,14 @@ uint8_t Sd2Card::cardCommand(uint8_t cmd, uint32_t arg) { // send command spiSend(cmd | 0x40); +#ifdef ESP8266 + // send argument + SPI.write32(arg, true); +#else // send argument for (int8_t s = 24; s >= 0; s -= 8) spiSend(arg >> s); +#endif + // send CRC uint8_t crc = 0xFF; @@ -424,7 +434,14 @@ uint8_t Sd2Card::readData(uint32_t block, dst[n] = SPDR; #else // OPTIMIZE_HARDWARE_SPI +#ifdef ESP8266 + // skip data before offset + SPI.transferBytes(NULL, NULL, offset_); + // transfer data + SPI.transferBytes(NULL, dst, count); + +#else // skip data before offset for (;offset_ < offset; offset_++) { spiRec(); @@ -433,6 +450,7 @@ uint8_t Sd2Card::readData(uint32_t block, for (uint16_t i = 0; i < count; i++) { dst[i] = spiRec(); } +#endif #endif // OPTIMIZE_HARDWARE_SPI offset_ += count; @@ -463,7 +481,11 @@ void Sd2Card::readEnd(void) { while (!(SPSR & (1 << SPIF))) ; #else // OPTIMIZE_HARDWARE_SPI +#ifdef ESP8266 + SPI.transferBytes(NULL, NULL, (514-offset_)); +#else while (offset_++ < 514) spiRec(); +#endif #endif // OPTIMIZE_HARDWARE_SPI chipSelectHigh(); inBlock_ = 0; @@ -479,7 +501,11 @@ uint8_t Sd2Card::readRegister(uint8_t cmd, void* buf) { } if (!waitStartBlock()) goto fail; // transfer data +#ifdef ESP8266 + SPI.transferBytes(NULL, dst, 16); +#else for (uint16_t i = 0; i < 16; i++) dst[i] = spiRec(); +#endif spiRec(); // get first crc byte spiRec(); // get second crc byte chipSelectHigh(); @@ -646,13 +672,21 @@ uint8_t Sd2Card::writeData(uint8_t token, const uint8_t* src) { #else // OPTIMIZE_HARDWARE_SPI spiSend(token); +#ifdef ESP8266 + // send argument + SPI.writeBytes((uint8_t *)src, 512); +#else for (uint16_t i = 0; i < 512; i++) { spiSend(src[i]); } +#endif #endif // OPTIMIZE_HARDWARE_SPI +#ifdef ESP8266 + SPI.write16(0xFFFF, true); +#else spiSend(0xff); // dummy crc spiSend(0xff); // dummy crc - +#endif status_ = spiRec(); if ((status_ & DATA_RES_MASK) != DATA_RES_ACCEPTED) { error(SD_CARD_ERROR_WRITE); From 12d53a053a76f85aae6d29dc78031aea6748d48c Mon Sep 17 00:00:00 2001 From: Jon Watte Date: Sun, 10 May 2015 14:00:50 -0700 Subject: [PATCH 4/7] Fix UDP send to not temporarily use connect() --- .../esp8266/libraries/ESP8266WiFi/src/WiFiUdp.cpp | 12 ++++++------ .../esp8266/libraries/ESP8266WiFi/src/WiFiUdp.h | 2 ++ .../libraries/ESP8266WiFi/src/include/UdpContext.h | 2 +- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/WiFiUdp.cpp b/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/WiFiUdp.cpp index f2328aa6b..df736742d 100644 --- a/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/WiFiUdp.cpp +++ b/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/WiFiUdp.cpp @@ -132,14 +132,13 @@ int WiFiUDP::beginPacket(const char *host, uint16_t port) int WiFiUDP::beginPacket(IPAddress ip, uint16_t port) { - ip_addr_t addr; - addr.addr = ip; - if (!_ctx) { _ctx = new UdpContext; _ctx->ref(); } - return (_ctx->connect(addr, port)) ? 1 : 0; + begunIp_ = ip; + begunPort_= port; + return 1; } int WiFiUDP::beginPacketMulticast(IPAddress multicastAddress, uint16_t port, @@ -167,8 +166,9 @@ int WiFiUDP::endPacket() if (!_ctx) return 0; - _ctx->send(); - _ctx->disconnect(); + ip_addr_t addr; + addr.addr = begunIp_; + _ctx->send(&addr, begunPort_); return 1; } diff --git a/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/WiFiUdp.h b/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/WiFiUdp.h index a6bdc00da..880984745 100644 --- a/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/WiFiUdp.h +++ b/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/WiFiUdp.h @@ -31,6 +31,8 @@ class UdpContext; class WiFiUDP : public UDP { private: UdpContext* _ctx; + IPAddress begunIp_; + uint16_t begunPort_; public: WiFiUDP(); // Constructor diff --git a/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/include/UdpContext.h b/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/include/UdpContext.h index e244486e1..bd818e8e4 100644 --- a/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/include/UdpContext.h +++ b/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/include/UdpContext.h @@ -281,7 +281,7 @@ private: void _reserve(size_t size) { - const size_t pbuf_unit_size = 1024; + const size_t pbuf_unit_size = 512; if (!_tx_buf_head) { _tx_buf_head = pbuf_alloc(PBUF_TRANSPORT, pbuf_unit_size, PBUF_RAM); From d050ced4df7a611a79e659abb03de95bf2e03e94 Mon Sep 17 00:00:00 2001 From: Markus Sattler Date: Mon, 11 May 2015 19:10:32 +0200 Subject: [PATCH 5/7] remove libc still not working! ../lib/gcc/xtensa-lx106-elf/4.8.2/../../../../xtensa-lx106-elf/lib\libc.a(lib_a-exit.o):(.literal+0x4): undefined reference to `_exit' ../lib/gcc/xtensa-lx106-elf/4.8.2/../../../../xtensa-lx106-elf/lib\libc.a(lib_a-exit.o): In function `exit': d:\Neo\Project\ESP8266\DevKit\build\compiler\dl\esp-newlib\build\xtensa-lx106-elf\newlib\libc\stdlib/../../../../../newlib/libc/stdlib/exit.c:65: undefined reference to `_exit' ../lib/gcc/xtensa-lx106-elf/4.8.2/../../../../xtensa-lx106-elf/lib\libc.a(lib_a-fopen.o):(.literal+0x0): undefined reference to `_open_r' ../lib/gcc/xtensa-lx106-elf/4.8.2/../../../../xtensa-lx106-elf/lib\libc.a(lib_a-fopen.o): In function `_fopen_r': d:\Neo\Project\ESP8266\DevKit\build\compiler\dl\esp-newlib\build\xtensa-lx106-elf\newlib\libc\stdio/../../../../../newlib/libc/stdio/fopen.c:141: undefined reference to `_open_r' ../lib/gcc/xtensa-lx106-elf/4.8.2/../../../../xtensa-lx106-elf/lib\libc.a(lib_a-freer.o):(.literal+0x14): undefined reference to `_sbrk_r' ../lib/gcc/xtensa-lx106-elf/4.8.2/../../../../xtensa-lx106-elf/lib\libc.a(lib_a-freer.o): In function `_malloc_trim_r': d:\Neo\Project\ESP8266\DevKit\build\compiler\dl\esp-newlib\build\xtensa-lx106-elf\newlib\libc\stdlib/../../../../../newlib/libc/stdlib/mallocr.c:3325: undefined reference to `_sbrk_r' d:\Neo\Project\ESP8266\DevKit\build\compiler\dl\esp-newlib\build\xtensa-lx106-elf\newlib\libc\stdlib/../../../../../newlib/libc/stdlib/mallocr.c:3332: undefined reference to `_sbrk_r' d:\Neo\Project\ESP8266\DevKit\build\compiler\dl\esp-newlib\build\xtensa-lx106-elf\newlib\libc\stdlib/../../../../../newlib/libc/stdlib/mallocr.c:3340: undefined reference to `_sbrk_r' ../lib/gcc/xtensa-lx106-elf/4.8.2/../../../../xtensa-lx106-elf/lib\libc.a(lib_a-fseeko.o):(.literal+0x10): undefined reference to `_fstat_r' ../lib/gcc/xtensa-lx106-elf/4.8.2/../../../../xtensa-lx106-elf/lib\libc.a(lib_a-fseeko.o): In function `_fseeko_r': d:\Neo\Project\ESP8266\DevKit\build\compiler\dl\esp-newlib\build\xtensa-lx106-elf\newlib\libc\stdio/../../../../../newlib/libc/stdio/fseeko.c:231: undefined reference to `_fstat_r' d:\Neo\Project\ESP8266\DevKit\build\compiler\dl\esp-newlib\build\xtensa-lx106-elf\newlib\libc\stdio/../../../../../newlib/libc/stdio/fseeko.c:258: undefined reference to `_fstat_r' ../lib/gcc/xtensa-lx106-elf/4.8.2/../../../../xtensa-lx106-elf/lib\libc.a(lib_a-makebuf.o): In function `__smakebuf_r': d:\Neo\Project\ESP8266\DevKit\build\compiler\dl\esp-newlib\build\xtensa-lx106-elf\newlib\libc\stdio/../../../../../newlib/libc/stdio/makebuf.c:59: undefined reference to `_fstat_r' ../lib/gcc/xtensa-lx106-elf/4.8.2/../../../../xtensa-lx106-elf/lib\libc.a(lib_a-mallocr.o): In function `malloc_extend_top': d:\Neo\Project\ESP8266\DevKit\build\compiler\dl\esp-newlib\build\xtensa-lx106-elf\newlib\libc\stdlib/../../../../../newlib/libc/stdlib/mallocr.c:2165: undefined reference to `_sbrk_r' d:\Neo\Project\ESP8266\DevKit\build\compiler\dl\esp-newlib\build\xtensa-lx106-elf\newlib\libc\stdlib/../../../../../newlib/libc/stdlib/mallocr.c:2202: undefined reference to `_sbrk_r' ../lib/gcc/xtensa-lx106-elf/4.8.2/../../../../xtensa-lx106-elf/lib\libc.a(lib_a-stdio.o):(.literal+0x4): undefined reference to `_read_r' ../lib/gcc/xtensa-lx106-elf/4.8.2/../../../../xtensa-lx106-elf/lib\libc.a(lib_a-stdio.o):(.literal+0x8): undefined reference to `_lseek_r' ../lib/gcc/xtensa-lx106-elf/4.8.2/../../../../xtensa-lx106-elf/lib\libc.a(lib_a-stdio.o):(.literal+0xc): undefined reference to `_write_r' ../lib/gcc/xtensa-lx106-elf/4.8.2/../../../../xtensa-lx106-elf/lib\libc.a(lib_a-stdio.o):(.literal+0x10): undefined reference to `_close_r' ../lib/gcc/xtensa-lx106-elf/4.8.2/../../../../xtensa-lx106-elf/lib\libc.a(lib_a-stdio.o): In function `__sread': d:\Neo\Project\ESP8266\DevKit\build\compiler\dl\esp-newlib\build\xtensa-lx106-elf\newlib\libc\stdio/../../../../../newlib/libc/stdio/stdio.c:48: undefined reference to `_read_r' ../lib/gcc/xtensa-lx106-elf/4.8.2/../../../../xtensa-lx106-elf/lib\libc.a(lib_a-stdio.o): In function `__swrite': d:\Neo\Project\ESP8266\DevKit\build\compiler\dl\esp-newlib\build\xtensa-lx106-elf\newlib\libc\stdio/../../../../../newlib/libc/stdio/stdio.c:89: undefined reference to `_lseek_r' d:\Neo\Project\ESP8266\DevKit\build\compiler\dl\esp-newlib\build\xtensa-lx106-elf\newlib\libc\stdio/../../../../../newlib/libc/stdio/stdio.c:97: undefined reference to `_write_r' ../lib/gcc/xtensa-lx106-elf/4.8.2/../../../../xtensa-lx106-elf/lib\libc.a(lib_a-stdio.o): In function `__sseek': d:\Neo\Project\ESP8266\DevKit\build\compiler\dl\esp-newlib\build\xtensa-lx106-elf\newlib\libc\stdio/../../../../../newlib/libc/stdio/stdio.c:117: undefined reference to `_lseek_r' ../lib/gcc/xtensa-lx106-elf/4.8.2/../../../../xtensa-lx106-elf/lib\libc.a(lib_a-stdio.o): In function `__sclose': d:\Neo\Project\ESP8266\DevKit\build\compiler\dl\esp-newlib\build\xtensa-lx106-elf\newlib\libc\stdio/../../../../../newlib/libc/stdio/stdio.c:135: undefined reference to `_close_r' ../lib/gcc/xtensa-lx106-elf/4.8.2/../../../../xtensa-lx106-elf/lib\libc.a(lib_a-sysclose.o): In function `close': d:\Neo\Project\ESP8266\DevKit\build\compiler\dl\esp-newlib\build\xtensa-lx106-elf\newlib\libc\syscalls/../../../../../newlib/libc/syscalls/sysclose.c:10: undefined reference to `_close_r' ../lib/gcc/xtensa-lx106-elf/4.8.2/../../../../xtensa-lx106-elf/lib\libc.a(lib_a-time.o):(.literal+0x0): undefined reference to `_gettimeofday_r' ../lib/gcc/xtensa-lx106-elf/4.8.2/../../../../xtensa-lx106-elf/lib\libc.a(lib_a-time.o): In function `time': d:\Neo\Project\ESP8266\DevKit\build\compiler\dl\esp-newlib\build\xtensa-lx106-elf\newlib\libc\time/../../../../../newlib/libc/time/time.c:46: undefined reference to `_gettimeofday_r' ../lib/gcc/xtensa-lx106-elf/4.8.2/../../../../xtensa-lx106-elf/lib\libc.a(isatty.o): In function `_isatty_r': d:\Neo\Project\ESP8266\DevKit\build\compiler\dl\esp-newlib\build\xtensa-lx106-elf\newlib\libc\sys\xtensa/../../../../../../newlib/libc/sys/xtensa/isatty.c:13: undefined reference to `_fstat_r' collect2.exe: error: ld returned 1 exit status --- hardware/esp8266com/esp8266/platform.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hardware/esp8266com/esp8266/platform.txt b/hardware/esp8266com/esp8266/platform.txt index ebeeadfd4..cd09aff98 100644 --- a/hardware/esp8266com/esp8266/platform.txt +++ b/hardware/esp8266com/esp8266/platform.txt @@ -23,7 +23,7 @@ compiler.S.flags=-c -g -x assembler-with-cpp -MMD compiler.c.elf.ldscript=eagle.app.v6.ld compiler.c.elf.flags=-nostdlib -Wl,--no-check-sections -u call_user_start -Wl,-static "-L{compiler.sdk.path}/lib" "-L{compiler.sdk.path}/ld" "-T{compiler.c.elf.ldscript}" compiler.c.elf.cmd=xtensa-lx106-elf-gcc -compiler.c.elf.libs=-lm -lc -lgcc -lhal -lphy -lnet80211 -llwip -lwpa -lmain -lpp -lsmartconfig +compiler.c.elf.libs=-lm -lgcc -lhal -lphy -lnet80211 -llwip -lwpa -lmain -lpp -lsmartconfig compiler.cpp.cmd=xtensa-lx106-elf-g++ compiler.cpp.flags=-c -Os -mlongcalls -mtext-section-literals -fno-exceptions -fno-rtti -std=c++11 -MMD From ae2bc12b9b55d9b927eaed3857e2d4f13fc7cfbc Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Tue, 12 May 2015 17:52:22 +0300 Subject: [PATCH 6/7] some UdpContext fixes, add rx callback support Set udp destination address, port, and multicast TTL only on send. Fix read method to return -1 if buffer is empty. --- .../libraries/ESP8266WiFi/src/WiFiUdp.cpp | 3 +- .../ESP8266WiFi/src/include/UdpContext.h | 57 +++++++++++++++---- 2 files changed, 47 insertions(+), 13 deletions(-) diff --git a/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/WiFiUdp.cpp b/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/WiFiUdp.cpp index f2328aa6b..ee3bcb6e3 100644 --- a/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/WiFiUdp.cpp +++ b/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/WiFiUdp.cpp @@ -21,7 +21,8 @@ */ #define LWIP_INTERNAL - +#include + extern "C" { #include "include/wl_definitions.h" diff --git a/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/include/UdpContext.h b/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/include/UdpContext.h index e244486e1..743f76789 100644 --- a/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/include/UdpContext.h +++ b/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/include/UdpContext.h @@ -28,9 +28,13 @@ extern "C" void esp_schedule(); #define GET_IP_HDR(pb) reinterpret_cast(((uint8_t*)((pb)->payload)) - UDP_HLEN - IP_HLEN); #define GET_UDP_HDR(pb) reinterpret_cast(((uint8_t*)((pb)->payload)) - UDP_HLEN); + class UdpContext { public: + + typedef std::function rxhandler_t; + UdpContext() : _pcb(0) , _rx_buf(0) @@ -40,8 +44,11 @@ public: , _tx_buf_head(0) , _tx_buf_cur(0) , _tx_buf_offset(0) + , _multicast_ttl(1) + , _dest_port(0) { _pcb = udp_new(); + _dest_addr.addr = 0; } ~UdpContext() @@ -79,8 +86,9 @@ public: bool connect(ip_addr_t addr, uint16_t port) { - err_t err = udp_connect(_pcb, &addr, port); - return err == ERR_OK; + _dest_addr = addr; + _dest_port = port; + return true; } bool listen(ip_addr_t addr, uint16_t port) @@ -107,7 +115,13 @@ public: // newer versions of lwip have an additional field (mcast_ttl) for this purpose // and a macro to set it instead of direct field access // udp_set_multicast_ttl(_pcb, ttl); - _pcb->ttl = ttl; + _multicast_ttl = ttl; + } + + // warning: handler is called from tcp stack context + // esp_yield and non-reentrant functions which depend on it will fail + void onRx(rxhandler_t handler) { + _on_rx = handler; } size_t getSize() const @@ -173,10 +187,10 @@ public: return _rx_buf != 0; } - char read() + int read() { if (!_rx_buf || _rx_buf->len == _rx_buf_offset) - return 0; + return -1; char c = reinterpret_cast(_rx_buf->payload)[_rx_buf_offset]; _consume(1); @@ -190,7 +204,7 @@ public: size_t max_size = _rx_buf->len - _rx_buf_offset; size = (size < max_size) ? size : max_size; - DEBUGV(":rd %d, %d, %d\r\n", size, _rx_buf->len, _rx_buf_offset); + DEBUGV(":urd %d, %d, %d\r\n", size, _rx_buf->len, _rx_buf_offset); os_memcpy(dst, reinterpret_cast(_rx_buf->payload) + _rx_buf_offset, size); _consume(size); @@ -257,10 +271,19 @@ public: } } - if (addr) - udp_sendto(_pcb, _tx_buf_head, addr, port); - else - udp_send(_pcb, _tx_buf_head); + if (!addr) { + addr = &_dest_addr; + port = _dest_port; + } + + uint16_t old_ttl = _pcb->ttl; + if (ip_addr_ismulticast(addr)) { + _pcb->ttl = _multicast_ttl; + } + + udp_sendto(_pcb, _tx_buf_head, addr, port); + + _pcb->ttl = old_ttl; for (pbuf* p = _tx_buf_head; p; p = p->next) { @@ -317,16 +340,19 @@ private: { // there is some unread data // chain the new pbuf to the existing one - DEBUGV(":rch %d, %d\r\n", _rx_buf->tot_len, pb->tot_len); + DEBUGV(":urch %d, %d\r\n", _rx_buf->tot_len, pb->tot_len); pbuf_cat(_rx_buf, pb); } else { - DEBUGV(":rn %d\r\n", pb->tot_len); + DEBUGV(":urn %d\r\n", pb->tot_len); _first_buf_taken = false; _rx_buf = pb; _rx_buf_offset = 0; } + if (_on_rx) { + _on_rx(); + } } @@ -341,6 +367,11 @@ private: int _refcnt; udp_pcb* _pcb; + ip_addr_t _dest_addr; + uint16_t _dest_port; + + uint16_t _multicast_ttl; + bool _first_buf_taken; pbuf* _rx_buf; size_t _rx_buf_offset; @@ -348,6 +379,8 @@ private: pbuf* _tx_buf_head; pbuf* _tx_buf_cur; size_t _tx_buf_offset; + + rxhandler_t _on_rx; }; From a1967b9cf18995cbaa8caffc9982bcb2968f7e76 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Tue, 12 May 2015 17:59:24 +0300 Subject: [PATCH 7/7] implement async replies in mDNS library No need to call mdns.update() from loop() any more. --- .../examples/HelloServer/HelloServer.ino | 1 - .../examples/SDWebServer/SDWebServer.ino | 1 - .../libraries/ESP8266mDNS/ESP8266mDNS.cpp | 44 ++++++++++++++----- .../libraries/ESP8266mDNS/ESP8266mDNS.h | 5 ++- .../mDNS_Web_Server/mDNS_Web_Server.ino | 3 -- 5 files changed, 38 insertions(+), 16 deletions(-) diff --git a/hardware/esp8266com/esp8266/libraries/ESP8266WebServer/examples/HelloServer/HelloServer.ino b/hardware/esp8266com/esp8266/libraries/ESP8266WebServer/examples/HelloServer/HelloServer.ino index 326f0df80..4264aeca9 100644 --- a/hardware/esp8266com/esp8266/libraries/ESP8266WebServer/examples/HelloServer/HelloServer.ino +++ b/hardware/esp8266com/esp8266/libraries/ESP8266WebServer/examples/HelloServer/HelloServer.ino @@ -69,6 +69,5 @@ void setup(void){ } void loop(void){ - mdns.update(); server.handleClient(); } diff --git a/hardware/esp8266com/esp8266/libraries/ESP8266WebServer/examples/SDWebServer/SDWebServer.ino b/hardware/esp8266com/esp8266/libraries/ESP8266WebServer/examples/SDWebServer/SDWebServer.ino index 02198fae3..296dd22f2 100644 --- a/hardware/esp8266com/esp8266/libraries/ESP8266WebServer/examples/SDWebServer/SDWebServer.ino +++ b/hardware/esp8266com/esp8266/libraries/ESP8266WebServer/examples/SDWebServer/SDWebServer.ino @@ -156,6 +156,5 @@ void setup(void){ } void loop(void){ - mdns.update(); server.handleClient(); } diff --git a/hardware/esp8266com/esp8266/libraries/ESP8266mDNS/ESP8266mDNS.cpp b/hardware/esp8266com/esp8266/libraries/ESP8266mDNS/ESP8266mDNS.cpp index 14ff6bcf8..3e65e6c56 100644 --- a/hardware/esp8266com/esp8266/libraries/ESP8266mDNS/ESP8266mDNS.cpp +++ b/hardware/esp8266com/esp8266/libraries/ESP8266mDNS/ESP8266mDNS.cpp @@ -42,6 +42,10 @@ License (MIT license): #define TTL_OFFSET 4 #define IP_OFFSET 10 +static const IPAddress MDNS_MULTICAST_ADDR(224, 0, 0, 251); +static const int MDNS_MULTICAST_TTL = 1; +static const int MDNS_PORT = 5353; + MDNSResponder::MDNSResponder() : _expected(NULL) @@ -49,6 +53,7 @@ MDNSResponder::MDNSResponder() , _response(NULL) , _responseLen(0) , _index(0) + , _conn(0) { } MDNSResponder::~MDNSResponder() { @@ -149,21 +154,37 @@ bool MDNSResponder::begin(const char* domain, IPAddress addr, uint32_t ttlSecond records[IP_OFFSET + 0] = (uint8_t) ipAddress; // Open the MDNS socket if it isn't already open. - if (!_mdnsConn) { - if (!_mdnsConn.beginMulticast(addr, IPAddress(224, 0, 0, 251), 5353)) { + if (!_conn) { + ip_addr_t ifaddr; + ifaddr.addr = (uint32_t) addr; + ip_addr_t multicast_addr; + multicast_addr.addr = (uint32_t) MDNS_MULTICAST_ADDR; + + if (igmp_joingroup(&ifaddr, &multicast_addr)!= ERR_OK) { return false; } - } + _conn = new UdpContext; + _conn->ref(); + + if (!_conn->listen(*IP_ADDR_ANY, MDNS_PORT)) { + return false; + } + _conn->setMulticastInterface(ifaddr); + _conn->setMulticastTTL(MDNS_MULTICAST_TTL); + _conn->onRx(std::bind(&MDNSResponder::update, this)); + _conn->connect(multicast_addr, MDNS_PORT); + } return true; } void MDNSResponder::update() { - if (!_mdnsConn.parsePacket()) - return; + if (!_conn->next()) { + return; + } // Read available data. - int n = _mdnsConn.available(); + int n = _conn->getSize(); _index = 0; @@ -172,7 +193,7 @@ void MDNSResponder::update() { #endif // Look for domain name in request and respond with canned response if found. for (int i = 0; i < n; ++i) { - uint8_t ch = tolower(_mdnsConn.read()); + uint8_t ch = tolower(_conn->read()); #ifdef MDNS_DEBUG String str(ch, 16); @@ -191,9 +212,12 @@ void MDNSResponder::update() { Serial.print("responding, i="); Serial.println(i); #endif - _mdnsConn.beginPacketMulticast(IPAddress(224, 0, 0, 251), 5353, _localAddr); - _mdnsConn.write(_response, _responseLen); - _mdnsConn.endPacket(); + ip_addr_t multicast_addr; + multicast_addr.addr = (uint32_t) MDNS_MULTICAST_ADDR; + + _conn->append(reinterpret_cast(_response), _responseLen); + _conn->send(); + _index = 0; } } diff --git a/hardware/esp8266com/esp8266/libraries/ESP8266mDNS/ESP8266mDNS.h b/hardware/esp8266com/esp8266/libraries/ESP8266mDNS/ESP8266mDNS.h index 65dd491ec..9a1fc56d3 100644 --- a/hardware/esp8266com/esp8266/libraries/ESP8266mDNS/ESP8266mDNS.h +++ b/hardware/esp8266com/esp8266/libraries/ESP8266mDNS/ESP8266mDNS.h @@ -46,6 +46,9 @@ License (MIT license): #include "ESP8266WiFi.h" #include "WiFiUdp.h" + +class UdpContext; + class MDNSResponder { public: MDNSResponder(); @@ -63,7 +66,7 @@ private: uint8_t* _response; int _responseLen; // Socket for MDNS communication - WiFiUDP _mdnsConn; + UdpContext* _conn; // local IP Address IPAddress _localAddr; }; diff --git a/hardware/esp8266com/esp8266/libraries/ESP8266mDNS/examples/mDNS_Web_Server/mDNS_Web_Server.ino b/hardware/esp8266com/esp8266/libraries/ESP8266mDNS/examples/mDNS_Web_Server/mDNS_Web_Server.ino index c174f4638..08ed4b4eb 100644 --- a/hardware/esp8266com/esp8266/libraries/ESP8266mDNS/examples/mDNS_Web_Server/mDNS_Web_Server.ino +++ b/hardware/esp8266com/esp8266/libraries/ESP8266mDNS/examples/mDNS_Web_Server/mDNS_Web_Server.ino @@ -68,9 +68,6 @@ void setup(void) void loop(void) { - // Check for any mDNS queries and send responses - mdns.update(); - // Check if a client has connected WiFiClient client = server.available(); if (!client) {