diff --git a/src/M5Display.cpp b/src/M5Display.cpp index 0e80c5a..297fce7 100644 --- a/src/M5Display.cpp +++ b/src/M5Display.cpp @@ -1,6 +1,6 @@ #include "M5Display.h" -#define BLK_PWM_CHANNEL 7 //LEDC_CHANNEL_7 +#define BLK_PWM_CHANNEL 7 // LEDC_CHANNEL_7 M5Display::M5Display() : TFT_eSPI() {} @@ -63,12 +63,12 @@ void M5Display::progressBar(int x, int y, int w, int h, uint8_t val) { #include "utility/qrcode.h" void M5Display::qrcode(const char *string, uint16_t x, uint16_t y, uint8_t width, uint8_t version) { - + // Create the QR code QRCode qrcode; uint8_t qrcodeData[qrcode_getBufferSize(version)]; qrcode_initText(&qrcode, qrcodeData, version, 0, string); - + // Top quiet zone uint8_t thickness = width / qrcode.size; uint16_t lineLength = qrcode.size * thickness; @@ -113,7 +113,6 @@ uint32_t read32(fs::File &f) { // Bodmers BMP image rendering function void M5Display::drawBmpFile(fs::FS &fs, const char *path, uint16_t x, uint16_t y) { - if ((x >= width()) || (y >= height())) return; // Open requested file on SD card @@ -184,7 +183,7 @@ void M5Display::drawBmpFile(fs::FS &fs, const char *path, uint16_t x, uint16_t y /* * JPEG - * */ + */ #include "rom/tjpgd.h" @@ -350,8 +349,8 @@ static bool jpgDecode(jpg_file_decoder_t *jpeg, } void M5Display::drawJpg(const uint8_t *jpg_data, size_t jpg_len, uint16_t x, - uint16_t y, uint16_t maxWidth, uint16_t maxHeight, - uint16_t offX, uint16_t offY, jpeg_div_t scale) { + uint16_t y, uint16_t maxWidth, uint16_t maxHeight, + uint16_t offX, uint16_t offY, jpeg_div_t scale) { if ((x + maxWidth) > width() || (y + maxHeight) > height()) { log_e("Bad dimensions given"); return; @@ -381,10 +380,9 @@ void M5Display::drawJpg(const uint8_t *jpg_data, size_t jpg_len, uint16_t x, jpgDecode(&jpeg, jpgRead); } - void M5Display::drawJpgFile(fs::FS &fs, const char *path, uint16_t x, uint16_t y, - uint16_t maxWidth, uint16_t maxHeight, uint16_t offX, - uint16_t offY, jpeg_div_t scale) { + uint16_t maxWidth, uint16_t maxHeight, uint16_t offX, + uint16_t offY, jpeg_div_t scale) { if ((x + maxWidth) > width() || (y + maxHeight) > height()) { log_e("Bad dimensions given"); return; diff --git a/src/M5Display.h b/src/M5Display.h index 7581bc3..a77747c 100644 --- a/src/M5Display.h +++ b/src/M5Display.h @@ -1,80 +1,87 @@ #ifndef _M5DISPLAY_H_ -#define _M5DISPLAY_H_ + #define _M5DISPLAY_H_ -#include -#include -#include -#include "utility/In_eSPI.h" -#include "utility/Sprite.h" + #include + #include + #include + #include "utility/In_eSPI.h" + #include "utility/Sprite.h" -typedef enum { - JPEG_DIV_NONE, - JPEG_DIV_2, - JPEG_DIV_4, - JPEG_DIV_8, - JPEG_DIV_MAX -} jpeg_div_t; + typedef enum { + JPEG_DIV_NONE, + JPEG_DIV_2, + JPEG_DIV_4, + JPEG_DIV_8, + JPEG_DIV_MAX + } jpeg_div_t; -class M5Display : public TFT_eSPI { + class M5Display : public TFT_eSPI { + public: + M5Display(); + void begin(); + void sleep(); + void wakeup(); + void setBrightness(uint8_t brightness); + void clearDisplay(uint32_t color=ILI9341_BLACK) { fillScreen(color); } + void clear(uint32_t color=ILI9341_BLACK) { fillScreen(color); } + void display() {} - public: - M5Display(); - void begin(); - void sleep(); - void wakeup(); - void setBrightness(uint8_t brightness); - void clearDisplay(uint32_t color=ILI9341_BLACK) { fillScreen(color); } - void clear(uint32_t color=ILI9341_BLACK) { fillScreen(color); } - void display() {} + inline void startWrite(void){ + #if defined (SPI_HAS_TRANSACTION) && defined (SUPPORT_TRANSACTIONS) && !defined(ESP32_PARALLEL) + if (locked) { + locked = false; SPI.beginTransaction(SPISettings(SPI_FREQUENCY, MSBFIRST, SPI_MODE0)); + } + #endif + CS_L; + } + inline void endWrite(void){ + #if defined (SPI_HAS_TRANSACTION) && defined (SUPPORT_TRANSACTIONS) && !defined(ESP32_PARALLEL) + if(!inTransaction) { + if (!locked) { + locked = true; + SPI.endTransaction(); + } + } + #endif + CS_H; + } + inline void writePixel(uint16_t color) { + SPI.write16(color); + } + inline void writePixels(uint16_t * colors, uint32_t len){ + SPI.writePixels((uint8_t*)colors , len * 2); + } + void progressBar(int x, int y, int w, int h, uint8_t val); - inline void startWrite(void){ - #if defined (SPI_HAS_TRANSACTION) && defined (SUPPORT_TRANSACTIONS) && !defined(ESP32_PARALLEL) - if (locked) {locked = false; SPI.beginTransaction(SPISettings(SPI_FREQUENCY, MSBFIRST, SPI_MODE0));} - #endif - CS_L; - } - inline void endWrite(void){ - #if defined (SPI_HAS_TRANSACTION) && defined (SUPPORT_TRANSACTIONS) && !defined(ESP32_PARALLEL) - if(!inTransaction) {if (!locked) {locked = true; SPI.endTransaction();}} - #endif - CS_H; - } - inline void writePixel(uint16_t color) { SPI.write16(color); } - inline void writePixels(uint16_t * colors, uint32_t len){ - SPI.writePixels((uint8_t*)colors , len * 2); - } - void progressBar(int x, int y, int w, int h, uint8_t val); + #define setFont setFreeFont - #define setFont setFreeFont + void qrcode(const char *string, uint16_t x = 50, uint16_t y = 10, uint8_t width = 220, uint8_t version = 6); + void qrcode(const String &string, uint16_t x = 50, uint16_t y = 10, uint8_t width = 220, uint8_t version = 6); - void qrcode(const char *string, uint16_t x = 50, uint16_t y = 10, uint8_t width = 220, uint8_t version = 6); - void qrcode(const String &string, uint16_t x = 50, uint16_t y = 10, uint8_t width = 220, uint8_t version = 6); + void drawBmp(fs::FS &fs, const char *path, uint16_t x, uint16_t y); + void drawBmpFile(fs::FS &fs, const char *path, uint16_t x, uint16_t y); - void drawBmp(fs::FS &fs, const char *path, uint16_t x, uint16_t y); - void drawBmpFile(fs::FS &fs, const char *path, uint16_t x, uint16_t y); + void drawBitmap(int16_t x0, int16_t y0, int16_t w, int16_t h, const uint16_t *data); + void drawBitmap(int16_t x0, int16_t y0, int16_t w, int16_t h, const uint8_t *data); + void drawBitmap(int16_t x0, int16_t y0, int16_t w, int16_t h, uint16_t *data); + void drawBitmap(int16_t x0, int16_t y0, int16_t w, int16_t h, uint8_t *data); + void drawBitmap(int16_t x0, int16_t y0, int16_t w, int16_t h, const uint16_t *data, uint16_t transparent); - void drawBitmap(int16_t x0, int16_t y0, int16_t w, int16_t h, const uint16_t *data); - void drawBitmap(int16_t x0, int16_t y0, int16_t w, int16_t h, const uint8_t *data); - void drawBitmap(int16_t x0, int16_t y0, int16_t w, int16_t h, uint16_t *data); - void drawBitmap(int16_t x0, int16_t y0, int16_t w, int16_t h, uint8_t *data); - void drawBitmap(int16_t x0, int16_t y0, int16_t w, int16_t h, const uint16_t *data, uint16_t transparent); + void drawJpg(const uint8_t *jpg_data, size_t jpg_len, uint16_t x = 0, + uint16_t y = 0, uint16_t maxWidth = 0, uint16_t maxHeight = 0, + uint16_t offX = 0, uint16_t offY = 0, + jpeg_div_t scale = JPEG_DIV_NONE); - void drawJpg(const uint8_t *jpg_data, size_t jpg_len, uint16_t x = 0, - uint16_t y = 0, uint16_t maxWidth = 0, uint16_t maxHeight = 0, - uint16_t offX = 0, uint16_t offY = 0, - jpeg_div_t scale = JPEG_DIV_NONE); + void drawJpg(fs::FS &fs, const char *path, uint16_t x = 0, uint16_t y = 0, + uint16_t maxWidth = 0, uint16_t maxHeight = 0, + uint16_t offX = 0, uint16_t offY = 0, + jpeg_div_t scale = JPEG_DIV_NONE); - void drawJpg(fs::FS &fs, const char *path, uint16_t x = 0, uint16_t y = 0, - uint16_t maxWidth = 0, uint16_t maxHeight = 0, - uint16_t offX = 0, uint16_t offY = 0, - jpeg_div_t scale = JPEG_DIV_NONE); - - void drawJpgFile(fs::FS &fs, const char *path, uint16_t x = 0, uint16_t y = 0, - uint16_t maxWidth = 0, uint16_t maxHeight = 0, - uint16_t offX = 0, uint16_t offY = 0, - jpeg_div_t scale = JPEG_DIV_NONE); - - private: -}; + void drawJpgFile(fs::FS &fs, const char *path, uint16_t x = 0, uint16_t y = 0, + uint16_t maxWidth = 0, uint16_t maxHeight = 0, + uint16_t offX = 0, uint16_t offY = 0, + jpeg_div_t scale = JPEG_DIV_NONE); + private: + }; #endif diff --git a/src/M5Faces.cpp b/src/M5Faces.cpp index 1084c29..13a4d60 100644 --- a/src/M5Faces.cpp +++ b/src/M5Faces.cpp @@ -3,47 +3,38 @@ #include "M5Faces.h" -// ================ Faces Keyboard6 =================== +// ================ Faces Keyboard =================== #define KEYBOARD_I2C_ADDR 0x08 #define KEYBOARD_INT 5 #define READI2CSUBADDR 0 - /*----------------------------------------------------------------------* * Extentions for Facces * *----------------------------------------------------------------------*/ -bool M5Faces::canControlFaces() -{ - return M5.I2C.writeCommand(KEYBOARD_I2C_ADDR,READI2CSUBADDR); - +bool M5Faces::canControlFaces() { + return M5.I2C.writeCommand(KEYBOARD_I2C_ADDR,READI2CSUBADDR); } -M5Faces::M5Faces() -{ - pinMode(KEYBOARD_INT, INPUT_PULLUP); - +M5Faces::M5Faces() { + pinMode(KEYBOARD_INT, INPUT_PULLUP); } + uint8_t M5Faces::getch(void) { uint8_t data=0x00; - - if(kbhit()) { - - while(data==0x00) - { - if (!M5.I2C.readByte(KEYBOARD_I2C_ADDR,&data)) { - - return 0x00; - } - delay(1); - } - return data; + + if (kbhit()) { + + while (data==0x00){ + if (!M5.I2C.readByte(KEYBOARD_I2C_ADDR,&data)) { + return 0x00; + } + delay(1); } - - return 0x00; + return data; + } + return 0x00; } + bool M5Faces::kbhit(void) { - return(digitalRead(KEYBOARD_INT) == LOW); + return(digitalRead(KEYBOARD_INT) == LOW); } - - - diff --git a/src/M5Faces.h b/src/M5Faces.h index 9905c48..230fa3e 100644 --- a/src/M5Faces.h +++ b/src/M5Faces.h @@ -1,16 +1,17 @@ // Copyright (c) M5Stack. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. #ifndef M5Faces_h -#define M5Faces_h -#include "M5Stack.h" + #define M5Faces_h -class M5Faces -{ + #include "M5Stack.h" + + class M5Faces { public: - M5Faces(); - bool canControlFaces(); - uint8_t getch(void); - bool kbhit(void); + M5Faces(); + bool canControlFaces(); + uint8_t getch(void); + bool kbhit(void); private: -}; + }; + #endif diff --git a/src/M5LoRa.cpp b/src/M5LoRa.cpp index 0a64258..67b0483 100644 --- a/src/M5LoRa.cpp +++ b/src/M5LoRa.cpp @@ -62,8 +62,7 @@ LoRaClass::LoRaClass() : setTimeout(0); } -int LoRaClass::begin(long frequency) -{ +int LoRaClass::begin(long frequency) { // setup pins pinMode(_ss, OUTPUT); // set SS high @@ -113,8 +112,7 @@ int LoRaClass::begin(long frequency) return 1; } -void LoRaClass::end() -{ +void LoRaClass::end() { // put in sleep mode sleep(); @@ -122,12 +120,11 @@ void LoRaClass::end() SPI.end(); } -int LoRaClass::beginPacket(int implicitHeader) -{ +int LoRaClass::beginPacket(int implicitHeader) { // put in standby mode idle(); - if (implicitHeader) { + if (implicitHeader == true) { implicitHeaderMode(); } else { explicitHeaderMode(); @@ -140,8 +137,7 @@ int LoRaClass::beginPacket(int implicitHeader) return 1; } -int LoRaClass::endPacket() -{ +int LoRaClass::endPacket() { // put in TX mode writeRegister(REG_OP_MODE, MODE_LONG_RANGE_MODE | MODE_TX); @@ -156,8 +152,7 @@ int LoRaClass::endPacket() return 1; } -int LoRaClass::parsePacket(int size) -{ +int LoRaClass::parsePacket(int size) { int packetLength = 0; int irqFlags = readRegister(REG_IRQ_FLAGS); @@ -177,7 +172,7 @@ int LoRaClass::parsePacket(int size) _packetIndex = 0; // read packet length - if (_implicitHeaderMode) { + if (_implicitHeaderMode == true) { packetLength = readRegister(REG_PAYLOAD_LENGTH); } else { packetLength = readRegister(REG_RX_NB_BYTES); @@ -201,23 +196,19 @@ int LoRaClass::parsePacket(int size) return packetLength; } -int LoRaClass::packetRssi() -{ +int LoRaClass::packetRssi() { return (readRegister(REG_PKT_RSSI_VALUE) - (_frequency < 868E6 ? 164 : 157)); } -float LoRaClass::packetSnr() -{ +float LoRaClass::packetSnr() { return ((int8_t)readRegister(REG_PKT_SNR_VALUE)) * 0.25; } -size_t LoRaClass::write(uint8_t byte) -{ +size_t LoRaClass::write(uint8_t byte) { return write(&byte, sizeof(byte)); } -size_t LoRaClass::write(const uint8_t *buffer, size_t size) -{ +size_t LoRaClass::write(const uint8_t *buffer, size_t size) { int currentLength = readRegister(REG_PAYLOAD_LENGTH); // check size @@ -236,14 +227,12 @@ size_t LoRaClass::write(const uint8_t *buffer, size_t size) return size; } -int LoRaClass::available() -{ +int LoRaClass::available() { return (readRegister(REG_RX_NB_BYTES) - _packetIndex); } -int LoRaClass::read() -{ - if (!available()) { +int LoRaClass::read() { + if (!available() == true) { return -1; } @@ -252,9 +241,8 @@ int LoRaClass::read() return readRegister(REG_FIFO); } -int LoRaClass::peek() -{ - if (!available()) { +int LoRaClass::peek() { + if (!available() == true) { return -1; } @@ -270,12 +258,10 @@ int LoRaClass::peek() return b; } -void LoRaClass::flush() -{ +void LoRaClass::flush() { } -void LoRaClass::onReceive(void(*callback)(int)) -{ +void LoRaClass::onReceive(void(*callback)(int)) { _onReceive = callback; if (callback) { @@ -289,8 +275,7 @@ void LoRaClass::onReceive(void(*callback)(int)) } } -void LoRaClass::receive(int size) -{ +void LoRaClass::receive(int size) { if (size > 0) { implicitHeaderMode(); @@ -302,18 +287,15 @@ void LoRaClass::receive(int size) writeRegister(REG_OP_MODE, MODE_LONG_RANGE_MODE | MODE_RX_CONTINUOUS); } -void LoRaClass::idle() -{ +void LoRaClass::idle() { writeRegister(REG_OP_MODE, MODE_LONG_RANGE_MODE | MODE_STDBY); } -void LoRaClass::sleep() -{ +void LoRaClass::sleep() { writeRegister(REG_OP_MODE, MODE_LONG_RANGE_MODE | MODE_SLEEP); } -void LoRaClass::setTxPower(int level, int outputPin) -{ +void LoRaClass::setTxPower(int level, int outputPin) { if (PA_OUTPUT_RFO_PIN == outputPin) { // RFO if (level < 0) { @@ -335,8 +317,7 @@ void LoRaClass::setTxPower(int level, int outputPin) } } -void LoRaClass::setFrequency(long frequency) -{ +void LoRaClass::setFrequency(long frequency) { _frequency = frequency; uint64_t frf = ((uint64_t)frequency << 19) / 32000000; @@ -346,8 +327,7 @@ void LoRaClass::setFrequency(long frequency) writeRegister(REG_FRF_LSB, (uint8_t)(frf >> 0)); } -void LoRaClass::setSpreadingFactor(int sf) -{ +void LoRaClass::setSpreadingFactor(int sf) { if (sf < 6) { sf = 6; } else if (sf > 12) { @@ -365,8 +345,7 @@ void LoRaClass::setSpreadingFactor(int sf) writeRegister(REG_MODEM_CONFIG_2, (readRegister(REG_MODEM_CONFIG_2) & 0x0f) | ((sf << 4) & 0xf0)); } -void LoRaClass::setSignalBandwidth(long sbw) -{ +void LoRaClass::setSignalBandwidth(long sbw) { int bw; if (sbw <= 7.8E3) { @@ -394,8 +373,7 @@ void LoRaClass::setSignalBandwidth(long sbw) writeRegister(REG_MODEM_CONFIG_1, (readRegister(REG_MODEM_CONFIG_1) & 0x0f) | (bw << 4)); } -void LoRaClass::setCodingRate4(int denominator) -{ +void LoRaClass::setCodingRate4(int denominator) { if (denominator < 5) { denominator = 5; } else if (denominator > 8) { @@ -407,46 +385,38 @@ void LoRaClass::setCodingRate4(int denominator) writeRegister(REG_MODEM_CONFIG_1, (readRegister(REG_MODEM_CONFIG_1) & 0xf1) | (cr << 1)); } -void LoRaClass::setPreambleLength(long length) -{ +void LoRaClass::setPreambleLength(long length) { writeRegister(REG_PREAMBLE_MSB, (uint8_t)(length >> 8)); writeRegister(REG_PREAMBLE_LSB, (uint8_t)(length >> 0)); } -void LoRaClass::setSyncWord(int sw) -{ +void LoRaClass::setSyncWord(int sw) { writeRegister(REG_SYNC_WORD, sw); } -void LoRaClass::enableCrc() -{ +void LoRaClass::enableCrc() { writeRegister(REG_MODEM_CONFIG_2, readRegister(REG_MODEM_CONFIG_2) | 0x04); } -void LoRaClass::disableCrc() -{ +void LoRaClass::disableCrc() { writeRegister(REG_MODEM_CONFIG_2, readRegister(REG_MODEM_CONFIG_2) & 0xfb); } -byte LoRaClass::random() -{ +byte LoRaClass::random() { return readRegister(REG_RSSI_WIDEBAND); } -void LoRaClass::setPins(int ss, int reset, int dio0) -{ +void LoRaClass::setPins(int ss, int reset, int dio0) { _ss = ss; _reset = reset; _dio0 = dio0; } -void LoRaClass::setSPIFrequency(uint32_t frequency) -{ +void LoRaClass::setSPIFrequency(uint32_t frequency) { _spiSettings = SPISettings(frequency, MSBFIRST, SPI_MODE0); } -void LoRaClass::dumpRegisters(Stream& out) -{ +void LoRaClass::dumpRegisters(Stream& out) { for (int i = 0; i < 128; i++) { out.print("0x"); out.print(i, HEX); @@ -455,22 +425,19 @@ void LoRaClass::dumpRegisters(Stream& out) } } -void LoRaClass::explicitHeaderMode() -{ +void LoRaClass::explicitHeaderMode() { _implicitHeaderMode = 0; writeRegister(REG_MODEM_CONFIG_1, readRegister(REG_MODEM_CONFIG_1) & 0xfe); } -void LoRaClass::implicitHeaderMode() -{ +void LoRaClass::implicitHeaderMode() { _implicitHeaderMode = 1; writeRegister(REG_MODEM_CONFIG_1, readRegister(REG_MODEM_CONFIG_1) | 0x01); } -void LoRaClass::handleDio0Rise() -{ +void LoRaClass::handleDio0Rise() { int irqFlags = readRegister(REG_IRQ_FLAGS); // clear IRQ's @@ -495,18 +462,15 @@ void LoRaClass::handleDio0Rise() } } -uint8_t LoRaClass::readRegister(uint8_t address) -{ +uint8_t LoRaClass::readRegister(uint8_t address) { return singleTransfer(address & 0x7f, 0x00); } -void LoRaClass::writeRegister(uint8_t address, uint8_t value) -{ +void LoRaClass::writeRegister(uint8_t address, uint8_t value) { singleTransfer(address | 0x80, value); } -uint8_t LoRaClass::singleTransfer(uint8_t address, uint8_t value) -{ +uint8_t LoRaClass::singleTransfer(uint8_t address, uint8_t value) { uint8_t response; digitalWrite(_ss, LOW); @@ -521,9 +485,8 @@ uint8_t LoRaClass::singleTransfer(uint8_t address, uint8_t value) return response; } -void LoRaClass::onDio0Rise() -{ +void LoRaClass::onDio0Rise() { LoRa.handleDio0Rise(); } -LoRaClass LoRa; \ No newline at end of file +LoRaClass LoRa; diff --git a/src/M5LoRa.h b/src/M5LoRa.h index 25b21c2..b82ce4d 100644 --- a/src/M5LoRa.h +++ b/src/M5LoRa.h @@ -5,92 +5,92 @@ // reset on pin 36; irq on pin 26 #ifndef M5LORA_H -#define M5LORA_H + #define M5LORA_H -#include -#include + #include + #include -#define LORA_DEFAULT_SS_PIN 5 -#define LORA_DEFAULT_RESET_PIN 36 -#define LORA_DEFAULT_DIO0_PIN 26 + #define LORA_DEFAULT_SS_PIN 5 + #define LORA_DEFAULT_RESET_PIN 36 + #define LORA_DEFAULT_DIO0_PIN 26 -#define PA_OUTPUT_RFO_PIN 0 -#define PA_OUTPUT_PA_BOOST_PIN 1 + #define PA_OUTPUT_RFO_PIN 0 + #define PA_OUTPUT_PA_BOOST_PIN 1 -class LoRaClass : public Stream { -public: - LoRaClass(); + class LoRaClass : public Stream { + public: + LoRaClass(); - int begin(long frequency); - void end(); + int begin(long frequency); + void end(); - int beginPacket(int implicitHeader = false); - int endPacket(); + int beginPacket(int implicitHeader = false); + int endPacket(); - int parsePacket(int size = 0); - int packetRssi(); - float packetSnr(); + int parsePacket(int size = 0); + int packetRssi(); + float packetSnr(); - // from Print - virtual size_t write(uint8_t byte); - virtual size_t write(const uint8_t *buffer, size_t size); + // from Print + virtual size_t write(uint8_t byte); + virtual size_t write(const uint8_t *buffer, size_t size); - // from Stream - virtual int available(); - virtual int read(); - virtual int peek(); - virtual void flush(); + // from Stream + virtual int available(); + virtual int read(); + virtual int peek(); + virtual void flush(); - void onReceive(void(*callback)(int)); + void onReceive(void(*callback)(int)); - void receive(int size = 0); - void idle(); - void sleep(); + void receive(int size = 0); + void idle(); + void sleep(); - void setTxPower(int level, int outputPin = PA_OUTPUT_PA_BOOST_PIN); - void setFrequency(long frequency); - void setSpreadingFactor(int sf); - void setSignalBandwidth(long sbw); - void setCodingRate4(int denominator); - void setPreambleLength(long length); - void setSyncWord(int sw); - void enableCrc(); - void disableCrc(); + void setTxPower(int level, int outputPin = PA_OUTPUT_PA_BOOST_PIN); + void setFrequency(long frequency); + void setSpreadingFactor(int sf); + void setSignalBandwidth(long sbw); + void setCodingRate4(int denominator); + void setPreambleLength(long length); + void setSyncWord(int sw); + void enableCrc(); + void disableCrc(); - // deprecated - void crc() { enableCrc(); } - void noCrc() { disableCrc(); } + // deprecated + void crc() { enableCrc(); } + void noCrc() { disableCrc(); } - byte random(); + byte random(); - void setPins(int ss = LORA_DEFAULT_SS_PIN, int reset = LORA_DEFAULT_RESET_PIN, int dio0 = LORA_DEFAULT_DIO0_PIN); - void setSPIFrequency(uint32_t frequency); + void setPins(int ss = LORA_DEFAULT_SS_PIN, int reset = LORA_DEFAULT_RESET_PIN, int dio0 = LORA_DEFAULT_DIO0_PIN); + void setSPIFrequency(uint32_t frequency); - void dumpRegisters(Stream& out); + void dumpRegisters(Stream& out); -private: - void explicitHeaderMode(); - void implicitHeaderMode(); + private: + void explicitHeaderMode(); + void implicitHeaderMode(); - void handleDio0Rise(); + void handleDio0Rise(); - uint8_t readRegister(uint8_t address); - void writeRegister(uint8_t address, uint8_t value); - uint8_t singleTransfer(uint8_t address, uint8_t value); + uint8_t readRegister(uint8_t address); + void writeRegister(uint8_t address, uint8_t value); + uint8_t singleTransfer(uint8_t address, uint8_t value); - static void onDio0Rise(); + static void onDio0Rise(); -private: - SPISettings _spiSettings; - int _ss; - int _reset; - int _dio0; - int _frequency; - int _packetIndex; - int _implicitHeaderMode; - void (*_onReceive)(int); -}; + private: + SPISettings _spiSettings; + int _ss; + int _reset; + int _dio0; + int _frequency; + int _packetIndex; + int _implicitHeaderMode; + void (*_onReceive)(int); + }; -extern LoRaClass LoRa; + extern LoRaClass LoRa; #endif diff --git a/src/M5Stack.cpp b/src/M5Stack.cpp index b782567..035f476 100644 --- a/src/M5Stack.cpp +++ b/src/M5Stack.cpp @@ -4,81 +4,80 @@ #include "M5Stack.h" M5Stack::M5Stack() : isInited(0) { - } -void M5Stack::begin(bool LCDEnable, bool SDEnable, bool SerialEnable,bool I2CEnable) { +void M5Stack::begin(bool LCDEnable, bool SDEnable, bool SerialEnable, bool I2CEnable) { + // Correct init once + if (isInited == true) { + return; + } else { + isInited = true; + } - // Correct init once - if (isInited) return; - else isInited = true; + // UART + if (SerialEnable == true) { + Serial.begin(115200); + Serial.flush(); + delay(50); + Serial.print("M5Stack initializing..."); + } - // UART - if (SerialEnable) { - Serial.begin(115200); - Serial.flush(); - delay(50); - Serial.print("M5Stack initializing..."); - } + // LCD INIT + if (LCDEnable == true) { + Lcd.begin(); + } - // LCD INIT - if (LCDEnable) { - Lcd.begin(); - } + // TF Card + if (SDEnable == true) { + SD.begin(TFCARD_CS_PIN, SPI, 40000000); + } - // TF Card - if (SDEnable) { - SD.begin(TFCARD_CS_PIN, SPI, 40000000); - } + // TONE + // Speaker.begin(); - // TONE - // Speaker.begin(); + // Set wakeup button + Power.setWakeupButton(BUTTON_A_PIN); - // Set wakeup button - Power.setWakeupButton(BUTTON_A_PIN); + // I2C init + if (I2CEnable == true) { + Wire.begin(21, 22); + } - // I2C init - if(I2CEnable) - { - Wire.begin(21, 22); - } - - if (SerialEnable) { - Serial.println("OK"); - } + if (SerialEnable == true) { + Serial.println("OK"); + } } void M5Stack::update() { + //Button update + BtnA.read(); + BtnB.read(); + BtnC.read(); - //Button update - BtnA.read(); - BtnB.read(); - BtnC.read(); - - //Speaker update - Speaker.update(); + //Speaker update + Speaker.update(); } /** * Function has been move to Power class.(for compatibility) * This name will be removed in a future release. */ -void M5Stack::setPowerBoostKeepOn(bool en){ - M5.Power.setPowerBoostKeepOn(en); +void M5Stack::setPowerBoostKeepOn(bool en) { + M5.Power.setPowerBoostKeepOn(en); } /** * Function has been move to Power class.(for compatibility) * This name will be removed in a future release. */ void M5Stack::setWakeupButton(uint8_t button) { - M5.Power.setWakeupButton(button); + M5.Power.setWakeupButton(button); } /** * Function has been move to Power class.(for compatibility) * This name will be removed in a future release. */ void M5Stack::powerOFF() { - M5.Power.deepSleep(); + M5.Power.deepSleep(); } M5Stack M5; diff --git a/src/M5Stack.h b/src/M5Stack.h index 108f521..db41572 100644 --- a/src/M5Stack.h +++ b/src/M5Stack.h @@ -15,7 +15,7 @@ * This file is a drive for M5Stack core. * * \par Method List: - * + * * System: M5.begin(); M5.update(); @@ -27,7 +27,7 @@ M5.Power.isChargeFull(); M5.Power.setWakeupButton(uint8_t button); M5.Power.powerOFF(); - + bool setPowerBoostOnOff(bool en); bool setPowerBoostSet(bool en); bool setPowerVin(bool en); @@ -64,7 +64,6 @@ M5.Lcd.drawJpgFile(fs::FS &fs, const char *path, uint16_t x, uint16_t y); M5.Lcd.drawBmpFile(fs::FS &fs, const char *path, uint16_t x, uint16_t y); - Button: M5.BtnA/B/C.read(); M5.BtnA/B/C.isPressed(); @@ -94,77 +93,75 @@ */ #ifndef _M5STACK_H_ -#define _M5STACK_H_ + #define _M5STACK_H_ + + #if defined(ESP32) -#if defined(ESP32) + // #define MPU9250_INSDE + #include "gitTagVersion.h" + #include + #include + #include + #include "FS.h" + #include "SD.h" -// #define MPU9250_INSDE -#include "gitTagVersion.h" -#include -#include -#include -#include "FS.h" -#include "SD.h" + #include "M5Display.h" + #include "utility/Config.h" + #include "utility/Button.h" + #include "utility/Speaker.h" + #include "utility/Power.h" + #include "utility/CommUtil.h" -#include "M5Display.h" -#include "utility/Config.h" -#include "utility/Button.h" -#include "utility/Speaker.h" -#include "utility/Power.h" -#include "utility/CommUtil.h" + class M5Stack + { + public: + M5Stack(); + void begin(bool LCDEnable = true, bool SDEnable = true, bool SerialEnable = true, bool I2CEnable = false); + void update(); -class M5Stack { + // Button API + #define DEBOUNCE_MS 10 + Button BtnA = Button(BUTTON_A_PIN, true, DEBOUNCE_MS); + Button BtnB = Button(BUTTON_B_PIN, true, DEBOUNCE_MS); + Button BtnC = Button(BUTTON_C_PIN, true, DEBOUNCE_MS); - public: - M5Stack(); - void begin(bool LCDEnable=true, bool SDEnable=true, bool SerialEnable=true,bool I2CEnable=false); - void update(); + // SPEAKER + SPEAKER Speaker; - // Button API - #define DEBOUNCE_MS 10 - Button BtnA = Button(BUTTON_A_PIN, true, DEBOUNCE_MS); - Button BtnB = Button(BUTTON_B_PIN, true, DEBOUNCE_MS); - Button BtnC = Button(BUTTON_C_PIN, true, DEBOUNCE_MS); + // LCD + M5Display Lcd = M5Display(); - // SPEAKER - SPEAKER Speaker; + //Power + POWER Power; - // LCD - M5Display Lcd = M5Display(); + // UART + // HardwareSerial Serial0 = HardwareSerial(0); + // HardwareSerial Serial2 = HardwareSerial(2); - //Power - POWER Power; - - // UART - // HardwareSerial Serial0 = HardwareSerial(0); - // HardwareSerial Serial2 = HardwareSerial(2); - - // MPU9250 -#ifdef MPU9250_INSDE - MPU9250 IMU = MPU9250(); + // MPU9250 + #ifdef MPU9250_INSDE + MPU9250 IMU = MPU9250(); + #endif + + // I2C + CommUtil I2C = CommUtil(); + + /** + * Function has been move to Power class.(for compatibility) + * This name will be removed in a future release. + */ + void setPowerBoostKeepOn(bool en) __attribute__((deprecated)); + void setWakeupButton(uint8_t button) __attribute__((deprecated)); + void powerOFF() __attribute__((deprecated)); + + private: + bool isInited; + }; + + extern M5Stack M5; + #define m5 M5 + #define lcd Lcd + #else + #error “This library only supports boards with ESP32 processor.” + #endif #endif - // I2C - CommUtil I2C = CommUtil(); - - /** - * Function has been move to Power class.(for compatibility) - * This name will be removed in a future release. - */ - void setPowerBoostKeepOn(bool en) __attribute__ ((deprecated)); - void setWakeupButton(uint8_t button) __attribute__ ((deprecated)); - void powerOFF() __attribute__ ((deprecated)); - - private: - bool isInited; -}; - -extern M5Stack M5; -#define m5 M5 -#define lcd Lcd - -#else -#error “This library only supports boards with ESP32 processor.” -#endif - -#endif - diff --git a/src/utility/Button.cpp b/src/utility/Button.cpp index 8a19f7f..42bbfca 100644 --- a/src/utility/Button.cpp +++ b/src/utility/Button.cpp @@ -29,56 +29,54 @@ * (Note that invert cannot be implied from puEnable since an external * * pullup could be used.) * *----------------------------------------------------------------------*/ -Button::Button(uint8_t pin, uint8_t invert, uint32_t dbTime) -{ - _pin = pin; - _invert = invert; - _dbTime = dbTime; - pinMode(_pin, INPUT_PULLUP); - _state = digitalRead(_pin); - if (_invert != 0) _state = !_state; - _time = millis(); - _lastState = _state; - _changed = 0; - _hold_time = -1; - _lastTime = _time; - _lastChange = _time; - _pressTime = _time; +Button::Button(uint8_t pin, uint8_t invert, uint32_t dbTime) { + _pin = pin; + _invert = invert; + _dbTime = dbTime; + pinMode(_pin, INPUT_PULLUP); + _state = digitalRead(_pin); + if (_invert != 0) _state = !_state; + _time = millis(); + _lastState = _state; + _changed = 0; + _hold_time = -1; + _lastTime = _time; + _lastChange = _time; + _pressTime = _time; } /*----------------------------------------------------------------------* * read() returns the state of the button, 1==pressed, 0==released, * * does debouncing, captures and maintains times, previous states, etc. * *----------------------------------------------------------------------*/ -uint8_t Button::read(void) -{ - static uint32_t ms; - static uint8_t pinVal; +uint8_t Button::read(void) { + static uint32_t ms; + static uint8_t pinVal; - ms = millis(); - pinVal = digitalRead(_pin); - if (_invert != 0) pinVal = !pinVal; - if (ms - _lastChange < _dbTime) { - _lastTime = _time; - _time = ms; - _changed = 0; - return _state; + ms = millis(); + pinVal = digitalRead(_pin); + if (_invert != 0) pinVal = !pinVal; + if (ms - _lastChange < _dbTime) { + _lastTime = _time; + _time = ms; + _changed = 0; + return _state; + } + else { + _lastTime = _time; + _time = ms; + _lastState = _state; + _state = pinVal; + if (_state != _lastState) { + _lastChange = ms; + _changed = 1; + if (_state) { _pressTime = _time; } } else { - _lastTime = _time; - _time = ms; - _lastState = _state; - _state = pinVal; - if (_state != _lastState) { - _lastChange = ms; - _changed = 1; - if (_state) { _pressTime = _time; } - } - else { - _changed = 0; - } - return _state; + _changed = 0; } + return _state; + } } /*----------------------------------------------------------------------* @@ -87,11 +85,11 @@ uint8_t Button::read(void) * These functions do not cause the button to be read. * *----------------------------------------------------------------------*/ uint8_t Button::isPressed(void) { - return _state == 0 ? 0 : 1; + return _state == 0 ? 0 : 1; } uint8_t Button::isReleased(void) { - return _state == 0 ? 1 : 0; + return _state == 0 ? 1 : 0; } /*----------------------------------------------------------------------* @@ -101,16 +99,16 @@ uint8_t Button::isReleased(void) { * These functions do not cause the button to be read. * *----------------------------------------------------------------------*/ uint8_t Button::wasPressed(void) { - return _state && _changed; + return _state && _changed; } uint8_t Button::wasReleased(void) { - return !_state && _changed && millis() - _pressTime < _hold_time; + return !_state && _changed && millis() - _pressTime < _hold_time; } uint8_t Button::wasReleasefor(uint32_t ms) { - _hold_time = ms; - return !_state && _changed && millis() - _pressTime >= ms; + _hold_time = ms; + return !_state && _changed && millis() - _pressTime >= ms; } /*----------------------------------------------------------------------* * pressedFor(ms) and releasedFor(ms) check to see if the button is * @@ -119,16 +117,16 @@ uint8_t Button::wasReleasefor(uint32_t ms) { * These functions do not cause the button to be read. * *----------------------------------------------------------------------*/ uint8_t Button::pressedFor(uint32_t ms) { - return (_state == 1 && _time - _lastChange >= ms) ? 1 : 0; + return (_state == 1 && _time - _lastChange >= ms) ? 1 : 0; } uint8_t Button::releasedFor(uint32_t ms) { - return (_state == 0 && _time - _lastChange >= ms) ? 1 : 0; + return (_state == 0 && _time - _lastChange >= ms) ? 1 : 0; } /*----------------------------------------------------------------------* * lastChange() returns the time the button last changed state, * * in milliseconds. * *----------------------------------------------------------------------*/ uint32_t Button::lastChange(void) { - return _lastChange; + return _lastChange; } diff --git a/src/utility/Button.h b/src/utility/Button.h index 3b9a845..a34dd64 100644 --- a/src/utility/Button.h +++ b/src/utility/Button.h @@ -11,36 +11,35 @@ #ifndef Button_h #define Button_h // #if ARDUINO >= 100 -#include +#include // #else -// #include +// #include // #endif -class Button -{ - public: - Button(uint8_t pin, uint8_t invert, uint32_t dbTime); - uint8_t read(); - uint8_t isPressed(); - uint8_t isReleased(); - uint8_t wasPressed(); - uint8_t wasReleased(); - uint8_t pressedFor(uint32_t ms); - uint8_t releasedFor(uint32_t ms); - uint8_t wasReleasefor(uint32_t ms); - uint32_t lastChange(); +class Button { + public: + Button(uint8_t pin, uint8_t invert, uint32_t dbTime); + uint8_t read(); + uint8_t isPressed(); + uint8_t isReleased(); + uint8_t wasPressed(); + uint8_t wasReleased(); + uint8_t pressedFor(uint32_t ms); + uint8_t releasedFor(uint32_t ms); + uint8_t wasReleasefor(uint32_t ms); + uint32_t lastChange(); - private: - uint8_t _pin; //arduino pin number - uint8_t _puEnable; //internal pullup resistor enabled - uint8_t _invert; //if 0, interpret high state as pressed, else interpret low state as pressed - uint8_t _state; //current button state - uint8_t _lastState; //previous button state - uint8_t _changed; //state changed since last read - uint32_t _time; //time of current state (all times are in ms) - uint32_t _lastTime; //time of previous state - uint32_t _lastChange; //time of last state change - uint32_t _dbTime; //debounce time - uint32_t _pressTime; //press time - uint32_t _hold_time; //hold time call wasreleasefor + private: + uint8_t _pin; //arduino pin number + uint8_t _puEnable; //internal pullup resistor enabled + uint8_t _invert; //if 0, interpret high state as pressed, else interpret low state as pressed + uint8_t _state; //current button state + uint8_t _lastState; //previous button state + uint8_t _changed; //state changed since last read + uint32_t _time; //time of current state (all times are in ms) + uint32_t _lastTime; //time of previous state + uint32_t _lastChange; //time of last state change + uint32_t _dbTime; //debounce time + uint32_t _pressTime; //press time + uint32_t _hold_time; //hold time call wasreleasefor }; #endif diff --git a/src/utility/CommUtil.cpp b/src/utility/CommUtil.cpp index b83fb26..4f8d847 100644 --- a/src/utility/CommUtil.cpp +++ b/src/utility/CommUtil.cpp @@ -13,81 +13,74 @@ extern M5Stack M5; //debug for message of I2C ( bypass message to serial) //#define I2C_DEBUG_TO_SERIAL -CommUtil::CommUtil() -{ -} -// Wire.h read and write protocols -bool CommUtil::writeCommand(uint8_t address, uint8_t subAddress) -{ - bool function_result=false; - Wire.beginTransmission(address); // Initialize the Tx buffer - Wire.write(subAddress); // Put slave register address in Tx buffer - function_result=(Wire.endTransmission() == 0); // Send the Tx buffer - - #ifdef I2C_DEBUG_TO_SERIAL - Serial.printf("writeCommand:send to 0x%02x [0x%02x] result:%s\n",address,subAddress,function_result?"OK":"NG"); - #endif - - return (function_result); - +CommUtil::CommUtil() { } // Wire.h read and write protocols -bool CommUtil::writeByte(uint8_t address, uint8_t subAddress, uint8_t data) -{ - bool function_result=false; +bool CommUtil::writeCommand(uint8_t address, uint8_t subAddress) { + bool function_result = false; + Wire.beginTransmission(address); // Initialize the Tx buffer + Wire.write(subAddress); // Put slave register address in Tx buffer + function_result = (Wire.endTransmission() == 0); // Send the Tx buffer + + #ifdef I2C_DEBUG_TO_SERIAL + Serial.printf("writeCommand:send to 0x%02x [0x%02x] result:%s\n", address, subAddress, function_result ? "OK" : "NG"); + #endif + + return (function_result); +} + +// Wire.h read and write protocols +bool CommUtil::writeByte(uint8_t address, uint8_t subAddress, uint8_t data) { + bool function_result = false; Wire.beginTransmission(address); // Initialize the Tx buffer Wire.write(subAddress); // Put slave register address in Tx buffer Wire.write(data); // Put data in Tx buffer - function_result=(Wire.endTransmission() == 0); // Send the Tx buffer - + function_result = (Wire.endTransmission() == 0); // Send the Tx buffer + #ifdef I2C_DEBUG_TO_SERIAL - Serial.printf("writeByte:send to 0x%02x [0x%2x] data=0x%02x result:%s\n",address,subAddress,data,function_result?"OK":"NG"); + Serial.printf("writeByte:send to 0x%02x [0x%2x] data=0x%02x result:%s\n", address, subAddress, data, function_result ? "OK" : "NG"); #endif - + return (function_result); - } // Wire.h read and write protocols -bool CommUtil::writeBytes(uint8_t address, uint8_t subAddress, uint8_t *data,uint8_t length) -{ - bool function_result=false; +bool CommUtil::writeBytes(uint8_t address, uint8_t subAddress, uint8_t *data, uint8_t length) { + bool function_result = false; #ifdef I2C_DEBUG_TO_SERIAL - Serial.printf("writeBytes:send to 0x%02x [0x%02x] data=",address,subAddress); + Serial.printf("writeBytes:send to 0x%02x [0x%02x] data=",address,subAddress); #endif - + Wire.beginTransmission(address); // Initialize the Tx buffer Wire.write(subAddress); // Put slave register address in Tx buffer - for(int i=0;i #include -class CommUtil -{ - public: +class CommUtil { + public: CommUtil(); - bool writeCommand(uint8_t address, uint8_t subAddress); - bool writeByte(uint8_t address, uint8_t subAddress, uint8_t data); - bool writeBytes(uint8_t address, uint8_t subAddress, uint8_t *data,uint8_t length); - bool readByte(uint8_t address, uint8_t *result); - bool readByte(uint8_t address, uint8_t subAddress,uint8_t *result); - bool readBytes(uint8_t address, uint8_t count,uint8_t * dest); - bool readBytes(uint8_t address, uint8_t subAddress, uint8_t count, uint8_t * dest); - void scanID(bool *result); - - private: - + bool writeCommand(uint8_t address, uint8_t subAddress); + bool writeByte(uint8_t address, uint8_t subAddress, uint8_t data); + bool writeBytes(uint8_t address, uint8_t subAddress, uint8_t *data,uint8_t length); + bool readByte(uint8_t address, uint8_t *result); + bool readByte(uint8_t address, uint8_t subAddress,uint8_t *result); + bool readBytes(uint8_t address, uint8_t count,uint8_t * dest); + bool readBytes(uint8_t address, uint8_t subAddress, uint8_t count, uint8_t * dest); + void scanID(bool *result); + private: }; #endif diff --git a/src/utility/Config.h b/src/utility/Config.h index b91d41e..7b39083 100644 --- a/src/utility/Config.h +++ b/src/utility/Config.h @@ -1,39 +1,39 @@ #ifndef _CONFIG_H_ -#define _CONFIG_H_ + #define _CONFIG_H_ -// Screen -#define TFT_LED_PIN 32 -#define TFT_DC_PIN 27 -#define TFT_CS_PIN 14 -#define TFT_MOSI_PIN 23 -#define TFT_CLK_PIN 18 -#define TFT_RST_PIN 33 -#define TFT_MISO_PIN 19 + // Screen + #define TFT_LED_PIN 32 + #define TFT_DC_PIN 27 + #define TFT_CS_PIN 14 + #define TFT_MOSI_PIN 23 + #define TFT_CLK_PIN 18 + #define TFT_RST_PIN 33 + #define TFT_MISO_PIN 19 -// SD card -#define TFCARD_CS_PIN 4 + // SD card + #define TFCARD_CS_PIN 4 -// Buttons -#define BTN_A 0 -#define BTN_B 1 -#define BTN_C 2 -#define BUTTON_A 0 -#define BUTTON_B 1 -#define BUTTON_C 2 -#define BUTTON_A_PIN 39 -#define BUTTON_B_PIN 38 -#define BUTTON_C_PIN 37 + // Buttons + #define BTN_A 0 + #define BTN_B 1 + #define BTN_C 2 + #define BUTTON_A 0 + #define BUTTON_B 1 + #define BUTTON_C 2 + #define BUTTON_A_PIN 39 + #define BUTTON_B_PIN 38 + #define BUTTON_C_PIN 37 -// BEEP PIN -#define SPEAKER_PIN 25 -#define TONE_PIN_CHANNEL 0 + // BEEP PIN + #define SPEAKER_PIN 25 + #define TONE_PIN_CHANNEL 0 -// LORA -#define LORA_CS_PIN 5 -#define LORA_RST_PIN 26 -#define LORA_IRQ_PIN 36 + // LORA + #define LORA_CS_PIN 5 + #define LORA_RST_PIN 26 + #define LORA_IRQ_PIN 36 -// UART -#define USE_SERIAL Serial + // UART + #define USE_SERIAL Serial #endif /* SETTINGS_C */ diff --git a/src/utility/ILI9341_Defines.h b/src/utility/ILI9341_Defines.h index 96d3411..ef5b8c0 100644 --- a/src/utility/ILI9341_Defines.h +++ b/src/utility/ILI9341_Defines.h @@ -3,7 +3,6 @@ #define TFT_WIDTH 240 #define TFT_HEIGHT 320 - // Color definitions for backwards compatibility with old sketches // use colour definitions like TFT_BLACK to make sketches more portable #define ILI9341_BLACK 0x0000 /* 0, 0, 0 */ diff --git a/src/utility/ILI9341_Init.h b/src/utility/ILI9341_Init.h index 404c3b9..2f6a807 100644 --- a/src/utility/ILI9341_Init.h +++ b/src/utility/ILI9341_Init.h @@ -41,18 +41,18 @@ writedata(0x00); writedata(0x00); - writecommand(ILI9341_PWCTR1); //Power control - writedata(0x23); //VRH[5:0] + 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_PWCTR2); // Power control + writedata(0x10); // SAP[2:0];BT[3:0] - writecommand(ILI9341_VMCTR1); //VCM control + writecommand(ILI9341_VMCTR1); // VCM control writedata(0x3e); writedata(0x28); - writecommand(ILI9341_VMCTR2); //VCM control2 - writedata(0x86); //-- + writecommand(ILI9341_VMCTR2); // VCM control2 + writedata(0x86); // -- writecommand(ILI9341_MADCTL); // Memory Access Control #ifdef M5STACK @@ -76,10 +76,10 @@ writecommand(0xF2); // 3Gamma Function Disable writedata(0x00); - writecommand(ILI9341_GAMMASET); //Gamma curve selected + writecommand(ILI9341_GAMMASET); // Gamma curve selected writedata(0x01); - writecommand(ILI9341_GMCTRP1); //Set Gamma + writecommand(ILI9341_GMCTRP1); // Set Gamma writedata(0x0F); writedata(0x31); writedata(0x2B); @@ -96,7 +96,7 @@ writedata(0x09); writedata(0x00); - writecommand(ILI9341_GMCTRN1); //Set Gamma + writecommand(ILI9341_GMCTRN1); // Set Gamma writedata(0x00); writedata(0x0E); writedata(0x14); @@ -113,12 +113,11 @@ writedata(0x36); writedata(0x0F); - writecommand(ILI9341_SLPOUT); //Exit Sleep - + writecommand(ILI9341_SLPOUT); // Exit Sleep + spi_end(); delay(120); spi_begin(); - - writecommand(ILI9341_DISPON); //Display on -} \ No newline at end of file + writecommand(ILI9341_DISPON); // Display on +} diff --git a/src/utility/In_eSPI.cpp b/src/utility/In_eSPI.cpp index 000281c..b64e168 100644 --- a/src/utility/In_eSPI.cpp +++ b/src/utility/In_eSPI.cpp @@ -33,7 +33,7 @@ SPIClass spi = SPIClass(); #endif - // SUPPORT_TRANSACTIONS is mandatory for ESP32 so the hal mutex is toggled +// SUPPORT_TRANSACTIONS is mandatory for ESP32 so the hal mutex is toggled #if defined (ESP32) && !defined (SUPPORT_TRANSACTIONS) #define SUPPORT_TRANSACTIONS #endif @@ -58,7 +58,7 @@ void busDir(uint32_t mask, uint8_t mode); // establish settings and protect from interference from other // libraries. Otherwise, they simply do nothing. -inline void TFT_eSPI::spi_begin(void){ +inline void TFT_eSPI::spi_begin(void) { #if defined (SPI_HAS_TRANSACTION) && defined (SUPPORT_TRANSACTIONS) && !defined(ESP32_PARALLEL) if (locked) {locked = false; spi.beginTransaction(SPISettings(SPI_FREQUENCY, MSBFIRST, TFT_SPI_MODE)); CS_L;} #else @@ -66,49 +66,49 @@ inline void TFT_eSPI::spi_begin(void){ #endif } -inline void TFT_eSPI::spi_end(void){ +inline void TFT_eSPI::spi_end(void) { #if defined (SPI_HAS_TRANSACTION) && defined (SUPPORT_TRANSACTIONS) && !defined(ESP32_PARALLEL) - if(!inTransaction) {if (!locked) {locked = true; CS_H; spi.endTransaction();}} + if (!inTransaction) { if (!locked) { locked = true; CS_H; spi.endTransaction(); } } #else CS_H; #endif } -inline void TFT_eSPI::spi_begin_read(void){ +inline void TFT_eSPI::spi_begin_read(void) { #if defined (SPI_HAS_TRANSACTION) && defined (SUPPORT_TRANSACTIONS) && !defined(ESP32_PARALLEL) if (locked) {locked = false; spi.beginTransaction(SPISettings(SPI_READ_FREQUENCY, MSBFIRST, TFT_SPI_MODE)); CS_L;} #else #if !defined(ESP32_PARALLEL) spi.setFrequency(SPI_READ_FREQUENCY); #endif - CS_L; + CS_L; #endif } -inline void TFT_eSPI::spi_end_read(void){ +inline void TFT_eSPI::spi_end_read(void) { #if defined (SPI_HAS_TRANSACTION) && defined (SUPPORT_TRANSACTIONS) && !defined(ESP32_PARALLEL) - if(!inTransaction) {if (!locked) {locked = true; CS_H; spi.endTransaction();}} + if (!inTransaction) { if (!locked) { locked = true; CS_H; spi.endTransaction(); } } #else #if !defined(ESP32_PARALLEL) spi.setFrequency(SPI_FREQUENCY); #endif - CS_H; + CS_H; #endif } #if defined (TOUCH_CS) && defined (SPI_TOUCH_FREQUENCY) // && !defined(ESP32_PARALLEL) - inline void TFT_eSPI::spi_begin_touch(void){ + inline void TFT_eSPI::spi_begin_touch(void) { #if defined (SPI_HAS_TRANSACTION) && defined (SUPPORT_TRANSACTIONS) - if (locked) {locked = false; spi.beginTransaction(SPISettings(SPI_TOUCH_FREQUENCY, MSBFIRST, SPI_MODE0));} + if (locked) { locked = false; spi.beginTransaction(SPISettings(SPI_TOUCH_FREQUENCY, MSBFIRST, SPI_MODE0)); } #else spi.setFrequency(SPI_TOUCH_FREQUENCY); #endif } - inline void TFT_eSPI::spi_end_touch(void){ + inline void TFT_eSPI::spi_end_touch(void) { #if defined (SPI_HAS_TRANSACTION) && defined (SUPPORT_TRANSACTIONS) - if(!inTransaction) {if (!locked) {locked = true; spi.endTransaction();}} + if (!inTransaction) { if (!locked) { locked = true; spi.endTransaction(); } } #else spi.setFrequency(SPI_FREQUENCY); #endif @@ -116,12 +116,12 @@ inline void TFT_eSPI::spi_end_read(void){ #endif + /*************************************************************************************** ** Function name: TFT_eSPI ** Description: Constructor , we must use hardware SPI pins ***************************************************************************************/ -TFT_eSPI::TFT_eSPI(int16_t w, int16_t h) -{ +TFT_eSPI::TFT_eSPI(int16_t w, int16_t h) { // The control pins are deliberately set to the inactive state (CS high) as setup() // might call and initialise other SPI peripherals which would could cause conflicts @@ -157,17 +157,16 @@ TFT_eSPI::TFT_eSPI(int16_t w, int16_t h) #ifdef ESP32_PARALLEL // Create a bit set lookup table for data bus - wastes 1kbyte of RAM but speeds things up dramatically - for (int32_t c = 0; c<256; c++) - { + for (int32_t c = 0; c < 256; c++) { xset_mask[c] = 0; - if ( c & 0x01 ) xset_mask[c] |= (1 << TFT_D0); - if ( c & 0x02 ) xset_mask[c] |= (1 << TFT_D1); - if ( c & 0x04 ) xset_mask[c] |= (1 << TFT_D2); - if ( c & 0x08 ) xset_mask[c] |= (1 << TFT_D3); - if ( c & 0x10 ) xset_mask[c] |= (1 << TFT_D4); - if ( c & 0x20 ) xset_mask[c] |= (1 << TFT_D5); - if ( c & 0x40 ) xset_mask[c] |= (1 << TFT_D6); - if ( c & 0x80 ) xset_mask[c] |= (1 << TFT_D7); + if (c & 0x01) xset_mask[c] |= (1 << TFT_D0); + if (c & 0x02) xset_mask[c] |= (1 << TFT_D1); + if (c & 0x04) xset_mask[c] |= (1 << TFT_D2); + if (c & 0x08) xset_mask[c] |= (1 << TFT_D3); + if (c & 0x10) xset_mask[c] |= (1 << TFT_D4); + if (c & 0x20) xset_mask[c] |= (1 << TFT_D5); + if (c & 0x40) xset_mask[c] |= (1 << TFT_D6); + if (c & 0x80) xset_mask[c] |= (1 << TFT_D7); } // Make sure read is high before we set the bus to output @@ -247,9 +246,8 @@ TFT_eSPI::TFT_eSPI(int16_t w, int16_t h) ** Function name: begin ** Description: Included for backwards compatibility ***************************************************************************************/ -void TFT_eSPI::begin(uint8_t tc) -{ - init(tc); +void TFT_eSPI::begin(uint8_t tc) { + init(tc); } @@ -257,10 +255,8 @@ void TFT_eSPI::begin(uint8_t tc) ** Function name: init (tc is tab colour for ST7735 displays only) ** Description: Reset, then initialise the TFT display registers ***************************************************************************************/ -void TFT_eSPI::init(uint8_t tc) -{ - if (_booted) - { +void TFT_eSPI::init(uint8_t tc) { + if (_booted) { #if !defined (ESP32) #ifdef TFT_CS cspinmask = (uint32_t) digitalPinToBitMask(TFT_CS); @@ -417,8 +413,7 @@ void TFT_eSPI::init(uint8_t tc) ** Function name: setRotation ** Description: rotate the screen orientation m = 0-3 or 4-7 for BMP drawing ***************************************************************************************/ -void TFT_eSPI::setRotation(uint8_t m) -{ +void TFT_eSPI::setRotation(uint8_t m) { spi_begin(); @@ -471,8 +466,7 @@ void TFT_eSPI::setRotation(uint8_t m) ** Function name: commandList, used for FLASH based lists only (e.g. ST7735) ** Description: Get initialisation commands from FLASH and send to TFT ***************************************************************************************/ -void TFT_eSPI::commandList (const uint8_t *addr) -{ +void TFT_eSPI::commandList (const uint8_t *addr) { uint8_t numCommands; uint8_t numArgs; uint8_t ms; @@ -481,22 +475,19 @@ void TFT_eSPI::commandList (const uint8_t *addr) numCommands = pgm_read_byte(addr++); // Number of commands to follow - while (numCommands--) // For each command... - { + while (numCommands--) { // For each command... writecommand(pgm_read_byte(addr++)); // Read, issue command numArgs = pgm_read_byte(addr++); // Number of args to follow ms = numArgs & TFT_INIT_DELAY; // If hibit set, delay follows args numArgs &= ~TFT_INIT_DELAY; // Mask out delay bit - while (numArgs--) // For each argument... - { + while (numArgs--) { // For each argument... writedata(pgm_read_byte(addr++)); // Read, issue argument } - if (ms) - { + if (ms) { ms = pgm_read_byte(addr++); // Read post-command delay time (ms) - delay( (ms==255 ? 500 : ms) ); + delay((ms == 255 ? 500 : ms)); } } spi_end(); @@ -507,8 +498,7 @@ void TFT_eSPI::commandList (const uint8_t *addr) ** Function name: spiwrite ** Description: Write 8 bits to SPI port (legacy support only) ***************************************************************************************/ -void TFT_eSPI::spiwrite(uint8_t c) -{ +void TFT_eSPI::spiwrite(uint8_t c) { tft_Write_8(c); } @@ -517,8 +507,7 @@ void TFT_eSPI::spiwrite(uint8_t c) ** Function name: writecommand ** Description: Send an 8 bit command to the TFT ***************************************************************************************/ -void TFT_eSPI::writecommand(uint8_t c) -{ +void TFT_eSPI::writecommand(uint8_t c) { spi_begin(); // CS_L; DC_C; @@ -528,7 +517,6 @@ void TFT_eSPI::writecommand(uint8_t c) DC_D; spi_end(); // CS_H; - } @@ -536,8 +524,7 @@ void TFT_eSPI::writecommand(uint8_t c) ** Function name: writedata ** Description: Send a 8 bit data value to the TFT ***************************************************************************************/ -void TFT_eSPI::writedata(uint8_t d) -{ +void TFT_eSPI::writedata(uint8_t d) { spi_begin(); // CS_L; DC_D; // Play safe, but should already be in data mode @@ -554,8 +541,7 @@ void TFT_eSPI::writedata(uint8_t d) ** Function name: readcommand8 ** Description: Read a 8 bit data value from an indexed command register ***************************************************************************************/ -uint8_t TFT_eSPI::readcommand8(uint8_t cmd_function, uint8_t index) -{ +uint8_t TFT_eSPI::readcommand8(uint8_t cmd_function, uint8_t index) { uint8_t reg = 0; #ifdef ESP32_PARALLEL @@ -600,8 +586,7 @@ uint8_t TFT_eSPI::readcommand8(uint8_t cmd_function, uint8_t index) ** Function name: readcommand16 ** Description: Read a 16 bit data value from an indexed command register ***************************************************************************************/ -uint16_t TFT_eSPI::readcommand16(uint8_t cmd_function, uint8_t index) -{ +uint16_t TFT_eSPI::readcommand16(uint8_t cmd_function, uint8_t index) { uint32_t reg; reg = (readcommand8(cmd_function, index + 0) << 8); @@ -615,8 +600,7 @@ uint16_t TFT_eSPI::readcommand16(uint8_t cmd_function, uint8_t index) ** Function name: readcommand32 ** Description: Read a 32 bit data value from an indexed command register ***************************************************************************************/ -uint32_t TFT_eSPI::readcommand32(uint8_t cmd_function, uint8_t index) -{ +uint32_t TFT_eSPI::readcommand32(uint8_t cmd_function, uint8_t index) { uint32_t reg; reg = (readcommand8(cmd_function, index + 0) << 24); @@ -632,8 +616,7 @@ uint32_t TFT_eSPI::readcommand32(uint8_t cmd_function, uint8_t index) ** Function name: read pixel (for SPI Interface II i.e. IM [3:0] = "1101") ** Description: Read 565 pixel colours from a pixel ***************************************************************************************/ -uint16_t TFT_eSPI::readPixel(int32_t x0, int32_t y0) -{ +uint16_t TFT_eSPI::readPixel(int32_t x0, int32_t y0) { #if defined(ESP32_PARALLEL) readAddrWindow(x0, y0, 1, 1); // Sets CS low @@ -670,7 +653,7 @@ uint16_t TFT_eSPI::readPixel(int32_t x0, int32_t y0) busDir(dir_mask, OUTPUT); // Swap Red and Blue (could check MADCTL setting to see if this is needed) - return (bgr>>11) | (bgr<<11) | (bgr & 0x7E0); + return (bgr >> 11) | (bgr << 11) | (bgr & 0x7E0); #endif #else // Not ESP32_PARALLEL @@ -717,13 +700,13 @@ uint16_t TFT_eSPI::readPixel(int32_t x0, int32_t y0) #endif } + /*************************************************************************************** ** Function name: read byte - supports class functions ** Description: Read a byte from ESP32 8 bit data port ***************************************************************************************/ // Bus MUST be set to input before calling this function! -uint8_t readByte(void) -{ +uint8_t readByte(void) { uint8_t b = 0; #ifdef ESP32_PARALLEL @@ -735,25 +718,25 @@ uint8_t readByte(void) RD_H; // Check GPIO bits used and build value - b = (((reg>>TFT_D0)&1) << 0); - b |= (((reg>>TFT_D1)&1) << 1); - b |= (((reg>>TFT_D2)&1) << 2); - b |= (((reg>>TFT_D3)&1) << 3); - b |= (((reg>>TFT_D4)&1) << 4); - b |= (((reg>>TFT_D5)&1) << 5); - b |= (((reg>>TFT_D6)&1) << 6); - b |= (((reg>>TFT_D7)&1) << 7); + b = (((reg >> TFT_D0)&1) << 0); + b |= (((reg >> TFT_D1)&1) << 1); + b |= (((reg >> TFT_D2)&1) << 2); + b |= (((reg >> TFT_D3)&1) << 3); + b |= (((reg >> TFT_D4)&1) << 4); + b |= (((reg >> TFT_D5)&1) << 5); + b |= (((reg >> TFT_D6)&1) << 6); + b |= (((reg >> TFT_D7)&1) << 7); #endif return b; } + /*************************************************************************************** ** Function name: masked GPIO direction control - supports class functions ** Description: Set masked ESP32 GPIO pins to input or output ***************************************************************************************/ -void busDir(uint32_t mask, uint8_t mode) -{ +void busDir(uint32_t mask, uint8_t mode) { #ifdef ESP32_PARALLEL // Supports GPIO 0 - 31 on ESP32 only @@ -772,12 +755,12 @@ void busDir(uint32_t mask, uint8_t mode) #endif } + /*************************************************************************************** ** Function name: read rectangle (for SPI Interface II i.e. IM [3:0] = "1101") ** Description: Read 565 pixel colours from a defined area ***************************************************************************************/ -void TFT_eSPI::readRect(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *data) -{ +void TFT_eSPI::readRect(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *data) { if ((x > _width) || (y > _height) || (w == 0) || (h == 0)) return; #if defined(ESP32_PARALLEL) @@ -800,7 +783,7 @@ void TFT_eSPI::readRect(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *da uint16_t rgb = ((readByte() & 0xF8) << 8) | ((readByte() & 0xFC) << 3) | (readByte() >> 3); // Swapped byte order for compatibility with pushRect() - *data++ = (rgb<<8) | (rgb>>8); + *data++ = (rgb << 8) | (rgb >> 8); } #else // ILI9481 reads as 16 bits // Fetch the 16 bit BRG pixels @@ -809,10 +792,10 @@ void TFT_eSPI::readRect(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *da uint16_t bgr = (readByte() << 8) | readByte(); // Swap Red and Blue (could check MADCTL setting to see if this is needed) - uint16_t rgb = (bgr>>11) | (bgr<<11) | (bgr & 0x7E0); + uint16_t rgb = (bgr >> 11) | (bgr << 11) | (bgr & 0x7E0); // Swapped byte order for compatibility with pushRect() - *data++ = (rgb<<8) | (rgb>>8); + *data++ = (rgb << 8) | (rgb >> 8); } #endif CS_H; @@ -870,13 +853,13 @@ void TFT_eSPI::readRect(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *da #endif } + /*************************************************************************************** ** Function name: tft_Read_8 ** Description: Software SPI to read bidirectional SDA line ***************************************************************************************/ #if defined (ESP8266) && defined (TFT_SDA_READ) -uint8_t TFT_eSPI::tft_Read_8(void) -{ +uint8_t TFT_eSPI::tft_Read_8(void) { uint8_t ret = 0; uint32_t reg = 0; @@ -891,13 +874,13 @@ uint8_t TFT_eSPI::tft_Read_8(void) } #endif + /*************************************************************************************** ** Function name: beginSDA ** Description: Detach SPI from pin to permit software SPI ***************************************************************************************/ #ifdef TFT_SDA_READ -void TFT_eSPI::begin_SDA_Read(void) -{ +void TFT_eSPI::begin_SDA_Read(void) { #ifdef ESP32 pinMatrixOutDetach(TFT_MOSI, false, false); pinMode(TFT_MOSI, INPUT); @@ -912,13 +895,13 @@ void TFT_eSPI::begin_SDA_Read(void) } #endif + /*************************************************************************************** ** Function name: endSDA ** Description: Attach SPI pins after software SPI ***************************************************************************************/ #ifdef TFT_SDA_READ -void TFT_eSPI::end_SDA_Read(void) -{ +void TFT_eSPI::end_SDA_Read(void) { #ifdef ESP32 pinMode(TFT_MOSI, OUTPUT); pinMatrixOutAttach(TFT_MOSI, VSPID_OUT_IDX, false, false); @@ -934,12 +917,12 @@ void TFT_eSPI::end_SDA_Read(void) } #endif + /*************************************************************************************** ** Function name: push rectangle (for SPI Interface II i.e. IM [3:0] = "1101") ** Description: push 565 pixel colours into a defined area ***************************************************************************************/ -void TFT_eSPI::pushRect(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *data) -{ +void TFT_eSPI::pushRect(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *data) { // Function deprecated, remains for backwards compatibility // pushImage() is better as it will crop partly off-screen image blocks pushImage(x, y, w, h, data); @@ -950,8 +933,7 @@ void TFT_eSPI::pushRect(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *da ** Function name: pushImage ** Description: plot 16 bit colour sprite or image onto TFT ***************************************************************************************/ -void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *data) -{ +void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *data) { if ((x >= _width) || (y >= _height)) return; @@ -975,8 +957,7 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *d data += dx + dy * w; - while (dh--) - { + while (dh--) { pushColors(data, dw, _swapBytes); data += w; } @@ -985,12 +966,12 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *d spi_end(); } + /*************************************************************************************** ** Function name: pushImage ** Description: plot 16 bit sprite or image with 1 colour being transparent ***************************************************************************************/ -void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *data, uint16_t transp) -{ +void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *data, uint16_t transp) { if ((x >= _width) || (y >= _height)) return; @@ -1018,29 +999,23 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *d if (!_swapBytes) transp = transp >> 8 | transp << 8; - while (dh--) - { + while (dh--) { int32_t len = dw; uint16_t* ptr = data; int32_t px = x; boolean move = true; uint16_t np = 0; - while (len--) - { - if (transp != *ptr) - { + while (len--) { + if (transp != *ptr) { if (move) { move = false; setWindow(px, y, xe, ye); } lineBuf[np] = *ptr; np++; - } - else - { + } else { move = true; - if (np) - { - pushColors((uint16_t*)lineBuf, np, _swapBytes); - np = 0; + if (np) { + pushColors((uint16_t*)lineBuf, np, _swapBytes); + np = 0; } } px++; @@ -1061,8 +1036,7 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *d ** Function name: pushImage - for FLASH (PROGMEM) stored images ** Description: plot 16 bit image ***************************************************************************************/ -void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, const uint16_t *data) -{ +void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, const uint16_t *data) { #ifdef ESP32 pushImage(x, y, w, h, (uint16_t*)data); #else @@ -1108,8 +1082,7 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, const uint1 // Send any partial buffer left over if (np) { - for (int32_t i = 0; i < np; i++) - { + for (int32_t i = 0; i < np; i++) { pix_buffer[i] = pgm_read_word(&data[nb * 64 + i]); } pushColors(pix_buffer, np, _swapBytes); @@ -1125,8 +1098,7 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, const uint1 ** Function name: pushImage - for FLASH (PROGMEM) stored images ** Description: plot 16 bit image with 1 colour being transparent ***************************************************************************************/ -void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, const uint16_t *data, uint16_t transp) -{ +void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, const uint16_t *data, uint16_t transp) { #ifdef ESP32 pushImage(x, y, w, h, (uint16_t*) data, transp); #else @@ -1157,8 +1129,7 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, const uint1 if (!_swapBytes) transp = transp >> 8 | transp << 8; - while (dh--) - { + while (dh--) { int32_t len = dw; uint16_t* ptr = (uint16_t*)data; int32_t px = x; @@ -1166,22 +1137,17 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, const uint1 uint16_t np = 0; - while (len--) - { + while (len--) { uint16_t color = pgm_read_word(ptr); - if (transp != color) - { + if (transp != color) { if (move) { move = false; setWindow(px, y, xe, ye); } lineBuf[np] = color; np++; - } - else - { + } else { move = true; - if (np) - { - pushColors(lineBuf, np, _swapBytes); - np = 0; + if (np) { + pushColors(lineBuf, np, _swapBytes); + np = 0; } } px++; @@ -1203,8 +1169,7 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, const uint1 ** Function name: pushImage ** Description: plot 8 bit image or sprite using a line buffer ***************************************************************************************/ -void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint8_t *data, bool bpp8) -{ +void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint8_t *data, bool bpp8) { if ((x >= _width) || (y >= (int32_t)_height)) return; int32_t dx = 0; @@ -1228,9 +1193,8 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint8_t *da // Line buffer makes plotting faster uint16_t lineBuf[dw]; - if (bpp8) - { - uint8_t blue[] = {0, 11, 21, 31}; // blue 2 to 5 bit colour lookup table + if (bpp8) { + uint8_t blue[] = { 0, 11, 21, 31 }; // blue 2 to 5 bit colour lookup table _lastColor = -1; // Set to illegal value @@ -1239,14 +1203,12 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint8_t *da uint8_t lsbColor = 0; data += dx + dy * w; - while (dh--) - { + while (dh--) { uint32_t len = dw; uint8_t* ptr = data; uint8_t* linePtr = (uint8_t*)lineBuf; - while(len--) - { + while(len--) { uint32_t color = *ptr++; // Shifts are slow so check if colour has changed first @@ -1266,28 +1228,23 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint8_t *da data += w; } - } - else - { - while (dh--) - { + } else { + while (dh--) { w = (w+7) & 0xFFF8; int32_t len = dw; uint8_t* ptr = data; uint8_t* linePtr = (uint8_t*)lineBuf; uint8_t bits = 8; - while(len>0) - { + while(len > 0) { if (len < 8) bits = len; uint32_t xp = dx; - for (uint16_t i = 0; i < bits; i++) - { + for (uint16_t i = 0; i < bits; i++) { uint8_t col = (ptr[(xp + dy * w)>>3] << (xp & 0x7)) & 0x80; - if (col) {*linePtr++ = bitmap_fg>>8; *linePtr++ = (uint8_t) bitmap_fg;} - else {*linePtr++ = bitmap_bg>>8; *linePtr++ = (uint8_t) bitmap_bg;} - //if (col) drawPixel((dw-len)+xp,h-dh,bitmap_fg); - //else drawPixel((dw-len)+xp,h-dh,bitmap_bg); + if (col) {*linePtr++ = bitmap_fg >> 8; *linePtr++ = (uint8_t) bitmap_fg;} + else {*linePtr++ = bitmap_bg >> 8; *linePtr++ = (uint8_t) bitmap_bg;} + //if (col) drawPixel((dw-len)+xp, h-dh, bitmap_fg); + //else drawPixel((dw-len)+xp, h-dh, bitmap_bg); xp++; } ptr++; @@ -1309,8 +1266,7 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint8_t *da ** Function name: pushImage ** Description: plot 8 or 1 bit image or sprite with a transparent colour ***************************************************************************************/ -void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint8_t *data, uint8_t transp, bool bpp8) -{ +void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint8_t *data, uint8_t transp, bool bpp8) { if ((x >= _width) || (y >= _height)) return; int32_t dx = 0; @@ -1334,11 +1290,10 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint8_t *da // Line buffer makes plotting faster uint16_t lineBuf[dw]; - if (bpp8) - { + if (bpp8) { data += dx + dy * w; - uint8_t blue[] = {0, 11, 21, 31}; // blue 2 to 5 bit colour lookup table + uint8_t blue[] = { 0, 11, 21, 31 }; // blue 2 to 5 bit colour lookup table _lastColor = -1; // Set to illegal value @@ -1348,8 +1303,7 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint8_t *da //int32_t spx = x, spy = y; - while (dh--) - { + while (dh--) { int32_t len = dw; uint8_t* ptr = data; uint8_t* linePtr = (uint8_t*)lineBuf; @@ -1358,10 +1312,8 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint8_t *da boolean move = true; uint16_t np = 0; - while (len--) - { - if (transp != *ptr) - { + while (len--) { + if (transp != *ptr) { if (move) { move = false; setWindow(px, y, xe, ye);} uint8_t color = *ptr; @@ -1376,12 +1328,9 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint8_t *da *linePtr++ = msbColor; *linePtr++ = lsbColor; np++; - } - else - { + } else { move = true; - if (np) - { + if (np) { pushColors(lineBuf, np, false); linePtr = (uint8_t*)lineBuf; np = 0; @@ -1396,39 +1345,29 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint8_t *da y++; data += w; } - } - else - { + } else { w = (w+7) & 0xFFF8; - while (dh--) - { + while (dh--) { int32_t px = x; boolean move = true; uint16_t np = 0; int32_t len = dw; uint8_t* ptr = data; uint8_t bits = 8; - while(len>0) - { + while(len > 0) { if (len < 8) bits = len; uint32_t xp = dx; uint32_t yp = (dy * w)>>3; - for (uint16_t i = 0; i < bits; i++) - { + for (uint16_t i = 0; i < bits; i++) { //uint8_t col = (ptr[(xp + dy * w)>>3] << (xp & 0x7)) & 0x80; - if ((ptr[(xp>>3) + yp] << (xp & 0x7)) & 0x80) - { - if (move) - { + if ((ptr[(xp >> 3) + yp] << (xp & 0x7)) & 0x80) { + if (move) { move = false; setWindow(px, y, xe, ye); } np++; - } - else - { - if (np) - { + } else { + if (np) { pushColor(bitmap_fg, np); np = 0; move = true; @@ -1455,8 +1394,7 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint8_t *da ** Function name: setSwapBytes ** Description: Used by 16 bit pushImage() to swap byte order in colours ***************************************************************************************/ -void TFT_eSPI::setSwapBytes(bool swap) -{ +void TFT_eSPI::setSwapBytes(bool swap) { _swapBytes = swap; } @@ -1465,18 +1403,17 @@ void TFT_eSPI::setSwapBytes(bool swap) ** Function name: getSwapBytes ** Description: Return the swap byte order for colours ***************************************************************************************/ -bool TFT_eSPI::getSwapBytes(void) -{ +bool TFT_eSPI::getSwapBytes(void) { return _swapBytes; } + /*************************************************************************************** ** Function name: read rectangle (for SPI Interface II i.e. IM [3:0] = "1101") ** Description: Read RGB pixel colours from a defined area ***************************************************************************************/ // If w and h are 1, then 1 pixel is read, *data array size must be 3 bytes per pixel -void TFT_eSPI::readRectRGB(int32_t x0, int32_t y0, int32_t w, int32_t h, uint8_t *data) -{ +void TFT_eSPI::readRectRGB(int32_t x0, int32_t y0, int32_t w, int32_t h, uint8_t *data) { #if defined(ESP32_PARALLEL) // ESP32 parallel bus supported yet @@ -1535,12 +1472,11 @@ void TFT_eSPI::readRectRGB(int32_t x0, int32_t y0, int32_t w, int32_t h, uint8_ ** Description: Draw a circle outline ***************************************************************************************/ // Optimised midpoint circle algorithm -void TFT_eSPI::drawCircle(int32_t x0, int32_t y0, int32_t r, uint32_t color) -{ +void TFT_eSPI::drawCircle(int32_t x0, int32_t y0, int32_t r, uint32_t color) { int32_t x = 0; int32_t dx = 1; int32_t dy = r+r; - int32_t p = -(r>>1); + int32_t p = -(r >> 1); spi_begin(); inTransaction = true; @@ -1552,16 +1488,16 @@ void TFT_eSPI::drawCircle(int32_t x0, int32_t y0, int32_t r, uint32_t color) drawPixel(x0, y0 - r, color); drawPixel(x0, y0 + r, color); - while(x=0) { + if (p>=0) { dy-=2; p-=dy; r--; } - dx+=2; - p+=dx; + dx += 2; + p += dx; x++; @@ -1587,8 +1523,7 @@ void TFT_eSPI::drawCircle(int32_t x0, int32_t y0, int32_t r, uint32_t color) ** Function name: drawCircleHelper ** Description: Support function for circle drawing ***************************************************************************************/ -void TFT_eSPI::drawCircleHelper( int32_t x0, int32_t y0, int32_t r, uint8_t cornername, uint32_t color) -{ +void TFT_eSPI::drawCircleHelper( int32_t x0, int32_t y0, int32_t r, uint8_t cornername, uint32_t color) { int32_t f = 1 - r; int32_t ddF_x = 1; int32_t ddF_y = -2 * r; @@ -1628,28 +1563,27 @@ void TFT_eSPI::drawCircleHelper( int32_t x0, int32_t y0, int32_t r, uint8_t corn ** Description: draw a filled circle ***************************************************************************************/ // Optimised midpoint circle algorithm, changed to horizontal lines (faster in sprites) -void TFT_eSPI::fillCircle(int32_t x0, int32_t y0, int32_t r, uint32_t color) -{ +void TFT_eSPI::fillCircle(int32_t x0, int32_t y0, int32_t r, uint32_t color) { int32_t x = 0; int32_t dx = 1; int32_t dy = r+r; - int32_t p = -(r>>1); + int32_t p = -(r >> 1); spi_begin(); inTransaction = true; drawFastHLine(x0 - r, y0, dy+1, color); - while(x=0) { + if (p>=0) { dy-=2; p-=dy; r--; } - dx+=2; - p+=dx; + dx += 2; + p += dx; x++; @@ -1670,8 +1604,7 @@ void TFT_eSPI::fillCircle(int32_t x0, int32_t y0, int32_t r, uint32_t color) ** Description: Support function for filled circle drawing ***************************************************************************************/ // Used to support drawing roundrects, changed to horizontal lines (faster in sprites) -void TFT_eSPI::fillCircleHelper(int32_t x0, int32_t y0, int32_t r, uint8_t cornername, int32_t delta, uint32_t color) -{ +void TFT_eSPI::fillCircleHelper(int32_t x0, int32_t y0, int32_t r, uint8_t cornername, int32_t delta, uint32_t color) { int32_t f = 1 - r; int32_t ddF_x = 1; int32_t ddF_y = -r - r; @@ -1689,8 +1622,7 @@ void TFT_eSPI::fillCircleHelper(int32_t x0, int32_t y0, int32_t r, uint8_t corne ddF_x += 2; f += ddF_x; - if (cornername & 0x1) - { + if (cornername & 0x1) { drawFastHLine(x0 - r, y0 + y, r + r + delta, color); drawFastHLine(x0 - y, y0 + r, y + y + delta, color); } @@ -1706,10 +1638,9 @@ void TFT_eSPI::fillCircleHelper(int32_t x0, int32_t y0, int32_t r, uint8_t corne ** Function name: drawEllipse ** Description: Draw a ellipse outline ***************************************************************************************/ -void TFT_eSPI::drawEllipse(int16_t x0, int16_t y0, int32_t rx, int32_t ry, uint16_t color) -{ - if (rx<2) return; - if (ry<2) return; +void TFT_eSPI::drawEllipse(int16_t x0, int16_t y0, int32_t rx, int32_t ry, uint16_t color) { + if (rx < 2) return; + if (ry < 2) return; int32_t x, y; int32_t rx2 = rx * rx; int32_t ry2 = ry * ry; @@ -1720,32 +1651,28 @@ void TFT_eSPI::drawEllipse(int16_t x0, int16_t y0, int32_t rx, int32_t ry, uint1 spi_begin(); inTransaction = true; - for (x = 0, y = ry, s = 2*ry2+rx2*(1-2*ry); ry2*x <= rx2*y; x++) - { + for (x = 0, y = ry, s = 2*ry2+rx2*(1-2*ry); ry2*x <= rx2*y; x++) { // These are ordered to minimise coordinate changes in x or y // drawPixel can then send fewer bounding box commands drawPixel(x0 + x, y0 + y, color); drawPixel(x0 - x, y0 + y, color); drawPixel(x0 - x, y0 - y, color); drawPixel(x0 + x, y0 - y, color); - if (s >= 0) - { + if (s >= 0) { s += fx2 * (1 - y); y--; } s += ry2 * ((4 * x) + 6); } - for (x = rx, y = 0, s = 2*rx2+ry2*(1-2*rx); rx2*y <= ry2*x; y++) - { + for (x = rx, y = 0, s = 2*rx2+ry2*(1-2*rx); rx2*y <= ry2*x; y++) { // These are ordered to minimise coordinate changes in x or y // drawPixel can then send fewer bounding box commands drawPixel(x0 + x, y0 + y, color); drawPixel(x0 - x, y0 + y, color); drawPixel(x0 - x, y0 - y, color); drawPixel(x0 + x, y0 - y, color); - if (s >= 0) - { + if (s >= 0) { s += fy2 * (1 - x); x--; } @@ -1761,10 +1688,9 @@ void TFT_eSPI::drawEllipse(int16_t x0, int16_t y0, int32_t rx, int32_t ry, uint1 ** Function name: fillEllipse ** Description: draw a filled ellipse ***************************************************************************************/ -void TFT_eSPI::fillEllipse(int16_t x0, int16_t y0, int32_t rx, int32_t ry, uint16_t color) -{ - if (rx<2) return; - if (ry<2) return; +void TFT_eSPI::fillEllipse(int16_t x0, int16_t y0, int32_t rx, int32_t ry, uint16_t color) { + if (rx < 2) return; + if (ry < 2) return; int32_t x, y; int32_t rx2 = rx * rx; int32_t ry2 = ry * ry; @@ -1775,26 +1701,22 @@ void TFT_eSPI::fillEllipse(int16_t x0, int16_t y0, int32_t rx, int32_t ry, uint1 spi_begin(); inTransaction = true; - for (x = 0, y = ry, s = 2*ry2+rx2*(1-2*ry); ry2*x <= rx2*y; x++) - { + for (x = 0, y = ry, s = 2*ry2+rx2*(1-2*ry); ry2*x <= rx2*y; x++) { drawFastHLine(x0 - x, y0 - y, x + x + 1, color); drawFastHLine(x0 - x, y0 + y, x + x + 1, color); - if (s >= 0) - { + if (s >= 0) { s += fx2 * (1 - y); y--; } s += ry2 * ((4 * x) + 6); } - for (x = rx, y = 0, s = 2*rx2+ry2*(1-2*rx); rx2*y <= ry2*x; y++) - { + for (x = rx, y = 0, s = 2*rx2+ry2*(1-2*rx); rx2*y <= ry2*x; y++) { drawFastHLine(x0 - x, y0 - y, x + x + 1, color); drawFastHLine(x0 - x, y0 + y, x + x + 1, color); - if (s >= 0) - { + if (s >= 0) { s += fy2 * (1 - x); x--; } @@ -1810,8 +1732,7 @@ void TFT_eSPI::fillEllipse(int16_t x0, int16_t y0, int32_t rx, int32_t ry, uint1 ** Function name: fillScreen ** Description: Clear the screen to defined colour ***************************************************************************************/ -void TFT_eSPI::fillScreen(uint32_t color) -{ +void TFT_eSPI::fillScreen(uint32_t color) { fillRect(0, 0, _width, _height, color); } @@ -1821,8 +1742,7 @@ void TFT_eSPI::fillScreen(uint32_t color) ** Description: Draw a rectangle outline ***************************************************************************************/ // Draw a rectangle -void TFT_eSPI::drawRect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t color) -{ +void TFT_eSPI::drawRect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t color) { spi_begin(); inTransaction = true; @@ -1841,8 +1761,7 @@ void TFT_eSPI::drawRect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t col ** Description: Draw a rounded corner rectangle outline ***************************************************************************************/ // Draw a rounded rectangle -void TFT_eSPI::drawRoundRect(int32_t x, int32_t y, int32_t w, int32_t h, int32_t r, uint32_t color) -{ +void TFT_eSPI::drawRoundRect(int32_t x, int32_t y, int32_t w, int32_t h, int32_t r, uint32_t color) { spi_begin(); inTransaction = true; @@ -1867,8 +1786,7 @@ void TFT_eSPI::drawRoundRect(int32_t x, int32_t y, int32_t w, int32_t h, int32_t ** Description: Draw a rounded corner filled rectangle ***************************************************************************************/ // Fill a rounded rectangle, changed to horizontal lines (faster in sprites) -void TFT_eSPI::fillRoundRect(int32_t x, int32_t y, int32_t w, int32_t h, int32_t r, uint32_t color) -{ +void TFT_eSPI::fillRoundRect(int32_t x, int32_t y, int32_t w, int32_t h, int32_t r, uint32_t color) { spi_begin(); inTransaction = true; @@ -1889,8 +1807,7 @@ void TFT_eSPI::fillRoundRect(int32_t x, int32_t y, int32_t w, int32_t h, int32_t ** Description: Draw a triangle outline using 3 arbitrary points ***************************************************************************************/ // Draw a triangle -void TFT_eSPI::drawTriangle(int32_t x0, int32_t y0, int32_t x1, int32_t y1, int32_t x2, int32_t y2, uint32_t color) -{ +void TFT_eSPI::drawTriangle(int32_t x0, int32_t y0, int32_t x1, int32_t y1, int32_t x2, int32_t y2, uint32_t color) { spi_begin(); inTransaction = true; @@ -1908,8 +1825,7 @@ void TFT_eSPI::drawTriangle(int32_t x0, int32_t y0, int32_t x1, int32_t y1, int3 ** Description: Draw a filled triangle using 3 arbitrary points ***************************************************************************************/ // Fill a triangle - original Adafruit function works well and code footprint is small -void TFT_eSPI::fillTriangle ( int32_t x0, int32_t y0, int32_t x1, int32_t y1, int32_t x2, int32_t y2, uint32_t color) -{ +void TFT_eSPI::fillTriangle ( int32_t x0, int32_t y0, int32_t x1, int32_t y1, int32_t x2, int32_t y2, uint32_t color) { int32_t a, b, y, last; // Sort coordinates by Y order (y2 >= y1 >= y0) @@ -1952,8 +1868,8 @@ void TFT_eSPI::fillTriangle ( int32_t x0, int32_t y0, int32_t x1, int32_t y1, in // error there), otherwise scanline y1 is skipped here and handled // in the second loop...which also avoids a /0 error here if y0=y1 // (flat-topped triangle). - if (y1 == y2) last = y1; // Include y1 scanline - else last = y1 - 1; // Skip it + if (y1 == y2) last = y1; // Include y1 scanline + else last = y1 - 1; // Skip it for (y = y0; y <= last; y++) { a = x0 + sa / dy01; @@ -1988,8 +1904,7 @@ void TFT_eSPI::fillTriangle ( int32_t x0, int32_t y0, int32_t x1, int32_t y1, in ** Function name: drawBitmap ** Description: Draw an image stored in an array on the TFT ***************************************************************************************/ -void TFT_eSPI::drawBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t w, int16_t h, uint16_t color) -{ +void TFT_eSPI::drawBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t w, int16_t h, uint16_t color) { spi_begin(); inTransaction = true; @@ -2012,8 +1927,7 @@ void TFT_eSPI::drawBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t w ** Function name: drawXBitmap ** Description: Draw an image stored in an XBM array onto the TFT ***************************************************************************************/ -void TFT_eSPI::drawXBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t w, int16_t h, uint16_t color) -{ +void TFT_eSPI::drawXBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t w, int16_t h, uint16_t color) { spi_begin(); inTransaction = true; @@ -2036,8 +1950,7 @@ void TFT_eSPI::drawXBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t ** Function name: drawXBitmap ** Description: Draw an XBM image with foreground and background colors ***************************************************************************************/ -void TFT_eSPI::drawXBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t w, int16_t h, uint16_t color, uint16_t bgcolor) -{ +void TFT_eSPI::drawXBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t w, int16_t h, uint16_t color, uint16_t bgcolor) { spi_begin(); inTransaction = true; @@ -2060,8 +1973,7 @@ void TFT_eSPI::drawXBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t ** Function name: setCursor ** Description: Set the text cursor x,y position ***************************************************************************************/ -void TFT_eSPI::setCursor(int16_t x, int16_t y) -{ +void TFT_eSPI::setCursor(int16_t x, int16_t y) { cursor_x = x; cursor_y = y; } @@ -2071,8 +1983,7 @@ void TFT_eSPI::setCursor(int16_t x, int16_t y) ** Function name: setCursor ** Description: Set the text cursor x,y position and font ***************************************************************************************/ -void TFT_eSPI::setCursor(int16_t x, int16_t y, uint8_t font) -{ +void TFT_eSPI::setCursor(int16_t x, int16_t y, uint8_t font) { textfont = font; cursor_x = x; cursor_y = y; @@ -2083,17 +1994,16 @@ void TFT_eSPI::setCursor(int16_t x, int16_t y, uint8_t font) ** Function name: getCursorX ** Description: Get the text cursor x position ***************************************************************************************/ -int16_t TFT_eSPI::getCursorX(void) -{ +int16_t TFT_eSPI::getCursorX(void) { return cursor_x; } + /*************************************************************************************** ** Function name: getCursorY ** Description: Get the text cursor y position ***************************************************************************************/ -int16_t TFT_eSPI::getCursorY(void) -{ +int16_t TFT_eSPI::getCursorY(void) { return cursor_y; } @@ -2102,9 +2012,8 @@ int16_t TFT_eSPI::getCursorY(void) ** Function name: setTextSize ** Description: Set the text size multiplier ***************************************************************************************/ -void TFT_eSPI::setTextSize(uint8_t s) -{ - if (s>7) s = 7; // Limit the maximum size multiplier so byte variables can be used for rendering +void TFT_eSPI::setTextSize(uint8_t s) { + if (s > 7) s = 7; // Limit the maximum size multiplier so byte variables can be used for rendering textsize = (s > 0) ? s : 1; // Don't allow font size 0 } @@ -2113,8 +2022,7 @@ void TFT_eSPI::setTextSize(uint8_t s) ** Function name: setTextColor ** Description: Set the font foreground colour (background is transparent) ***************************************************************************************/ -void TFT_eSPI::setTextColor(uint16_t c) -{ +void TFT_eSPI::setTextColor(uint16_t c) { // For 'transparent' background, we'll set the bg // to the same as fg instead of using a flag textcolor = textbgcolor = c; @@ -2125,8 +2033,7 @@ void TFT_eSPI::setTextColor(uint16_t c) ** Function name: setTextColor ** Description: Set the font foreground and background colour ***************************************************************************************/ -void TFT_eSPI::setTextColor(uint16_t c, uint16_t b) -{ +void TFT_eSPI::setTextColor(uint16_t c, uint16_t b) { textcolor = c; textbgcolor = b; } @@ -2136,8 +2043,7 @@ void TFT_eSPI::setTextColor(uint16_t c, uint16_t b) ** Function name: setPivot ** Description: Set the pivot point on the TFT *************************************************************************************x*/ -void TFT_eSPI::setPivot(int16_t x, int16_t y) -{ +void TFT_eSPI::setPivot(int16_t x, int16_t y) { _xpivot = x; _ypivot = y; } @@ -2147,8 +2053,7 @@ void TFT_eSPI::setPivot(int16_t x, int16_t y) ** Function name: getPivotX ** Description: Get the x pivot position ***************************************************************************************/ -int16_t TFT_eSPI::getPivotX(void) -{ +int16_t TFT_eSPI::getPivotX(void) { return _xpivot; } @@ -2157,8 +2062,7 @@ int16_t TFT_eSPI::getPivotX(void) ** Function name: getPivotY ** Description: Get the y pivot position ***************************************************************************************/ -int16_t TFT_eSPI::getPivotY(void) -{ +int16_t TFT_eSPI::getPivotY(void) { return _ypivot; } @@ -2167,8 +2071,7 @@ int16_t TFT_eSPI::getPivotY(void) ** Function name: setBitmapColor ** Description: Set the foreground foreground and background colour ***************************************************************************************/ -void TFT_eSPI::setBitmapColor(uint16_t c, uint16_t b) -{ +void TFT_eSPI::setBitmapColor(uint16_t c, uint16_t b) { if (c == b) b = ~c; bitmap_fg = c; bitmap_bg = b; @@ -2179,8 +2082,7 @@ void TFT_eSPI::setBitmapColor(uint16_t c, uint16_t b) ** Function name: setTextWrap ** Description: Define if text should wrap at end of line ***************************************************************************************/ -void TFT_eSPI::setTextWrap(boolean wrapX, boolean wrapY) -{ +void TFT_eSPI::setTextWrap(boolean wrapX, boolean wrapY) { textwrapX = wrapX; textwrapY = wrapY; } @@ -2190,8 +2092,7 @@ void TFT_eSPI::setTextWrap(boolean wrapX, boolean wrapY) ** Function name: setTextDatum ** Description: Set the text position reference datum ***************************************************************************************/ -void TFT_eSPI::setTextDatum(uint8_t d) -{ +void TFT_eSPI::setTextDatum(uint8_t d) { textdatum = d; } @@ -2200,8 +2101,7 @@ void TFT_eSPI::setTextDatum(uint8_t d) ** Function name: setTextPadding ** Description: Define padding width (aids erasing old text and numbers) ***************************************************************************************/ -void TFT_eSPI::setTextPadding(uint16_t x_width) -{ +void TFT_eSPI::setTextPadding(uint16_t x_width) { padX = x_width; } @@ -2210,17 +2110,16 @@ void TFT_eSPI::setTextPadding(uint16_t x_width) ** Function name: getRotation ** Description: Return the rotation value (as used by setRotation()) ***************************************************************************************/ -uint8_t TFT_eSPI::getRotation(void) -{ +uint8_t TFT_eSPI::getRotation(void) { return rotation; } + /*************************************************************************************** ** Function name: getTextDatum ** Description: Return the text datum value (as used by setTextDatum()) ***************************************************************************************/ -uint8_t TFT_eSPI::getTextDatum(void) -{ +uint8_t TFT_eSPI::getTextDatum(void) { return textdatum; } @@ -2230,8 +2129,7 @@ uint8_t TFT_eSPI::getTextDatum(void) ** Description: Return the pixel width of display (per current rotation) ***************************************************************************************/ // Return the size of the display (per current rotation) -int16_t TFT_eSPI::width(void) -{ +int16_t TFT_eSPI::width(void) { return _width; } @@ -2240,8 +2138,7 @@ int16_t TFT_eSPI::width(void) ** Function name: height ** Description: Return the pixel height of display (per current rotation) ***************************************************************************************/ -int16_t TFT_eSPI::height(void) -{ +int16_t TFT_eSPI::height(void) { return _height; } @@ -2250,47 +2147,38 @@ int16_t TFT_eSPI::height(void) ** Function name: textWidth ** Description: Return the width in pixels of a string in a given font ***************************************************************************************/ -int16_t TFT_eSPI::textWidth(const String& string) -{ +int16_t TFT_eSPI::textWidth(const String& string) { int16_t len = string.length() + 2; char buffer[len]; string.toCharArray(buffer, len); return textWidth(buffer, textfont); } -int16_t TFT_eSPI::textWidth(const String& string, uint8_t font) -{ +int16_t TFT_eSPI::textWidth(const String& string, uint8_t font) { int16_t len = string.length() + 2; char buffer[len]; string.toCharArray(buffer, len); return textWidth(buffer, font); } -int16_t TFT_eSPI::textWidth(const char *string) -{ +int16_t TFT_eSPI::textWidth(const char *string) { return textWidth(string, textfont); } -int16_t TFT_eSPI::textWidth(const char *string, uint8_t font) -{ +int16_t TFT_eSPI::textWidth(const char *string, uint8_t font) { int32_t str_width = 0; #ifdef SMOOTH_FONT - if(fontLoaded) - { - while (*string) - { + if (fontLoaded) { + while (*string) { uint16_t unicode = decodeUTF8(*string++); - if (unicode) - { + if (unicode) { if (unicode == 0x20) str_width += gFont.spaceWidth; - else - { + else { uint16_t gNum = 0; bool found = getUnicodeIndex(unicode, &gNum); - if (found) - { - if(str_width == 0 && gdX[gNum] < 0) str_width -= gdX[gNum]; + if (found) { + if (str_width == 0 && gdX[gNum] < 0) str_width -= gdX[gNum]; if (*string || isDigits) str_width += gxAdvance[gNum]; else str_width += (gdX[gNum] + gWidth[gNum]); } @@ -2306,29 +2194,23 @@ int16_t TFT_eSPI::textWidth(const char *string, uint8_t font) unsigned char uniCode; char *widthtable; - if (font>1 && font<9) - { + if (font > 1 && font < 9) { widthtable = (char *)pgm_read_dword( &(fontdata[font].widthtbl ) ) - 32; //subtract the 32 outside the loop - while (*string) - { + while (*string) { uniCode = *(string++); if (uniCode > 31 && uniCode < 128) - str_width += pgm_read_byte( widthtable + uniCode); // Normally we need to subract 32 from uniCode - else str_width += pgm_read_byte( widthtable + 32); // Set illegal character = space width + str_width += pgm_read_byte(widthtable + uniCode); // Normally we need to subract 32 from uniCode + else str_width += pgm_read_byte(widthtable + 32); // Set illegal character = space width } - } - else - { + } else { #ifdef LOAD_GFXFF - if(gfxFont) // New font + if (gfxFont) // New font { - while (*string) - { + while (*string) { uniCode = *(string++); - if ((uniCode >= (uint8_t)pgm_read_byte(&gfxFont->first)) && (uniCode <= (uint8_t)pgm_read_byte(&gfxFont->last ))) - { + if ((uniCode >= (uint8_t)pgm_read_byte(&gfxFont->first)) && (uniCode <= (uint8_t)pgm_read_byte(&gfxFont->last ))) { uniCode -= pgm_read_byte(&gfxFont->first); GFXglyph *glyph = &(((GFXglyph *)pgm_read_dword(&gfxFont->glyph))[uniCode]); // If this is not the last character or is a digit then use xAdvance @@ -2357,8 +2239,7 @@ int16_t TFT_eSPI::textWidth(const char *string, uint8_t font) ***************************************************************************************/ // Returns a value showing which fonts are loaded (bit N set = Font N loaded) -uint16_t TFT_eSPI::fontsLoaded(void) -{ +uint16_t TFT_eSPI::fontsLoaded(void) { return fontsloaded; } @@ -2367,16 +2248,14 @@ uint16_t TFT_eSPI::fontsLoaded(void) ** Function name: fontHeight ** Description: return the height of a font (yAdvance for free fonts) ***************************************************************************************/ -int16_t TFT_eSPI::fontHeight(int16_t font) -{ +int16_t TFT_eSPI::fontHeight(int16_t font) { #ifdef SMOOTH_FONT - if(fontLoaded) return gFont.yAdvance; + if (fontLoaded) return gFont.yAdvance; #endif #ifdef LOAD_GFXFF - if (font==1) - { - if(gfxFont) // New font + if (font == 1) { + if (gfxFont) // New font { return pgm_read_byte(&gfxFont->yAdvance) * textsize; } @@ -2385,17 +2264,16 @@ int16_t TFT_eSPI::fontHeight(int16_t font) return pgm_read_byte( &fontdata[font].height ) * textsize; } -int16_t TFT_eSPI::fontHeight(void) -{ +int16_t TFT_eSPI::fontHeight(void) { return fontHeight(textfont); } + /*************************************************************************************** ** Function name: drawChar ** Description: draw a single character in the Adafruit GLCD font ***************************************************************************************/ -void TFT_eSPI::drawChar(int32_t x, int32_t y, unsigned char c, uint32_t color, uint32_t bg, uint8_t size) -{ +void TFT_eSPI::drawChar(int32_t x, int32_t y, unsigned char c, uint32_t color, uint32_t bg, uint8_t size) { if ((x >= _width) || // Clip right (y >= _height) || // Clip bottom ((x + 6 * size - 1) < 0) || // Clip left @@ -2406,14 +2284,13 @@ void TFT_eSPI::drawChar(int32_t x, int32_t y, unsigned char c, uint32_t color, u #ifdef LOAD_GLCD //>>>>>>>>>>>>>>>>>> #ifdef LOAD_GFXFF - if(!gfxFont) { // 'Classic' built-in font + if (!gfxFont) { // 'Classic' built-in font #endif //>>>>>>>>>>>>>>>>>> boolean fillbg = (bg != color); - if ((size==1) && fillbg) - { + if ((size == 1) && fillbg) { uint8_t column[6]; uint8_t mask = 0x1; spi_begin(); @@ -2460,9 +2337,7 @@ void TFT_eSPI::drawChar(int32_t x, int32_t y, unsigned char c, uint32_t color, u #endif spi_end(); - } - else - { + } else { spi_begin(); inTransaction = true; for (int8_t i = 0; i < 6; i++ ) { @@ -2500,8 +2375,7 @@ void TFT_eSPI::drawChar(int32_t x, int32_t y, unsigned char c, uint32_t color, u #ifdef LOAD_GFXFF // Filter out bad characters not present in font - if ((c >= (uint8_t)pgm_read_byte(&gfxFont->first)) && (c <= (uint8_t)pgm_read_byte(&gfxFont->last ))) - { + if ((c >= (uint8_t)pgm_read_byte(&gfxFont->first)) && (c <= (uint8_t)pgm_read_byte(&gfxFont->last ))) { spi_begin(); inTransaction = true; //>>>>>>>>>>>>>>>>>>>>>>>>>>> @@ -2519,7 +2393,7 @@ void TFT_eSPI::drawChar(int32_t x, int32_t y, unsigned char c, uint32_t color, u uint8_t xx, yy, bits=0, bit=0; int16_t xo16 = 0, yo16 = 0; - if(size > 1) { + if (size > 1) { xo16 = xo; yo16 = yo; } @@ -2543,30 +2417,30 @@ void TFT_eSPI::drawChar(int32_t x, int32_t y, unsigned char c, uint32_t color, u //FIXED_SIZE is an option in User_Setup.h that only works with FAST_LINE enabled #ifdef FIXED_SIZE - x+=xo; // Save 88 bytes of FLASH - y+=yo; + x += xo; // Save 88 bytes of FLASH + y += yo; #endif #ifdef FAST_HLINE #ifdef FAST_SHIFT uint16_t hpc = 0; // Horizontal foreground pixel count - for(yy=0; yy>= 1; @@ -2574,51 +2448,51 @@ void TFT_eSPI::drawChar(int32_t x, int32_t y, unsigned char c, uint32_t color, u // Draw pixels for this line as we are about to increment yy if (hpc) { #ifndef FIXED_SIZE - if(size == 1) drawFastHLine(x+xo+xx-hpc, y+yo+yy, hpc, color); - else fillRect(x+(xo16+xx-hpc)*size, y+(yo16+yy)*size, size*hpc, size, color); + if (size == 1) drawFastHLine(x + xo + xx - hpc, y + yo + yy, hpc, color); + else fillRect(x + (xo16 + xx - hpc) * size, y + (yo16 + yy) * size, size * hpc, size, color); #else - drawFastHLine(x+xx-hpc, y+yy, hpc, color); + drawFastHLine(x + xx - hpc, y + yy, hpc, color); #endif - hpc=0; + hpc = 0; } } #else uint16_t hpc = 0; // Horizontal foreground pixel count - for(yy=0; yy> 8) | (uint16_t)(xs << 8) | ((uint8_t)(xe >> 8)<<16 | (xe << 24)); + SPI1W0 = (xs >> 8) | (uint16_t)(xs << 8) | ((uint8_t)(xe >> 8) << 16 | (xe << 24)); SPI1CMD |= SPIBUSY; while(SPI1CMD & SPIBUSY) {} @@ -2709,7 +2579,7 @@ void TFT_eSPI::setWindow(int32_t xs, int32_t ys, int32_t xe, int32_t ye) SPI1U1 = mask | (31 << SPILMOSI) | (31 << SPILMISO); // Load the two coords as a 32 bit value and shift in one go - SPI1W0 = (ys >> 8) | (uint16_t)(ys << 8) | ((uint8_t)(ye >> 8)<<16 | (ye << 24)); + SPI1W0 = (ys >> 8) | (uint16_t)(ys << 8) | ((uint8_t)(ye >> 8) << 16 | (ye << 24)); SPI1CMD |= SPIBUSY; while(SPI1CMD & SPIBUSY) {} @@ -2728,8 +2598,7 @@ void TFT_eSPI::setWindow(int32_t xs, int32_t ys, int32_t xe, int32_t ye) #elif defined (ESP8266) && !defined (RPI_WRITE_STROBE) && defined (RPI_ILI9486_DRIVER) // This is for the RPi display that needs 16 bits -void TFT_eSPI::setWindow(int32_t xs, int32_t ys, int32_t xe, int32_t ye) -{ +void TFT_eSPI::setWindow(int32_t xs, int32_t ys, int32_t xe, int32_t ye) { //spi_begin(); // Must be called before setWimdow addr_col = 0xFFFF; @@ -2743,13 +2612,13 @@ void TFT_eSPI::setWindow(int32_t xs, int32_t ys, int32_t xe, int32_t ye) SPI1U1 = mask | (CMD_BITS << SPILMOSI) | (CMD_BITS << SPILMISO); - SPI1W0 = TFT_CASET<<8; + SPI1W0 = TFT_CASET << 8; SPI1CMD |= SPIBUSY; while(SPI1CMD & SPIBUSY) {} DC_D; - uint8_t xb[] = { 0, (uint8_t) (xs>>8), 0, (uint8_t) (xs>>0), 0, (uint8_t) (xe>>8), 0, (uint8_t) (xe>>0), }; + uint8_t xb[] = { 0, (uint8_t) (xs >> 8), 0, (uint8_t) (xs >> 0), 0, (uint8_t) (xe >> 8), 0, (uint8_t) (xe >> 0), }; spi.writePattern(&xb[0], 8, 1); // Row addr set @@ -2757,20 +2626,20 @@ void TFT_eSPI::setWindow(int32_t xs, int32_t ys, int32_t xe, int32_t ye) SPI1U1 = mask | (CMD_BITS << SPILMOSI) | (CMD_BITS << SPILMISO); - SPI1W0 = TFT_PASET<<8; + SPI1W0 = TFT_PASET << 8; SPI1CMD |= SPIBUSY; while(SPI1CMD & SPIBUSY) {} DC_D; - uint8_t yb[] = { 0, (uint8_t) (ys>>8), 0, (uint8_t) (ys>>0), 0, (uint8_t) (ye>>8), 0, (uint8_t) (ye>>0), }; + uint8_t yb[] = { 0, (uint8_t) (ys >> 8), 0, (uint8_t) (ys >> 0), 0, (uint8_t) (ye >> 8), 0, (uint8_t) (ye >> 0), }; spi.writePattern(&yb[0], 8, 1); // write to RAM DC_C; SPI1U1 = mask | (CMD_BITS << SPILMOSI) | (CMD_BITS << SPILMISO); - SPI1W0 = TFT_RAMWR<<8; + SPI1W0 = TFT_RAMWR << 8; SPI1CMD |= SPIBUSY; while(SPI1CMD & SPIBUSY) {} @@ -2782,8 +2651,7 @@ void TFT_eSPI::setWindow(int32_t xs, int32_t ys, int32_t xe, int32_t ye) #else #if defined (ESP8266) && defined (RPI_ILI9486_DRIVER) // This is for the RPi display that needs 16 bits -void TFT_eSPI::setWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1) -{ +void TFT_eSPI::setWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1) { //spi_begin(); // Must be called before setWimdow uint32_t mask = ~((SPIMMOSI << SPILMOSI) | (SPIMMISO << SPILMISO)); @@ -2858,18 +2726,17 @@ void TFT_eSPI::setWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1) #else // This is for the ESP32 -void TFT_eSPI::setWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1) -{ +void TFT_eSPI::setWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1) { //spi_begin(); // Must be called before setWimdow addr_col = 0xFFFF; addr_row = 0xFFFF; #ifdef CGRAM_OFFSET - x0+=colstart; - x1+=colstart; - y0+=rowstart; - y1+=rowstart; + x0 += colstart; + x1 += colstart; + y0 += rowstart; + y1 += rowstart; #endif DC_C; @@ -2879,7 +2746,7 @@ void TFT_eSPI::setWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1) DC_D; #if defined (RPI_ILI9486_DRIVER) - uint8_t xb[] = { 0, (uint8_t) (x0>>8), 0, (uint8_t) (x0>>0), 0, (uint8_t) (x1>>8), 0, (uint8_t) (x1>>0), }; + uint8_t xb[] = { 0, (uint8_t) (x0 >> 8), 0, (uint8_t) (x0 >> 0), 0, (uint8_t) (x1 >> 8), 0, (uint8_t) (x1 >> 0), }; spi.writePattern(&xb[0], 8, 1); #else tft_Write_32(SPI_32(x0, x1)); @@ -2893,7 +2760,7 @@ void TFT_eSPI::setWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1) DC_D; #if defined (RPI_ILI9486_DRIVER) - uint8_t yb[] = { 0, (uint8_t) (y0>>8), 0, (uint8_t) (y0>>0), 0, (uint8_t) (y1>>8), 0, (uint8_t) (y1>>0), }; + uint8_t yb[] = { 0, (uint8_t) (y0 >> 8), 0, (uint8_t) (y0 >> 0), 0, (uint8_t) (y1 >> 8), 0, (uint8_t) (y1 >> 0), }; spi.writePattern(&yb[0], 8, 1); #else tft_Write_32(SPI_32(y0, y1)); @@ -2918,8 +2785,7 @@ void TFT_eSPI::setWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1) ***************************************************************************************/ // Chip select stays low #if defined (ESP8266) && !defined (RPI_WRITE_STROBE) -void TFT_eSPI::readAddrWindow(int32_t xs, int32_t ys, int32_t w, int32_t h) -{ +void TFT_eSPI::readAddrWindow(int32_t xs, int32_t ys, int32_t w, int32_t h) { spi_begin(); int32_t xe = xs + w - 1; @@ -2951,7 +2817,7 @@ void TFT_eSPI::readAddrWindow(int32_t xs, int32_t ys, int32_t w, int32_t h) SPI1U1 = mask | (31 << SPILMOSI) | (31 << SPILMISO); // Load the two coords as a 32 bit value and shift in one go - SPI1W0 = (xs >> 8) | (uint16_t)(xs << 8) | ((uint8_t)(xe >> 8)<<16 | (xe << 24)); + SPI1W0 = (xs >> 8) | (uint16_t)(xs << 8) | ((uint8_t)(xe >> 8) << 16 | (xe << 24)); SPI1CMD |= SPIBUSY; while(SPI1CMD & SPIBUSY) {} @@ -2968,7 +2834,7 @@ void TFT_eSPI::readAddrWindow(int32_t xs, int32_t ys, int32_t w, int32_t h) SPI1U1 = mask | (31 << SPILMOSI) | (31 << SPILMISO); // Load the two coords as a 32 bit value and shift in one go - SPI1W0 = (ys >> 8) | (uint16_t)(ys << 8) | ((uint8_t)(ye >> 8)<<16 | (ye << 24)); + SPI1W0 = (ys >> 8) | (uint16_t)(ys << 8) | ((uint8_t)(ye >> 8) << 16 | (ye << 24)); SPI1CMD |= SPIBUSY; while(SPI1CMD & SPIBUSY) {} @@ -2986,8 +2852,7 @@ void TFT_eSPI::readAddrWindow(int32_t xs, int32_t ys, int32_t w, int32_t h) #else //ESP32 -void TFT_eSPI::readAddrWindow(int32_t xs, int32_t ys, int32_t w, int32_t h) -{ +void TFT_eSPI::readAddrWindow(int32_t xs, int32_t ys, int32_t w, int32_t h) { spi_begin(); int32_t xe = xs + w - 1; @@ -3032,19 +2897,19 @@ ye += rowstart; #endif + /*************************************************************************************** ** Function name: drawPixel ** Description: push a single pixel at an arbitrary position ***************************************************************************************/ #if defined (ESP8266) && !defined (RPI_WRITE_STROBE) -void TFT_eSPI::drawPixel(int32_t x, int32_t y, uint32_t color) -{ +void TFT_eSPI::drawPixel(int32_t x, int32_t y, uint32_t color) { // Range checking if ((x < 0) || (y < 0) ||(x >= _width) || (y >= _height)) return; #ifdef CGRAM_OFFSET - x+=colstart; - y+=rowstart; + x += colstart; + y += rowstart; #endif spi_begin(); @@ -3064,7 +2929,7 @@ void TFT_eSPI::drawPixel(int32_t x, int32_t y, uint32_t color) DC_D; #if defined (RPI_ILI9486_DRIVER) // This is for the RPi display that needs 16 bits per byte - uint8_t cBin[] = { 0, (uint8_t) (x>>8), 0, (uint8_t) (x>>0)}; + uint8_t cBin[] = { 0, (uint8_t) (x >> 8), 0, (uint8_t) (x >> 0)}; spi.writePattern(&cBin[0], 4, 2); #else SPI1U1 = mask | (31 << SPILMOSI) | (31 << SPILMISO); @@ -3092,7 +2957,7 @@ void TFT_eSPI::drawPixel(int32_t x, int32_t y, uint32_t color) DC_D; #if defined (RPI_ILI9486_DRIVER) // This is for the RPi display that needs 16 bits per byte - uint8_t cBin[] = { 0, (uint8_t) (y>>8), 0, (uint8_t) (y>>0)}; + uint8_t cBin[] = { 0, (uint8_t) (y >> 8), 0, (uint8_t) (y >> 0)}; spi.writePattern(&cBin[0], 4, 2); #else SPI1U1 = mask | (31 << SPILMOSI) | (31 << SPILMISO); @@ -3133,8 +2998,7 @@ void TFT_eSPI::drawPixel(int32_t x, int32_t y, uint32_t color) #if defined (ESP8266) && defined (RPI_ILI9486_DRIVER) // This is for the RPi display that needs 16 bits -void TFT_eSPI::drawPixel(int32_t x, int32_t y, uint32_t color) -{ +void TFT_eSPI::drawPixel(int32_t x, int32_t y, uint32_t color) { // Range checking if ((x < 0) || (y < 0) ||(x >= _width) || (y >= _height)) return; @@ -3216,16 +3080,15 @@ void TFT_eSPI::drawPixel(int32_t x, int32_t y, uint32_t color) #else // ESP32 -void TFT_eSPI::drawPixel(int32_t x, int32_t y, uint32_t color) -{ +void TFT_eSPI::drawPixel(int32_t x, int32_t y, uint32_t color) { // Range checking if ((x < 0) || (y < 0) ||(x >= _width) || (y >= _height)) return; spi_begin(); #ifdef CGRAM_OFFSET - x+=colstart; - y+=rowstart; + x += colstart; + y += rowstart; #endif DC_C; @@ -3238,7 +3101,7 @@ void TFT_eSPI::drawPixel(int32_t x, int32_t y, uint32_t color) DC_D; #if defined (RPI_ILI9486_DRIVER) - uint8_t xb[] = { 0, (uint8_t) (x>>8), 0, (uint8_t) (x>>0), 0, (uint8_t) (x>>8), 0, (uint8_t) (x>>0), }; + uint8_t xb[] = { 0, (uint8_t) (x >> 8), 0, (uint8_t) (x >> 0), 0, (uint8_t) (x >> 8), 0, (uint8_t) (x >> 0), }; spi.writePattern(&xb[0], 8, 1); #else tft_Write_32(SPI_32(x, x)); @@ -3257,7 +3120,7 @@ void TFT_eSPI::drawPixel(int32_t x, int32_t y, uint32_t color) DC_D; #if defined (RPI_ILI9486_DRIVER) - uint8_t yb[] = { 0, (uint8_t) (y>>8), 0, (uint8_t) (y>>0), 0, (uint8_t) (y>>8), 0, (uint8_t) (y>>0), }; + uint8_t yb[] = { 0, (uint8_t) (y >> 8), 0, (uint8_t) (y >> 0), 0, (uint8_t) (y >> 8), 0, (uint8_t) (y >> 0), }; spi.writePattern(&yb[0], 8, 1); #else tft_Write_32(SPI_32(y, y)); @@ -3268,7 +3131,6 @@ void TFT_eSPI::drawPixel(int32_t x, int32_t y, uint32_t color) addr_row = y; } - tft_Write_8(TFT_RAMWR); DC_D; @@ -3285,8 +3147,7 @@ void TFT_eSPI::drawPixel(int32_t x, int32_t y, uint32_t color) ** Function name: pushColor ** Description: push a single pixel ***************************************************************************************/ -void TFT_eSPI::pushColor(uint16_t color) -{ +void TFT_eSPI::pushColor(uint16_t color) { spi_begin(); tft_Write_16(color); @@ -3299,13 +3160,12 @@ void TFT_eSPI::pushColor(uint16_t color) ** Function name: pushColor ** Description: push a single colour to "len" pixels ***************************************************************************************/ -void TFT_eSPI::pushColor(uint16_t color, uint32_t len) -{ +void TFT_eSPI::pushColor(uint16_t color, uint32_t len) { spi_begin(); #ifdef RPI_WRITE_STROBE uint8_t colorBin[] = { (uint8_t) (color >> 8), (uint8_t) color }; - if(len) spi.writePattern(&colorBin[0], 2, 1); len--; + if (len) spi.writePattern(&colorBin[0], 2, 1); len--; while(len--) {WR_L; WR_H;} #else #if defined (ESP32_PARALLEL) @@ -3318,35 +3178,35 @@ void TFT_eSPI::pushColor(uint16_t color, uint32_t len) spi_end(); } + /*************************************************************************************** ** Function name: startWrite ** Description: begin transaction with CS low, MUST later call endWrite ***************************************************************************************/ -void TFT_eSPI::startWrite(void) -{ +void TFT_eSPI::startWrite(void) { spi_begin(); inTransaction = true; } + /*************************************************************************************** ** Function name: endWrite ** Description: end transaction with CS high ***************************************************************************************/ -void TFT_eSPI::endWrite(void) -{ +void TFT_eSPI::endWrite(void) { inTransaction = false; spi_end(); } + /*************************************************************************************** ** Function name: writeColor (use startWrite() and endWrite() before & after) ** Description: raw write of "len" pixels avoiding transaction check ***************************************************************************************/ -void TFT_eSPI::writeColor(uint16_t color, uint32_t len) -{ +void TFT_eSPI::writeColor(uint16_t color, uint32_t len) { #ifdef RPI_WRITE_STROBE uint8_t colorBin[] = { (uint8_t) (color >> 8), (uint8_t) color }; - if(len) spi.writePattern(&colorBin[0], 2, 1); len--; + if (len) spi.writePattern(&colorBin[0], 2, 1); len--; while(len--) {WR_L; WR_H;} #else #if defined (ESP32_PARALLEL) @@ -3357,25 +3217,25 @@ void TFT_eSPI::writeColor(uint16_t color, uint32_t len) #endif } + /*************************************************************************************** ** Function name: pushColors ** Description: push an array of pixels for 16 bit raw image drawing ***************************************************************************************/ // Assumed that setAddrWindow() has previously been called -void TFT_eSPI::pushColors(uint8_t *data, uint32_t len) -{ +void TFT_eSPI::pushColors(uint8_t *data, uint32_t len) { spi_begin(); #if defined (RPI_WRITE_STROBE) - while ( len >=64 ) {spi.writePattern(data, 64, 1); data += 64; len -= 64; } + while (len >= 64) {spi.writePattern(data, 64, 1); data += 64; len -= 64; } if (len) spi.writePattern(data, len, 1); #else #ifdef ESP32_PARALLEL while (len--) {tft_Write_8(*data); data++;} #elif defined (ILI9488_DRIVER) uint16_t color; - while (len>1) {color = (*data++) | ((*data++)<<8); tft_Write_16(color); len-=2;} + while (len > 1) {color = (*data++) | ((*data++)<<8); tft_Write_16(color); len-=2;} #else #if (SPI_FREQUENCY == 80000000) while ( len >=64 ) {spi.writePattern(data, 64, 1); data += 64; len -= 64; } @@ -3394,8 +3254,7 @@ void TFT_eSPI::pushColors(uint8_t *data, uint32_t len) ** Function name: pushColors ** Description: push an array of pixels, for image drawing ***************************************************************************************/ -void TFT_eSPI::pushColors(uint16_t *data, uint32_t len, bool swap) -{ +void TFT_eSPI::pushColors(uint16_t *data, uint32_t len, bool swap) { spi_begin(); #if defined (ESP32) || defined (ILI9488_DRIVER) @@ -3403,8 +3262,8 @@ void TFT_eSPI::pushColors(uint16_t *data, uint32_t len, bool swap) if (swap) while ( len-- ) {tft_Write_16(*data); data++;} else while ( len-- ) {tft_Write_16S(*data); data++;} #else - if (swap) spi.writePixels(data,len<<1); - else spi.writeBytes((uint8_t*)data,len<<1); + if (swap) spi.writePixels(data, len << 1); + else spi.writeBytes((uint8_t*)data, len << 1); #endif #else @@ -3414,25 +3273,20 @@ void TFT_eSPI::pushColors(uint16_t *data, uint32_t len, bool swap) SPI1U1 = (SPI1U1 & mask) | (255 << SPILMOSI) | (255 << SPILMISO); - while(len>15) - { + while(len > 15) { - if (swap) - { + if (swap) { uint32_t i = 0; - while(i<8) - { + while(i < 8) { color[i] = (*data >> 8) | (uint16_t)(*data << 8); data++; color[i] |= ((*data >> 8) | (*data << 8)) << 16; data++; i++; } - } - else - { - memcpy(color,data,32); - data+=16; + } else { + memcpy(color, data, 32); + data += 16; } len -= 16; @@ -3450,21 +3304,16 @@ void TFT_eSPI::pushColors(uint16_t *data, uint32_t len, bool swap) SPI1CMD |= SPIBUSY; } - if(len) - { + if (len) { uint32_t bits = (len*16-1); // bits left to shift - 1 - if (swap) - { + if (swap) { uint16_t* ptr = (uint16_t*)color; - while(len--) - { + while(len--) { *ptr++ = (*(data) >> 8) | (uint16_t)(*(data) << 8); data++; } - } - else - { - memcpy(color,data,len<<1); + } else { + memcpy(color, data, len << 1); } while(SPI1CMD & SPIBUSY) {} SPI1U1 = (SPI1U1 & mask) | (bits << SPILMOSI) | (bits << SPILMISO); @@ -3496,8 +3345,7 @@ void TFT_eSPI::pushColors(uint16_t *data, uint32_t len, bool swap) #if defined (RPI_ILI9486_DRIVER) || defined (ESP32) || defined (RPI_WRITE_STROBE) || defined (HX8357D_DRIVER) || defined (ILI9488_DRIVER) -void TFT_eSPI::drawLine(int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint32_t color) -{ +void TFT_eSPI::drawLine(int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint32_t color) { spi_begin(); inTransaction = true; boolean steep = abs(y1 - y0) > abs(x1 - x0); @@ -3530,9 +3378,7 @@ void TFT_eSPI::drawLine(int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint32_t } } if (dlen) drawFastVLine(y0, xs, dlen, color); - } - else - { + } else { for (; x0 <= x1; x0++) { dlen++; err -= dy; @@ -3552,9 +3398,7 @@ void TFT_eSPI::drawLine(int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint32_t #else // This is a weeny bit faster -void TFT_eSPI::drawLine(int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint32_t color) -{ - +void TFT_eSPI::drawLine(int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint32_t color) { boolean steep = abs(y1 - y0) > abs(x1 - x0); if (steep) { @@ -3583,8 +3427,7 @@ void TFT_eSPI::drawLine(int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint32_t SPI1U = SPIUMOSI | SPIUSSE; int16_t swapped_color = (color >> 8) | (color << 8); - if (steep) // y increments every iteration (y0 is x-axis, and x0 is y-axis) - { + if (steep) { // y increments every iteration (y0 is x-axis, and x0 is y-axis) if (x1 >= (int32_t)_height) x1 = _height - 1; for (; x0 <= x1; x0++) { @@ -3596,7 +3439,7 @@ void TFT_eSPI::drawLine(int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint32_t } } - if (x0 > x1) {spi_end(); return;} + if (x0 > x1) { spi_end(); return; } setWindow(y0, x0, y0, _height); SPI1U1 = mask; @@ -3616,17 +3459,15 @@ void TFT_eSPI::drawLine(int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint32_t SPI1W0 = swapped_color; } } - } - else // x increments every iteration (x0 is x-axis, and y0 is y-axis) - { + } else { // x increments every iteration (x0 is x-axis, and y0 is y-axis) if (x1 >= _width) x1 = _width - 1; for (; x0 <= x1; x0++) { if ((x0 >= 0) && (y0 >= 0) && (y0 < (int32_t)_height)) break; err -= dy; if (err < 0) { - err += dx; - y0 += ystep; + err += dx; + y0 += ystep; } } @@ -3666,8 +3507,7 @@ void TFT_eSPI::drawLine(int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint32_t ** Description: draw a vertical line ***************************************************************************************/ #if defined (ESP8266) && !defined (RPI_WRITE_STROBE) -void TFT_eSPI::drawFastVLine(int32_t x, int32_t y, int32_t h, uint32_t color) -{ +void TFT_eSPI::drawFastVLine(int32_t x, int32_t y, int32_t h, uint32_t color) { // Clipping if ((x < 0) || (x >= _width) || (y >= _height)) return; @@ -3688,8 +3528,7 @@ void TFT_eSPI::drawFastVLine(int32_t x, int32_t y, int32_t h, uint32_t color) #else -void TFT_eSPI::drawFastVLine(int32_t x, int32_t y, int32_t h, uint32_t color) -{ +void TFT_eSPI::drawFastVLine(int32_t x, int32_t y, int32_t h, uint32_t color) { // Clipping if ((x < 0) || (x >= _width) || (y >= _height)) return; @@ -3726,13 +3565,13 @@ void TFT_eSPI::drawFastVLine(int32_t x, int32_t y, int32_t h, uint32_t color) } #endif + /*************************************************************************************** ** Function name: drawFastHLine ** Description: draw a horizontal line ***************************************************************************************/ #if defined (ESP8266) && !defined (RPI_WRITE_STROBE) -void TFT_eSPI::drawFastHLine(int32_t x, int32_t y, int32_t w, uint32_t color) -{ +void TFT_eSPI::drawFastHLine(int32_t x, int32_t y, int32_t w, uint32_t color) { // Clipping if ((y < 0) || (x >= _width) || (y >= _height)) return; @@ -3753,8 +3592,7 @@ void TFT_eSPI::drawFastHLine(int32_t x, int32_t y, int32_t w, uint32_t color) #else -void TFT_eSPI::drawFastHLine(int32_t x, int32_t y, int32_t w, uint32_t color) -{ +void TFT_eSPI::drawFastHLine(int32_t x, int32_t y, int32_t w, uint32_t color) { // Clipping if ((y < 0) || (x >= _width) || (y >= _height)) return; @@ -3791,13 +3629,13 @@ void TFT_eSPI::drawFastHLine(int32_t x, int32_t y, int32_t w, uint32_t color) } #endif + /*************************************************************************************** ** Function name: fillRect ** Description: draw a filled rectangle ***************************************************************************************/ #if defined (ESP8266) && !defined (RPI_WRITE_STROBE) -void TFT_eSPI::fillRect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t color) -{ +void TFT_eSPI::fillRect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t color) { // Clipping if ((x >= _width) || (y >= _height)) return; @@ -3820,8 +3658,7 @@ void TFT_eSPI::fillRect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t col #else -void TFT_eSPI::fillRect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t color) -{ +void TFT_eSPI::fillRect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t color) { // Clipping if ((x >= _width) || (y >= _height)) return; @@ -3845,14 +3682,11 @@ void TFT_eSPI::fillRect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t col while(n--) {WR_L; WR_H;} #else #ifdef ESP32_PARALLEL - if (color>>8 == (uint8_t)color) - { + if (color >> 8 == (uint8_t)color) { tft_Write_8(color); n--; WR_L; WR_H; while (n) {WR_L; WR_H; n--; WR_L; WR_H;} - } - else - { + } else { while (n--) {tft_Write_16(color);} } #else @@ -3864,12 +3698,12 @@ void TFT_eSPI::fillRect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t col } #endif + /*************************************************************************************** ** Function name: color565 ** Description: convert three 8 bit RGB levels to a 16 bit colour value ***************************************************************************************/ -uint16_t TFT_eSPI::color565(uint8_t r, uint8_t g, uint8_t b) -{ +uint16_t TFT_eSPI::color565(uint8_t r, uint8_t g, uint8_t b) { return ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3); } @@ -3878,8 +3712,7 @@ uint16_t TFT_eSPI::color565(uint8_t r, uint8_t g, uint8_t b) ** Function name: color16to8 ** Description: convert 16 bit colour to an 8 bit 332 RGB colour value ***************************************************************************************/ -uint8_t TFT_eSPI::color16to8(uint16_t c) -{ +uint8_t TFT_eSPI::color16to8(uint16_t c) { return ((c & 0xE000)>>8) | ((c & 0x0700)>>6) | ((c & 0x0018)>>3); } @@ -3888,9 +3721,8 @@ uint8_t TFT_eSPI::color16to8(uint16_t c) ** Function name: color8to16 ** Description: convert 8 bit colour to a 16 bit 565 colour value ***************************************************************************************/ -uint16_t TFT_eSPI::color8to16(uint8_t color) -{ - uint8_t blue[] = {0, 11, 21, 31}; // blue 2 to 5 bit colour lookup table +uint16_t TFT_eSPI::color8to16(uint8_t color) { + uint8_t blue[] = { 0, 11, 21, 31 }; // blue 2 to 5 bit colour lookup table uint16_t color16 = 0; // =====Green===== ===============Red============== @@ -3906,8 +3738,7 @@ uint16_t TFT_eSPI::color8to16(uint8_t color) ** Function name: invertDisplay ** Description: invert the display colours i = 1 invert, i = 0 normal ***************************************************************************************/ -void TFT_eSPI::invertDisplay(boolean i) -{ +void TFT_eSPI::invertDisplay(boolean i) { spi_begin(); // Send the command twice as otherwise it does not always work! writecommand(i ? TFT_INVON : TFT_INVOFF); @@ -3920,13 +3751,11 @@ void TFT_eSPI::invertDisplay(boolean i) ** Function name: write ** Description: draw characters piped through serial stream ***************************************************************************************/ -size_t TFT_eSPI::write(uint8_t utf8) -{ +size_t TFT_eSPI::write(uint8_t utf8) { if (utf8 == '\r') return 1; #ifdef SMOOTH_FONT - if(fontLoaded) - { + if (fontLoaded) { uint16_t unicode = decodeUTF8(utf8); //Serial.print("UniCode="); Serial.println(unicode); @@ -3936,7 +3765,7 @@ size_t TFT_eSPI::write(uint8_t utf8) //fontFile = SPIFFS.open( _gFontFilename, "r" ); - //if(!fontFile) + //if (!fontFile) //{ // fontLoaded = false; // return 1; @@ -3950,7 +3779,7 @@ size_t TFT_eSPI::write(uint8_t utf8) #endif uint8_t uniCode = utf8; // Work with a copy - if (utf8 == '\n') uniCode+=22; // Make it a valid space character to stop errors + if (utf8 == '\n') uniCode += 22; // Make it a valid space character to stop errors else if (utf8 < 32) return 1; uint16_t width = 0; @@ -3964,13 +3793,12 @@ size_t TFT_eSPI::write(uint8_t utf8) //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< #ifdef LOAD_GFXFF - if(!gfxFont) { + if (!gfxFont) { #endif //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< #ifdef LOAD_FONT2 - if (textfont == 2) - { + if (textfont == 2) { if (utf8 > 127) return 1; // This is 20us faster than using the fontdata structure (0.443ms per character instead of 0.465ms) width = pgm_read_byte(widtbl_f16 + uniCode-32); @@ -3986,8 +3814,7 @@ size_t TFT_eSPI::write(uint8_t utf8) #ifdef LOAD_RLE { - if ((textfont>2) && (textfont<9)) - { + if ((textfont > 2) && (textfont < 9)) { if (utf8 > 127) return 1; // Uses the fontinfo struct array to avoid lots of 'if' or 'switch' statements // A tad slower than above but this is not significant and is more convenient for the RLE fonts @@ -3998,13 +3825,12 @@ size_t TFT_eSPI::write(uint8_t utf8) #endif #ifdef LOAD_GLCD - if (textfont==1) - { + if (textfont == 1) { width = 6; height = 8; } #else - if (textfont==1) return 1; + if (textfont == 1) return 1; #endif height = height * textsize; @@ -4012,11 +3838,8 @@ size_t TFT_eSPI::write(uint8_t utf8) if (utf8 == '\n') { cursor_y += height; cursor_x = 0; - } - else - { - if (textwrapX && (cursor_x + width * textsize > _width)) - { + } else { + if (textwrapX && (cursor_x + width * textsize > _width)) { cursor_y += height; cursor_x = 0; } @@ -4026,11 +3849,8 @@ size_t TFT_eSPI::write(uint8_t utf8) //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< #ifdef LOAD_GFXFF - } // Custom GFX font - else - { - - if(utf8 == '\n') { + } else { // Custom GFX font + if (utf8 == '\n') { cursor_x = 0; cursor_y += (int16_t)textsize * (uint8_t)pgm_read_byte(&gfxFont->yAdvance); @@ -4042,9 +3862,9 @@ size_t TFT_eSPI::write(uint8_t utf8) GFXglyph *glyph = &(((GFXglyph *)pgm_read_dword(&gfxFont->glyph))[c2]); uint8_t w = pgm_read_byte(&glyph->width), h = pgm_read_byte(&glyph->height); - if((w > 0) && (h > 0)) { // Is there an associated bitmap? + if ((w > 0) && (h > 0)) { // Is there an associated bitmap? int16_t xo = (int8_t)pgm_read_byte(&glyph->xOffset); - if(textwrapX && ((cursor_x + textsize * (xo + w)) > _width)) { + if (textwrapX && ((cursor_x + textsize * (xo + w)) > _width)) { // Drawing character would go off right edge; wrap to new line cursor_x = 0; cursor_y += (int16_t)textsize * @@ -4067,16 +3887,13 @@ size_t TFT_eSPI::write(uint8_t utf8) ** Function name: drawChar ** Description: draw a Unicode onto the screen ***************************************************************************************/ -int16_t TFT_eSPI::drawChar(uint16_t uniCode, int32_t x, int32_t y) -{ - return drawChar(uniCode, x, y, textfont); +int16_t TFT_eSPI::drawChar(uint16_t uniCode, int32_t x, int32_t y) { + return drawChar(uniCode, x, y, textfont); } -int16_t TFT_eSPI::drawChar(uint16_t uniCode, int32_t x, int32_t y, uint8_t font) -{ +int16_t TFT_eSPI::drawChar(uint16_t uniCode, int32_t x, int32_t y, uint8_t font) { - if (font==1) - { + if (font == 1) { #ifdef LOAD_GLCD #ifndef LOAD_GFXFF drawChar(x, y, uniCode, textcolor, textbgcolor, textsize); @@ -4090,30 +3907,25 @@ int16_t TFT_eSPI::drawChar(uint16_t uniCode, int32_t x, int32_t y, uint8_t font) #ifdef LOAD_GFXFF drawChar(x, y, uniCode, textcolor, textbgcolor, textsize); - if(!gfxFont) { // 'Classic' built-in font + if (!gfxFont) { // 'Classic' built-in font #ifdef LOAD_GLCD return 6 * textsize; #else return 0; #endif - } - else - { - if((uniCode >= pgm_read_byte(&gfxFont->first)) && (uniCode <= pgm_read_byte(&gfxFont->last) )) - { + } else { + if ((uniCode >= pgm_read_byte(&gfxFont->first)) && (uniCode <= pgm_read_byte(&gfxFont->last))) { uint8_t c2 = uniCode - pgm_read_byte(&gfxFont->first); GFXglyph *glyph = &(((GFXglyph *)pgm_read_dword(&gfxFont->glyph))[c2]); return pgm_read_byte(&glyph->xAdvance) * textsize; - } - else - { + } else { return 0; } } #endif } - if ((font>1) && (font<9) && ((uniCode < 32) || (uniCode > 127))) return 0; + if ((font > 1) && (font < 9) && ((uniCode < 32) || (uniCode > 127))) return 0; int32_t width = 0; int32_t height = 0; @@ -4121,8 +3933,7 @@ int16_t TFT_eSPI::drawChar(uint16_t uniCode, int32_t x, int32_t y, uint8_t font) uniCode -= 32; #ifdef LOAD_FONT2 - if (font == 2) - { + if (font == 2) { // This is faster than using the fontdata structure flash_address = pgm_read_dword(&chrtbl_f16[uniCode]); width = pgm_read_byte(widtbl_f16 + uniCode); @@ -4135,8 +3946,7 @@ int16_t TFT_eSPI::drawChar(uint16_t uniCode, int32_t x, int32_t y, uint8_t font) #ifdef LOAD_RLE { - if ((font>2) && (font<9)) - { + if ((font > 2) && (font < 9)) { // This is slower than above but is more convenient for the RLE fonts flash_address = pgm_read_dword( pgm_read_dword( &(fontdata[font].chartbl ) ) + uniCode*sizeof(void *) ); width = pgm_read_byte( (uint8_t *)pgm_read_dword( &(fontdata[font].widthtbl ) ) + uniCode ); @@ -4160,12 +3970,10 @@ int16_t TFT_eSPI::drawChar(uint16_t uniCode, int32_t x, int32_t y, uint8_t font) spi_begin(); inTransaction = true; - for (int32_t i = 0; i < height; i++) - { + for (int32_t i = 0; i < height; i++) { if (textcolor != textbgcolor) fillRect(x, pY, width * textsize, textsize, textbgcolor); - for (int32_t k = 0; k < w; k++) - { + for (int32_t k = 0; k < w; k++) { line = pgm_read_byte((uint8_t *)flash_address + w * i + k); if (line) { if (textsize == 1) { @@ -4178,8 +3986,7 @@ int16_t TFT_eSPI::drawChar(uint16_t uniCode, int32_t x, int32_t y, uint8_t font) if (line & 0x04) drawPixel(pX + 5, pY, textcolor); if (line & 0x02) drawPixel(pX + 6, pY, textcolor); if (line & 0x01) drawPixel(pX + 7, pY, textcolor); - } - else { + } else { pX = x + k * 8 * textsize; if (line & 0x80) fillRect(pX, pY, textsize, textsize, textcolor); if (line & 0x40) fillRect(pX + textsize, pY, textsize, textsize, textcolor); @@ -4197,19 +4004,14 @@ int16_t TFT_eSPI::drawChar(uint16_t uniCode, int32_t x, int32_t y, uint8_t font) inTransaction = false; spi_end(); - } - else - // Faster drawing of characters and background using block write - { + } else { // Faster drawing of characters and background using block write spi_begin(); setWindow(x, y, (x + w * 8) - 1, y + height - 1); uint8_t mask; - for (int32_t i = 0; i < height; i++) - { - for (int32_t k = 0; k < w; k++) - { + for (int32_t i = 0; i < height; i++) { + for (int32_t k = 0; k < w; k++) { line = pgm_read_byte((uint8_t *)flash_address + w * i + k); pX = x + k * 8; mask = 0x80; @@ -4247,8 +4049,7 @@ int16_t TFT_eSPI::drawChar(uint16_t uniCode, int32_t x, int32_t y, uint8_t font) uint8_t ts = textsize - 1; // Temporary copy of textsize // 16 bit pixel count so maximum font size is equivalent to 180x180 pixels in area // w is total number of pixels to plot to fill character block - while (pc < w) - { + while (pc < w) { line = pgm_read_byte((uint8_t *)flash_address); flash_address++; if (line & 0x80) { @@ -4257,40 +4058,38 @@ int16_t TFT_eSPI::drawChar(uint16_t uniCode, int32_t x, int32_t y, uint8_t font) if (ts) { px = x + textsize * (pc % width); // Keep these px and py calculations outside the loop as they are slow py = y + textsize * (pc / width); - } - else { + } else { px = x + pc % width; // Keep these px and py calculations outside the loop as they are slow py = y + pc / width; } while (line--) { // In this case the while(line--) is faster - pc++; // This is faster than putting pc+=line before while()? + pc++; // This is faster than putting pc += line before while()? setWindow(px, py, px + ts, py + ts); if (ts) { tnp = np; while (tnp--) {tft_Write_16(textcolor);} + } else { + tft_Write_16(textcolor); } - else {tft_Write_16(textcolor);} px += textsize; - if (px >= (x + width * textsize)) - { + if (px >= (x + width * textsize)) { px = x; py += textsize; } } - } - else { + } else { line++; pc += line; } } spi_end(); - } - else // Text colour != background && textsize = 1 - // so use faster drawing of characters and background using block write - { + } else { + // Text colour != background && textsize = 1 + // so use faster drawing of characters and background using block write + //spi_begin(); setWindow(x, y, x + width - 1, y + height - 1); @@ -4300,8 +4099,7 @@ int16_t TFT_eSPI::drawChar(uint16_t uniCode, int32_t x, int32_t y, uint8_t font) #endif // Maximum font size is equivalent to 180x180 pixels in area - while (w > 0) - { + while (w > 0) { line = pgm_read_byte((uint8_t *)flash_address++); // 8 bytes smaller when incrementing here if (line & 0x80) { line &= 0x7F; @@ -4313,11 +4111,10 @@ int16_t TFT_eSPI::drawChar(uint16_t uniCode, int32_t x, int32_t y, uint8_t font) #ifdef ESP32_PARALLEL while (line--) {tft_Write_16(textcolor);} #else - writeBlock(textcolor,line); + writeBlock(textcolor, line); #endif #endif - } - else { + } else { line++; w -= line; #ifdef RPI_WRITE_STROBE spi.writePattern(&textbgcolorBin[0], 2, 1); line--; @@ -4326,7 +4123,7 @@ int16_t TFT_eSPI::drawChar(uint16_t uniCode, int32_t x, int32_t y, uint8_t font) #ifdef ESP32_PARALLEL while (line--) {tft_Write_16(textbgcolor);} #else - writeBlock(textbgcolor,line); + writeBlock(textbgcolor, line); #endif #endif } @@ -4346,16 +4143,14 @@ int16_t TFT_eSPI::drawChar(uint16_t uniCode, int32_t x, int32_t y, uint8_t font) ** Description : draw string with padding if it is defined ***************************************************************************************/ // Without font number, uses font set by setTextFont() -int16_t TFT_eSPI::drawString(const String& string, int32_t poX, int32_t poY) -{ +int16_t TFT_eSPI::drawString(const String& string, int32_t poX, int32_t poY) { int16_t len = string.length() + 2; char buffer[len]; string.toCharArray(buffer, len); return drawString(buffer, poX, poY, textfont); } // With font number -int16_t TFT_eSPI::drawString(const String& string, int32_t poX, int32_t poY, uint8_t font) -{ +int16_t TFT_eSPI::drawString(const String& string, int32_t poX, int32_t poY, uint8_t font) { int16_t len = string.length() + 2; char buffer[len]; string.toCharArray(buffer, len); @@ -4363,14 +4158,12 @@ int16_t TFT_eSPI::drawString(const String& string, int32_t poX, int32_t poY, uin } // Without font number, uses font set by setTextFont() -int16_t TFT_eSPI::drawString(const char *string, int32_t poX, int32_t poY) -{ +int16_t TFT_eSPI::drawString(const char *string, int32_t poX, int32_t poY) { return drawString(string, poX, poY, textfont); } // With font number -int16_t TFT_eSPI::drawString(const char *string, int32_t poX, int32_t poY, uint8_t font) -{ +int16_t TFT_eSPI::drawString(const char *string, int32_t poX, int32_t poY, uint8_t font) { int16_t sumX = 0; uint8_t padding = 1, baseline = 0; uint16_t cwidth = textWidth(string, font); // Find the pixel width of the string in the font @@ -4396,10 +4189,9 @@ int16_t TFT_eSPI::drawString(const char *string, int32_t poX, int32_t poY, uint8 } #endif - // If it is not font 1 (GLCD or free font) get the baseline and pixel height of the font #ifdef SMOOTH_FONT - if(fontLoaded) { + if (fontLoaded) { baseline = gFont.maxAscent; cheight = fontHeight(); } @@ -4410,8 +4202,7 @@ int16_t TFT_eSPI::drawString(const char *string, int32_t poX, int32_t poY, uint8 cheight = fontHeight(font); } - if (textdatum || padX) - { + if (textdatum || padX) { switch(textdatum) { case TC_DATUM: @@ -4472,16 +4263,13 @@ int16_t TFT_eSPI::drawString(const char *string, int32_t poX, int32_t poY, uint8 if (poY+cheight-baseline> height()) poY = height() - cheight; } - int8_t xo = 0; #ifdef LOAD_GFXFF - if (freeFont && (textcolor!=textbgcolor)) - { + if (freeFont && (textcolor!=textbgcolor)) { cheight = (glyph_ab + glyph_bb) * textsize; // Get the offset for the first character only to allow for negative offsets uint8_t c2 = *string; - if((c2 >= pgm_read_byte(&gfxFont->first)) && (c2 <= pgm_read_byte(&gfxFont->last) )) - { + if ((c2 >= pgm_read_byte(&gfxFont->first)) && (c2 <= pgm_read_byte(&gfxFont->last) )) { c2 -= pgm_read_byte(&gfxFont->first); GFXglyph *glyph = &(((GFXglyph *)pgm_read_dword(&gfxFont->glyph))[c2]); xo = pgm_read_byte(&glyph->xOffset) * textsize; @@ -4498,19 +4286,17 @@ int16_t TFT_eSPI::drawString(const char *string, int32_t poX, int32_t poY, uint8 #endif #ifdef SMOOTH_FONT - if(fontLoaded) - { + if (fontLoaded) { if (textcolor!=textbgcolor) fillRect(poX, poY, cwidth, cheight, textbgcolor); //drawLine(poX - 5, poY, poX + 5, poY, TFT_GREEN); //drawLine(poX, poY - 5, poX, poY + 5, TFT_GREEN); //fontFile = SPIFFS.open( _gFontFilename, "r"); - if(!fontFile) return 0; + if (!fontFile) return 0; uint16_t len = strlen(string); uint16_t n = 0; setCursor(poX, poY); - while (n < len) - { + while (n < len) { uint16_t unicode = decodeUTF8((uint8_t*)string, &n, len - n); drawGlyph(unicode); } @@ -4528,60 +4314,56 @@ int16_t TFT_eSPI::drawString(const char *string, int32_t poX, int32_t poY, uint8 #ifndef PADDING_DEBUG //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ DEBUG ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - if((padX>cwidth) && (textcolor!=textbgcolor)) - { + if ((padX > cwidth) && (textcolor!=textbgcolor)) { int16_t padXc = poX+cwidth+xo; #ifdef LOAD_GFXFF - if (freeFont) - { + if (freeFont) { poX +=xo; // Adjust for negative offset start character poY -= glyph_ab * textsize; } #endif switch(padding) { case 1: - fillRect(padXc,poY,padX-cwidth,cheight, textbgcolor); + fillRect(padXc, poY, padX-cwidth, cheight, textbgcolor); break; case 2: - fillRect(padXc,poY,(padX-cwidth)>>1,cheight, textbgcolor); + fillRect(padXc, poY,(padX-cwidth)>>1, cheight, textbgcolor); padXc = (padX-cwidth)>>1; - if (padXc>poX) padXc = poX; - fillRect(poX - padXc,poY,(padX-cwidth)>>1,cheight, textbgcolor); + if (padXc > poX) padXc = poX; + fillRect(poX - padXc, poY,(padX-cwidth)>>1, cheight, textbgcolor); break; case 3: - if (padXc>padX) padXc = padX; - fillRect(poX + cwidth - padXc,poY,padXc-cwidth,cheight, textbgcolor); + if (padXc > padX) padXc = padX; + fillRect(poX + cwidth - padXc, poY, padXc-cwidth, cheight, textbgcolor); break; } } - #else //vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv DEBUG vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv // This is debug code to show text (green box) and blanked (white box) areas // It shows that the padding areas are being correctly sized and positioned - if((padX>sumX) && (textcolor!=textbgcolor)) - { + if ((padX > sumX) && (textcolor!=textbgcolor)) { int16_t padXc = poX+sumX; // Maximum left side padding #ifdef LOAD_GFXFF if ((font == 1) && (gfxFont)) poY -= glyph_ab; #endif - drawRect(poX,poY,sumX,cheight, TFT_GREEN); + drawRect(poX, poY, sumX, cheight, TFT_GREEN); switch(padding) { case 1: - drawRect(padXc,poY,padX-sumX,cheight, TFT_WHITE); + drawRect(padXc, poY, padX-sumX, cheight, TFT_WHITE); break; case 2: - drawRect(padXc,poY,(padX-sumX)>>1, cheight, TFT_WHITE); + drawRect(padXc, poY,(padX-sumX)>>1, cheight, TFT_WHITE); padXc = (padX-sumX)>>1; - if (padXc>poX) padXc = poX; - drawRect(poX - padXc,poY,(padX-sumX)>>1,cheight, TFT_WHITE); + if (padXc > poX) padXc = poX; + drawRect(poX - padXc, poY,(padX-sumX)>>1, cheight, TFT_WHITE); break; case 3: - if (padXc>padX) padXc = padX; - drawRect(poX + sumX - padXc,poY,padXc-sumX,cheight, TFT_WHITE); + if (padXc > padX) padXc = padX; + drawRect(poX + sumX - padXc, poY, padXc-sumX, cheight, TFT_WHITE); break; } } @@ -4596,16 +4378,14 @@ return sumX; ** Function name: drawCentreString (deprecated, use setTextDatum()) ** Descriptions: draw string centred on dX ***************************************************************************************/ -int16_t TFT_eSPI::drawCentreString(const String& string, int32_t dX, int32_t poY, uint8_t font) -{ +int16_t TFT_eSPI::drawCentreString(const String& string, int32_t dX, int32_t poY, uint8_t font) { int16_t len = string.length() + 2; char buffer[len]; string.toCharArray(buffer, len); return drawCentreString(buffer, dX, poY, font); } -int16_t TFT_eSPI::drawCentreString(const char *string, int32_t dX, int32_t poY, uint8_t font) -{ +int16_t TFT_eSPI::drawCentreString(const char *string, int32_t dX, int32_t poY, uint8_t font) { uint8_t tempdatum = textdatum; int32_t sumX = 0; textdatum = TC_DATUM; @@ -4619,16 +4399,14 @@ int16_t TFT_eSPI::drawCentreString(const char *string, int32_t dX, int32_t poY, ** Function name: drawRightString (deprecated, use setTextDatum()) ** Descriptions: draw string right justified to dX ***************************************************************************************/ -int16_t TFT_eSPI::drawRightString(const String& string, int32_t dX, int32_t poY, uint8_t font) -{ +int16_t TFT_eSPI::drawRightString(const String& string, int32_t dX, int32_t poY, uint8_t font) { int16_t len = string.length() + 2; char buffer[len]; string.toCharArray(buffer, len); return drawRightString(buffer, dX, poY, font); } -int16_t TFT_eSPI::drawRightString(const char *string, int32_t dX, int32_t poY, uint8_t font) -{ +int16_t TFT_eSPI::drawRightString(const char *string, int32_t dX, int32_t poY, uint8_t font) { uint8_t tempdatum = textdatum; int16_t sumX = 0; textdatum = TR_DATUM; @@ -4642,16 +4420,14 @@ int16_t TFT_eSPI::drawRightString(const char *string, int32_t dX, int32_t poY, u ** Function name: drawNumber ** Description: draw a long integer ***************************************************************************************/ -int16_t TFT_eSPI::drawNumber(long long_num, int32_t poX, int32_t poY) -{ +int16_t TFT_eSPI::drawNumber(long long_num, int32_t poX, int32_t poY) { isDigits = true; // Eliminate jiggle in monospaced fonts char str[12]; ltoa(long_num, str, 10); return drawString(str, poX, poY, textfont); } -int16_t TFT_eSPI::drawNumber(long long_num, int32_t poX, int32_t poY, uint8_t font) -{ +int16_t TFT_eSPI::drawNumber(long long_num, int32_t poX, int32_t poY, uint8_t font) { isDigits = true; // Eliminate jiggle in monospaced fonts char str[12]; ltoa(long_num, str, 10); @@ -4665,13 +4441,11 @@ int16_t TFT_eSPI::drawNumber(long long_num, int32_t poX, int32_t poY, uint8_t fo ***************************************************************************************/ // Assemble and print a string, this permits alignment relative to a datum // looks complicated but much more compact and actually faster than using print class -int16_t TFT_eSPI::drawFloat(float floatNumber, uint8_t dp, int32_t poX, int32_t poY) -{ +int16_t TFT_eSPI::drawFloat(float floatNumber, uint8_t dp, int32_t poX, int32_t poY) { return drawFloat(floatNumber, dp, poX, poY, textfont); } -int16_t TFT_eSPI::drawFloat(float floatNumber, uint8_t dp, int32_t poX, int32_t poY, uint8_t font) -{ +int16_t TFT_eSPI::drawFloat(float floatNumber, uint8_t dp, int32_t poX, int32_t poY, uint8_t font) { isDigits = true; char str[14]; // Array to contain decimal string uint8_t ptr = 0; // Initialise pointer for array @@ -4720,8 +4494,7 @@ int16_t TFT_eSPI::drawFloat(float floatNumber, uint8_t dp, int32_t poX, int32_t // Get decimal digits one by one and put in array // Limit digit count so we don't get a false sense of resolution uint8_t i = 0; - while ((i < dp) && (digits < 9)) // while (i < dp) for no limit but array size must be increased - { + while ((i < dp) && (digits < 9)) { // while (i < dp) for no limit but array size must be increased i++; floatNumber *= 10; // for the next decimal temp = floatNumber; // get the decimal @@ -4742,8 +4515,7 @@ int16_t TFT_eSPI::drawFloat(float floatNumber, uint8_t dp, int32_t poX, int32_t #ifdef LOAD_GFXFF -void TFT_eSPI::setFreeFont(const GFXfont *f) -{ +void TFT_eSPI::setFreeFont(const GFXfont *f) { textfont = 1; gfxFont = (GFXfont *)f; @@ -4752,8 +4524,7 @@ void TFT_eSPI::setFreeFont(const GFXfont *f) uint8_t numChars = pgm_read_byte(&gfxFont->last) - pgm_read_byte(&gfxFont->first); // Find the biggest above and below baseline offsets - for (uint8_t c = 0; c < numChars; c++) - { + for (uint8_t c = 0; c < numChars; c++) { GFXglyph *glyph1 = &(((GFXglyph *)pgm_read_dword(&gfxFont->glyph))[c]); int8_t ab = -pgm_read_byte(&glyph1->yOffset); if (ab > glyph_ab) glyph_ab = ab; @@ -4767,8 +4538,7 @@ void TFT_eSPI::setFreeFont(const GFXfont *f) ** Function name: setTextFont ** Description: Set the font for the print stream ***************************************************************************************/ -void TFT_eSPI::setTextFont(uint8_t f) -{ +void TFT_eSPI::setTextFont(uint8_t f) { textfont = (f > 0) ? f : 1; // Don't allow font 0 gfxFont = NULL; } @@ -4782,8 +4552,7 @@ void TFT_eSPI::setTextFont(uint8_t f) ***************************************************************************************/ // Alternative to setTextFont() so we don't need two different named functions -void TFT_eSPI::setFreeFont(uint8_t font) -{ +void TFT_eSPI::setFreeFont(uint8_t font) { setTextFont(font); } @@ -4792,8 +4561,7 @@ void TFT_eSPI::setFreeFont(uint8_t font) ** Function name: setTextFont ** Description: Set the font for the print stream ***************************************************************************************/ -void TFT_eSPI::setTextFont(uint8_t f) -{ +void TFT_eSPI::setTextFont(uint8_t f) { textfont = (f > 0) ? f : 1; // Don't allow font 0 } @@ -4811,8 +4579,7 @@ void TFT_eSPI::setTextFont(uint8_t f) // Adafruit_GFX 19.62% 14.31% 7.94% // #if defined (ESP8266) && !defined (ILI9488_DRIVER) -void writeBlock(uint16_t color, uint32_t repeat) -{ +void writeBlock(uint16_t color, uint32_t repeat) { uint16_t color16 = (color >> 8) | (color << 8); uint32_t color32 = color16 | color16 << 16; uint32_t mask = ~(SPIMMOSI << SPILMOSI); @@ -4823,34 +4590,29 @@ void writeBlock(uint16_t color, uint32_t repeat) SPI1W1 = color32; SPI1W2 = color32; SPI1W3 = color32; - if (repeat > 8) - { + if (repeat > 8) { SPI1W4 = color32; SPI1W5 = color32; SPI1W6 = color32; SPI1W7 = color32; } - if (repeat > 16) - { + if (repeat > 16) { SPI1W8 = color32; SPI1W9 = color32; SPI1W10 = color32; SPI1W11 = color32; } - if (repeat > 24) - { + if (repeat > 24) { SPI1W12 = color32; SPI1W13 = color32; SPI1W14 = color32; SPI1W15 = color32; } - if (repeat > 31) - { + if (repeat > 31) { SPI1U1 = mask | (511 << SPILMOSI); - while(repeat>31) - { + while(repeat > 31) { #if defined SPI_FREQUENCY && (SPI_FREQUENCY == 80000000) - if(SPI1CMD & SPIBUSY) // added to sync with flag change + if (SPI1CMD & SPIBUSY) // added to sync with flag change #endif while(SPI1CMD & SPIBUSY) {} SPI1CMD |= SPIBUSY; @@ -4859,8 +4621,7 @@ void writeBlock(uint16_t color, uint32_t repeat) while(SPI1CMD & SPIBUSY) {} } - if (repeat) - { + if (repeat) { repeat = (repeat << 4) - 1; SPI1U1 = mask | (repeat << SPILMOSI); SPI1CMD |= SPIBUSY; @@ -4873,8 +4634,7 @@ void writeBlock(uint16_t color, uint32_t repeat) #elif defined (ILI9488_DRIVER) #ifdef ESP8266 -void writeBlock(uint16_t color, uint32_t repeat) -{ +void writeBlock(uint16_t color, uint32_t repeat) { uint32_t mask = ~(SPIMMOSI << SPILMOSI); mask = SPI1U1 & mask; @@ -4885,28 +4645,25 @@ void writeBlock(uint16_t color, uint32_t repeat) uint8_t g = (color & 0x07E0)>>3; uint8_t b = (color & 0x001F)<<3; // Concatenate 4 pixels into three 32 bit blocks - uint32_t r0 = r<<24 | b<<16 | g<<8 | r; - uint32_t r1 = g<<24 | r<<16 | b<<8 | g; - uint32_t r2 = b<<24 | g<<16 | r<<8 | b; + uint32_t r0 = r << 24 | b << 16 | g << 8 | r; + uint32_t r1 = g << 24 | r << 16 | b << 8 | g; + uint32_t r2 = b << 24 | g << 16 | r << 8 | b; SPI1W0 = r0; SPI1W1 = r1; SPI1W2 = r2; - if (repeat > 4) - { + if (repeat > 4) { SPI1W3 = r0; SPI1W4 = r1; SPI1W5 = r2; } - if (repeat > 8) - { + if (repeat > 8) { SPI1W6 = r0; SPI1W7 = r1; SPI1W8 = r2; } - if (repeat > 12) - { + if (repeat > 12) { SPI1W9 = r0; SPI1W10 = r1; SPI1W11 = r2; @@ -4916,11 +4673,9 @@ void writeBlock(uint16_t color, uint32_t repeat) SPI1W15 = r0; } - if (repeat > 20) - { + if (repeat > 20) { SPI1U1 = mask | (503 << SPILMOSI); - while(repeat>20) - { + while(repeat > 20) { while(SPI1CMD & SPIBUSY) {} SPI1CMD |= SPIBUSY; repeat -= 21; @@ -4928,8 +4683,7 @@ void writeBlock(uint16_t color, uint32_t repeat) while(SPI1CMD & SPIBUSY) {} } - if (repeat) - { + if (repeat) { repeat = (repeat * 24) - 1; SPI1U1 = mask | (repeat << SPILMOSI); SPI1CMD |= SPIBUSY; @@ -4940,23 +4694,20 @@ void writeBlock(uint16_t color, uint32_t repeat) } #else // Now the code for ESP32 and ILI9488 -void writeBlock(uint16_t color, uint32_t repeat) -{ +void writeBlock(uint16_t color, uint32_t repeat) { // Split out the colours uint32_t r = (color & 0xF800)>>8; uint32_t g = (color & 0x07E0)<<5; uint32_t b = (color & 0x001F)<<19; // Concatenate 4 pixels into three 32 bit blocks - uint32_t r0 = r<<24 | b | g | r; - uint32_t r1 = r0>>8 | g<<16; - uint32_t r2 = r1>>8 | b<<8; + uint32_t r0 = r << 24 | b | g | r; + uint32_t r1 = r0 >> 8 | g << 16; + uint32_t r2 = r1 >> 8 | b << 8; - if (repeat > 19) - { + if (repeat > 19) { SET_PERI_REG_BITS(SPI_MOSI_DLEN_REG(SPI_PORT), SPI_USR_MOSI_DBITLEN, 479, SPI_USR_MOSI_DBITLEN_S); - while(repeat>19) - { + while(repeat > 19) { while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR); WRITE_PERI_REG(SPI_W0_REG(SPI_PORT), r0); WRITE_PERI_REG(SPI_W1_REG(SPI_PORT), r1); @@ -4979,8 +4730,7 @@ void writeBlock(uint16_t color, uint32_t repeat) while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR); } - if (repeat) - { + if (repeat) { SET_PERI_REG_BITS(SPI_MOSI_DLEN_REG(SPI_PORT), SPI_USR_MOSI_DBITLEN, (repeat * 24) - 1, SPI_USR_MOSI_DBITLEN_S); WRITE_PERI_REG(SPI_W0_REG(SPI_PORT), r0); WRITE_PERI_REG(SPI_W1_REG(SPI_PORT), r1); @@ -4988,8 +4738,7 @@ void writeBlock(uint16_t color, uint32_t repeat) WRITE_PERI_REG(SPI_W3_REG(SPI_PORT), r0); WRITE_PERI_REG(SPI_W4_REG(SPI_PORT), r1); WRITE_PERI_REG(SPI_W5_REG(SPI_PORT), r2); - if (repeat > 8 ) - { + if (repeat > 8 ) { WRITE_PERI_REG(SPI_W6_REG(SPI_PORT), r0); WRITE_PERI_REG(SPI_W7_REG(SPI_PORT), r1); WRITE_PERI_REG(SPI_W8_REG(SPI_PORT), r2); @@ -5010,15 +4759,12 @@ void writeBlock(uint16_t color, uint32_t repeat) #else // Low level register based ESP32 code for 16 bit colour SPI TFTs -void writeBlock(uint16_t color, uint32_t repeat) -{ +void writeBlock(uint16_t color, uint32_t repeat) { uint32_t color32 = COL_32(color, color); - if (repeat > 31) // Revert legacy toggle buffer change - { + if (repeat > 31) { // Revert legacy toggle buffer change WRITE_PERI_REG(SPI_MOSI_DLEN_REG(SPI_PORT), 511); - while(repeat>31) - { + while(repeat > 31) { while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR); WRITE_PERI_REG(SPI_W0_REG(SPI_PORT), color32); WRITE_PERI_REG(SPI_W1_REG(SPI_PORT), color32); @@ -5042,11 +4788,10 @@ void writeBlock(uint16_t color, uint32_t repeat) while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR); } - if (repeat) - { + if (repeat) { // Revert toggle buffer change WRITE_PERI_REG(SPI_MOSI_DLEN_REG(SPI_PORT), (repeat << 4) - 1); - for (uint32_t i=0; i <= (repeat>>1); i++) WRITE_PERI_REG((SPI_W0_REG(SPI_PORT) + (i << 2)), color32); + for (uint32_t i=0; i <= (repeat >> 1); i++) WRITE_PERI_REG((SPI_W0_REG(SPI_PORT) + (i << 2)), color32); SET_PERI_REG_MASK(SPI_CMD_REG(SPI_PORT), SPI_USR); while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR); } @@ -5058,8 +4803,7 @@ void writeBlock(uint16_t color, uint32_t repeat) ** Function name: getSetup ** Description: Get the setup details for diagnostic and sketch access ***************************************************************************************/ -void TFT_eSPI::getSetup(setup_t &tft_settings) -{ +void TFT_eSPI::getSetup(setup_t &tft_settings) { // tft_settings.version is set in header file #if defined (ESP8266) diff --git a/src/utility/In_eSPI.h b/src/utility/In_eSPI.h index 41ea091..4375317 100644 --- a/src/utility/In_eSPI.h +++ b/src/utility/In_eSPI.h @@ -165,8 +165,8 @@ #endif #endif #else - #define DC_C GPOC=dcpinmask - #define DC_D GPOS=dcpinmask + #define DC_C GPOC = dcpinmask + #define DC_D GPOS = dcpinmask #endif #endif @@ -212,8 +212,8 @@ #endif #endif #else - #define CS_L GPOC=cspinmask - #define CS_H GPOS=cspinmask + #define CS_L GPOC = cspinmask + #define CS_H GPOS = cspinmask #endif #endif @@ -252,8 +252,8 @@ #define WR_L GPIO.out_w1tc = (1 << TFT_WR) #define WR_H GPIO.out_w1ts = (1 << TFT_WR) #else - #define WR_L GPOC=wrpinmask - #define WR_H GPOS=wrpinmask + #define WR_L GPOC = wrpinmask + #define WR_H GPOS = wrpinmask #endif #endif @@ -385,8 +385,8 @@ // Read from display using SPI or software SPI #if defined (ESP8266) && defined (TFT_SDA_READ) // Use a bit banged function call for ESP8266 and bi-directional SDA pin - #define SCLK_L GPOC=sclkpinmask - #define SCLK_H GPOS=sclkpinmask + #define SCLK_L GPOC = sclkpinmask + #define SCLK_H GPOS = sclkpinmask #else // Use a SPI read transfer #define tft_Read_8() spi.transfer(0) @@ -531,59 +531,58 @@ swap_coord(T& a, T& b) { T t = a; a = b; b = t; } // This structure allows sketches to retrieve the user setup parameters at runtime // by calling getSetup(), zero impact on code size unless used, mainly for diagnostics -typedef struct -{ -String version = TFT_ESPI_VERSION; -int16_t esp; -uint8_t trans; -uint8_t serial; -uint8_t overlap; +typedef struct { + String version = TFT_ESPI_VERSION; + int16_t esp; + uint8_t trans; + uint8_t serial; + uint8_t overlap; -#if defined (ESP32) - #if defined (USE_HSPI_PORT) - uint8_t port = HSPI; - #else - uint8_t port = VSPI; + #if defined (ESP32) + #if defined (USE_HSPI_PORT) + uint8_t port = HSPI; + #else + uint8_t port = VSPI; + #endif #endif -#endif -uint16_t tft_driver; // Hexadecimal code -uint16_t tft_width; // Rotation 0 width and height -uint16_t tft_height; + uint16_t tft_driver; // Hexadecimal code + uint16_t tft_width; // Rotation 0 width and height + uint16_t tft_height; -uint8_t r0_x_offset; // Offsets, not all used yet -uint8_t r0_y_offset; -uint8_t r1_x_offset; -uint8_t r1_y_offset; -uint8_t r2_x_offset; -uint8_t r2_y_offset; -uint8_t r3_x_offset; -uint8_t r3_y_offset; + uint8_t r0_x_offset; // Offsets, not all used yet + uint8_t r0_y_offset; + uint8_t r1_x_offset; + uint8_t r1_y_offset; + uint8_t r2_x_offset; + uint8_t r2_y_offset; + uint8_t r3_x_offset; + uint8_t r3_y_offset; -int8_t pin_tft_mosi; -int8_t pin_tft_miso; -int8_t pin_tft_clk; -int8_t pin_tft_cs; + int8_t pin_tft_mosi; + int8_t pin_tft_miso; + int8_t pin_tft_clk; + int8_t pin_tft_cs; -int8_t pin_tft_dc; -int8_t pin_tft_rd; -int8_t pin_tft_wr; -int8_t pin_tft_rst; + int8_t pin_tft_dc; + int8_t pin_tft_rd; + int8_t pin_tft_wr; + int8_t pin_tft_rst; -int8_t pin_tft_d0; -int8_t pin_tft_d1; -int8_t pin_tft_d2; -int8_t pin_tft_d3; -int8_t pin_tft_d4; -int8_t pin_tft_d5; -int8_t pin_tft_d6; -int8_t pin_tft_d7; + int8_t pin_tft_d0; + int8_t pin_tft_d1; + int8_t pin_tft_d2; + int8_t pin_tft_d3; + int8_t pin_tft_d4; + int8_t pin_tft_d5; + int8_t pin_tft_d6; + int8_t pin_tft_d7; -int8_t pin_tch_cs; + int8_t pin_tch_cs; -int16_t tft_spi_freq; -int16_t tft_rd_freq; -int16_t tch_spi_freq; + int16_t tft_spi_freq; + int16_t tft_rd_freq; + int16_t tch_spi_freq; } setup_t; // This is a structure to conveniently hold information on the default fonts @@ -595,11 +594,11 @@ PROGMEM const uint8_t chr_null[1] = {0}; PROGMEM const uint8_t* const chrtbl_null[1] = {chr_null}; typedef struct { - const uint8_t *chartbl; - const uint8_t *widthtbl; - uint8_t height; - uint8_t baseline; - } fontinfo; + const uint8_t *chartbl; + const uint8_t *widthtbl; + uint8_t height; + uint8_t baseline; +} fontinfo; // Now fill the structure const PROGMEM fontinfo fontdata [] = { @@ -652,7 +651,7 @@ const PROGMEM fontinfo fontdata [] = { // Class functions and variables class TFT_eSPI : public Print { - public: +public: TFT_eSPI(int16_t _W = TFT_WIDTH, int16_t _H = TFT_HEIGHT); @@ -830,7 +829,7 @@ class TFT_eSPI : public Print { int16_t _xpivot; // x pivot point coordinate int16_t _ypivot; // x pivot point coordinate - private: +private: inline void spi_begin() __attribute__((always_inline)); inline void spi_end() __attribute__((always_inline)); @@ -854,7 +853,7 @@ class TFT_eSPI : public Print { uint32_t lastColor = 0xFFFF; - protected: +protected: int32_t win_xe, win_ye; diff --git a/src/utility/M5Timer.cpp b/src/utility/M5Timer.cpp index 05cf77b..f5e0b58 100644 --- a/src/utility/M5Timer.cpp +++ b/src/utility/M5Timer.cpp @@ -23,219 +23,196 @@ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ - #include "M5Timer.h" - // Select time function: //static inline unsigned long elapsed() { return micros(); } static inline unsigned long elapsed() { return millis(); } - M5Timer::M5Timer() { - unsigned long current_millis = elapsed(); + unsigned long current_millis = elapsed(); - for (int i = 0; i < MAX_TIMERS; i++) { - enabled[i] = false; - callbacks[i] = 0; // if the callback pointer is zero, the slot is free, i.e. doesn't "contain" any timer - prev_millis[i] = current_millis; - numRuns[i] = 0; - } - - numTimers = 0; + for (int i = 0; i < MAX_TIMERS; i++) { + enabled[i] = false; + callbacks[i] = 0; // if the callback pointer is zero, the slot is free, i.e. doesn't "contain" any timer + prev_millis[i] = current_millis; + numRuns[i] = 0; + } + numTimers = 0; } - void M5Timer::run() { - int i; - unsigned long current_millis; + int i; + unsigned long current_millis; - // get current time - current_millis = elapsed(); + // get current time + current_millis = elapsed(); - for (i = 0; i < MAX_TIMERS; i++) { + for (i = 0; i < MAX_TIMERS; i++) { + toBeCalled[i] = DEFCALL_DONTRUN; - toBeCalled[i] = DEFCALL_DONTRUN; + // no callback == no timer, i.e. jump over empty slots + if (callbacks[i] != 0) { - // no callback == no timer, i.e. jump over empty slots - if (callbacks[i]) { + // is it time to process this timer ? + // see http://arduino.cc/forum/index.php/topic,124048.msg932592.html#msg932592 - // is it time to process this timer ? - // see http://arduino.cc/forum/index.php/topic,124048.msg932592.html#msg932592 + if (current_millis - prev_millis[i] >= delays[i]) { + // update time + //prev_millis[i] = current_millis; + prev_millis[i] += delays[i]; - if (current_millis - prev_millis[i] >= delays[i]) { - - // update time - //prev_millis[i] = current_millis; - prev_millis[i] += delays[i]; - - // check if the timer callback has to be executed - if (enabled[i]) { - - // "run forever" timers must always be executed - if (maxNumRuns[i] == RUN_FOREVER) { - toBeCalled[i] = DEFCALL_RUNONLY; - } - // other timers get executed the specified number of times - else if (numRuns[i] < maxNumRuns[i]) { - toBeCalled[i] = DEFCALL_RUNONLY; - numRuns[i]++; - - // after the last run, delete the timer - if (numRuns[i] >= maxNumRuns[i]) { - toBeCalled[i] = DEFCALL_RUNANDDEL; - } - } - } + // check if the timer callback has to be executed + if (enabled[i] == true) { + // "run forever" timers must always be executed + if (maxNumRuns[i] == RUN_FOREVER) { + toBeCalled[i] = DEFCALL_RUNONLY; + }else if (numRuns[i] < maxNumRuns[i]) { + // other timers get executed the specified number of times + toBeCalled[i] = DEFCALL_RUNONLY; + numRuns[i]++; + // after the last run, delete the timer + if (numRuns[i] >= maxNumRuns[i]) { + toBeCalled[i] = DEFCALL_RUNANDDEL; } + } } + } } + } + for (i = 0; i < MAX_TIMERS; i++) { + switch (toBeCalled[i]) { + case DEFCALL_DONTRUN: + break; - for (i = 0; i < MAX_TIMERS; i++) { - switch(toBeCalled[i]) { - case DEFCALL_DONTRUN: - break; + case DEFCALL_RUNONLY: + callbacks[i](); + break; - case DEFCALL_RUNONLY: - callbacks[i](); - break; - - case DEFCALL_RUNANDDEL: - callbacks[i](); - deleteTimer(i); - break; - } + case DEFCALL_RUNANDDEL: + callbacks[i](); + deleteTimer(i); + break; } + } } - // find the first available slot // return -1 if none found int M5Timer::findFirstFreeSlot() { - int i; + int i; - // all slots are used - if (numTimers >= MAX_TIMERS) { - return -1; - } - - // return the first slot with no callback (i.e. free) - for (i = 0; i < MAX_TIMERS; i++) { - if (callbacks[i] == 0) { - return i; - } - } - - // no free slots found + // all slots are used + if (numTimers >= MAX_TIMERS) { return -1; -} + } + // return the first slot with no callback (i.e. free) + for (i = 0; i < MAX_TIMERS; i++) { + if (callbacks[i] == 0) { + return i; + } + } + // no free slots found + return -1; +} int M5Timer::setTimer(long d, timer_callback f, int n) { - int freeTimer; + int freeTimer; - freeTimer = findFirstFreeSlot(); - if (freeTimer < 0) { - return -1; - } + freeTimer = findFirstFreeSlot(); + if (freeTimer < 0) { + return -1; + } - if (f == NULL) { - return -1; - } + if (f == NULL) { + return -1; + } - delays[freeTimer] = d; - callbacks[freeTimer] = f; - maxNumRuns[freeTimer] = n; - enabled[freeTimer] = true; - prev_millis[freeTimer] = elapsed(); + delays[freeTimer] = d; + callbacks[freeTimer] = f; + maxNumRuns[freeTimer] = n; + enabled[freeTimer] = true; + prev_millis[freeTimer] = elapsed(); - numTimers++; + numTimers++; - return freeTimer; + return freeTimer; } - int M5Timer::setInterval(long d, timer_callback f) { - return setTimer(d, f, RUN_FOREVER); + return setTimer(d, f, RUN_FOREVER); } - int M5Timer::setTimeout(long d, timer_callback f) { - return setTimer(d, f, RUN_ONCE); + return setTimer(d, f, RUN_ONCE); } - void M5Timer::deleteTimer(int timerId) { - if (timerId >= MAX_TIMERS) { - return; - } + if (timerId >= MAX_TIMERS) { + return; + } - // nothing to delete if no timers are in use - if (numTimers == 0) { - return; - } + // nothing to delete if no timers are in use + if (numTimers == 0) { + return; + } - // don't decrease the number of timers if the - // specified slot is already empty - if (callbacks[timerId] != NULL) { - callbacks[timerId] = 0; - enabled[timerId] = false; - toBeCalled[timerId] = DEFCALL_DONTRUN; - delays[timerId] = 0; - numRuns[timerId] = 0; + // don't decrease the number of timers if the + // specified slot is already empty + if (callbacks[timerId] != NULL) { + callbacks[timerId] = 0; + enabled[timerId] = false; + toBeCalled[timerId] = DEFCALL_DONTRUN; + delays[timerId] = 0; + numRuns[timerId] = 0; - // update number of timers - numTimers--; - } + // update number of timers + numTimers--; + } } - // function contributed by code@rowansimms.com void M5Timer::restartTimer(int numTimer) { - if (numTimer >= MAX_TIMERS) { - return; - } + if (numTimer >= MAX_TIMERS) { + return; + } - prev_millis[numTimer] = elapsed(); + prev_millis[numTimer] = elapsed(); } - boolean M5Timer::isEnabled(int numTimer) { - if (numTimer >= MAX_TIMERS) { - return false; - } + if (numTimer >= MAX_TIMERS) { + return false; + } - return enabled[numTimer]; + return enabled[numTimer]; } - void M5Timer::enable(int numTimer) { - if (numTimer >= MAX_TIMERS) { - return; - } + if (numTimer >= MAX_TIMERS) { + return; + } - enabled[numTimer] = true; + enabled[numTimer] = true; } - void M5Timer::disable(int numTimer) { - if (numTimer >= MAX_TIMERS) { - return; - } + if (numTimer >= MAX_TIMERS) { + return; + } - enabled[numTimer] = false; + enabled[numTimer] = false; } - void M5Timer::toggle(int numTimer) { - if (numTimer >= MAX_TIMERS) { - return; - } + if (numTimer >= MAX_TIMERS) { + return; + } - enabled[numTimer] = !enabled[numTimer]; + enabled[numTimer] = !enabled[numTimer]; } - int M5Timer::getNumTimers() { - return numTimers; + return numTimers; } diff --git a/src/utility/M5Timer.h b/src/utility/M5Timer.h index 63dcba6..4df696e 100644 --- a/src/utility/M5Timer.h +++ b/src/utility/M5Timer.h @@ -26,96 +26,95 @@ #ifndef M5Timer_H -#define M5Timer_H + #define M5Timer_H -#include -#include + #include + #include -typedef std::function timer_callback; + typedef std::function timer_callback; -class M5Timer { + class M5Timer { + public: + // maximum number of timers + const static int MAX_TIMERS = 10; -public: - // maximum number of timers - const static int MAX_TIMERS = 10; + // setTimer() constants + const static int RUN_FOREVER = 0; + const static int RUN_ONCE = 1; - // setTimer() constants - const static int RUN_FOREVER = 0; - const static int RUN_ONCE = 1; + // constructor + M5Timer(); - // constructor - M5Timer(); + // this function must be called inside loop() + void run(); - // this function must be called inside loop() - void run(); + // call function f every d milliseconds + int setInterval(long d, timer_callback f); - // call function f every d milliseconds - int setInterval(long d, timer_callback f); + // call function f once after d milliseconds + int setTimeout(long d, timer_callback f); - // call function f once after d milliseconds - int setTimeout(long d, timer_callback f); + // call function f every d milliseconds for n times + int setTimer(long d, timer_callback f, int n); - // call function f every d milliseconds for n times - int setTimer(long d, timer_callback f, int n); + // destroy the specified timer + void deleteTimer(int numTimer); - // destroy the specified timer - void deleteTimer(int numTimer); + // restart the specified timer + void restartTimer(int numTimer); - // restart the specified timer - void restartTimer(int numTimer); + // returns true if the specified timer is enabled + boolean isEnabled(int numTimer); - // returns true if the specified timer is enabled - boolean isEnabled(int numTimer); + // enables the specified timer + void enable(int numTimer); - // enables the specified timer - void enable(int numTimer); + // disables the specified timer + void disable(int numTimer); - // disables the specified timer - void disable(int numTimer); + // enables the specified timer if it's currently disabled, + // and vice-versa + void toggle(int numTimer); - // enables the specified timer if it's currently disabled, - // and vice-versa - void toggle(int numTimer); + // returns the number of used timers + int getNumTimers(); - // returns the number of used timers - int getNumTimers(); + // returns the number of available timers + int getNumAvailableTimers() { return MAX_TIMERS - numTimers; }; - // returns the number of available timers - int getNumAvailableTimers() { return MAX_TIMERS - numTimers; }; + private: + // deferred call constants + const static int DEFCALL_DONTRUN = 0; // don't call the callback function + const static int DEFCALL_RUNONLY = 1; // call the callback function but don't delete the timer + const static int DEFCALL_RUNANDDEL = 2; // call the callback function and delete the timer -private: - // deferred call constants - const static int DEFCALL_DONTRUN = 0; // don't call the callback function - const static int DEFCALL_RUNONLY = 1; // call the callback function but don't delete the timer - const static int DEFCALL_RUNANDDEL = 2; // call the callback function and delete the timer + // find the first available slot + int findFirstFreeSlot(); - // find the first available slot - int findFirstFreeSlot(); + // value returned by the millis() function + // in the previous run() call + unsigned long prev_millis[MAX_TIMERS]; - // value returned by the millis() function - // in the previous run() call - unsigned long prev_millis[MAX_TIMERS]; + // pointers to the callback functions + timer_callback callbacks[MAX_TIMERS]; - // pointers to the callback functions - timer_callback callbacks[MAX_TIMERS]; + // delay values + long delays[MAX_TIMERS]; - // delay values - long delays[MAX_TIMERS]; + // number of runs to be executed for each timer + int maxNumRuns[MAX_TIMERS]; - // number of runs to be executed for each timer - int maxNumRuns[MAX_TIMERS]; + // number of executed runs for each timer + int numRuns[MAX_TIMERS]; - // number of executed runs for each timer - int numRuns[MAX_TIMERS]; + // which timers are enabled + boolean enabled[MAX_TIMERS]; - // which timers are enabled - boolean enabled[MAX_TIMERS]; + // deferred function call (sort of) - N.B.: this array is only used in run() + int toBeCalled[MAX_TIMERS]; - // deferred function call (sort of) - N.B.: this array is only used in run() - int toBeCalled[MAX_TIMERS]; - - // actual number of timers in use - int numTimers; -}; + // actual number of timers in use + int numTimers; + }; #endif diff --git a/src/utility/MPU9250.cpp b/src/utility/MPU9250.cpp index 1b97665..157da08 100644 --- a/src/utility/MPU9250.cpp +++ b/src/utility/MPU9250.cpp @@ -1,4 +1,4 @@ -#include "..\M5Stack.h" +#include "../M5Stack.h" #include "MPU9250.h" //============================================================================== @@ -7,116 +7,104 @@ //============================================================================== void MPU9250::getMres() { - switch (Mscale) - { - // Possible magnetometer scales (and their register bit settings) are: - // 14 bit resolution (0) and 16 bit resolution (1) + switch (Mscale) { + // Possible magnetometer scales (and their register bit settings) are: + // 14 bit resolution (0) and 16 bit resolution (1) case MFS_14BITS: - mRes = 10.*4912./8190.; // Proper scale to return milliGauss - break; + mRes = 10. * 4912. / 8190.; // Proper scale to return milliGauss + break; case MFS_16BITS: - mRes = 10.*4912./32760.0; // Proper scale to return milliGauss - break; + mRes = 10. * 4912. / 32760.0; // Proper scale to return milliGauss + break; } } void MPU9250::getGres() { - switch (Gscale) - { - // Possible gyro scales (and their register bit settings) are: - // 250 DPS (00), 500 DPS (01), 1000 DPS (10), and 2000 DPS (11). - // Here's a bit of an algorith to calculate DPS/(ADC tick) based on that 2-bit value: + switch (Gscale) { + // Possible gyro scales (and their register bit settings) are: + // 250 DPS (00), 500 DPS (01), 1000 DPS (10), and 2000 DPS (11). + // Here's a bit of an algorith to calculate DPS/(ADC tick) based on that 2-bit value: case GFS_250DPS: - gRes = 250.0/32768.0; - break; + gRes = 250.0 / 32768.0; + break; case GFS_500DPS: - gRes = 500.0/32768.0; - break; + gRes = 500.0 / 32768.0; + break; case GFS_1000DPS: - gRes = 1000.0/32768.0; - break; + gRes = 1000.0 / 32768.0; + break; case GFS_2000DPS: - gRes = 2000.0/32768.0; - break; + gRes = 2000.0 / 32768.0; + break; } } void MPU9250::getAres() { - switch (Ascale) - { + switch (Ascale) { // Possible accelerometer scales (and their register bit settings) are: - // 2 Gs (00), 4 Gs (01), 8 Gs (10), and 16 Gs (11). - // Here's a bit of an algorith to calculate DPS/(ADC tick) based on that 2-bit value: + // 2 Gs (00), 4 Gs (01), 8 Gs (10), and 16 Gs (11). + // Here's a bit of an algorith to calculate DPS/(ADC tick) based on that 2-bit value: case AFS_2G: - aRes = 2.0/32768.0; - break; + aRes = 2.0 / 32768.0; + break; case AFS_4G: - aRes = 4.0/32768.0; - break; + aRes = 4.0 / 32768.0; + break; case AFS_8G: - aRes = 8.0/32768.0; - break; + aRes = 8.0 / 32768.0; + break; case AFS_16G: - aRes = 16.0/32768.0; - break; + aRes = 16.0 / 32768.0; + break; } } - -void MPU9250::readAccelData(int16_t * destination) -{ +void MPU9250::readAccelData(int16_t * destination) { uint8_t rawData[6]; // x/y/z accel register data stored here readBytes(MPU9250_ADDRESS, ACCEL_XOUT_H, 6, &rawData[0]); // Read the six raw data registers into data array destination[0] = ((int16_t)rawData[0] << 8) | rawData[1] ; // Turn the MSB and LSB into a signed 16-bit value - destination[1] = ((int16_t)rawData[2] << 8) | rawData[3] ; - destination[2] = ((int16_t)rawData[4] << 8) | rawData[5] ; + destination[1] = ((int16_t)rawData[2] << 8) | rawData[3] ; + destination[2] = ((int16_t)rawData[4] << 8) | rawData[5] ; } - -void MPU9250::readGyroData(int16_t * destination) -{ +void MPU9250::readGyroData(int16_t * destination) { uint8_t rawData[6]; // x/y/z gyro register data stored here readBytes(MPU9250_ADDRESS, GYRO_XOUT_H, 6, &rawData[0]); // Read the six raw data registers sequentially into data array destination[0] = ((int16_t)rawData[0] << 8) | rawData[1] ; // Turn the MSB and LSB into a signed 16-bit value - destination[1] = ((int16_t)rawData[2] << 8) | rawData[3] ; - destination[2] = ((int16_t)rawData[4] << 8) | rawData[5] ; + destination[1] = ((int16_t)rawData[2] << 8) | rawData[3] ; + destination[2] = ((int16_t)rawData[4] << 8) | rawData[5] ; } -void MPU9250::readMagData(int16_t * destination) -{ +void MPU9250::readMagData(int16_t * destination) { // x/y/z gyro register data, ST2 register stored here, must read ST2 at end of // data acquisition uint8_t rawData[7]; // Wait for magnetometer data ready bit to be set - if(readByte(AK8963_ADDRESS, AK8963_ST1) & 0x01) - { + if(readByte(AK8963_ADDRESS, AK8963_ST1) & 0x01) { // Read the six raw data and ST2 registers sequentially into data array readBytes(AK8963_ADDRESS, AK8963_XOUT_L, 7, &rawData[0]); uint8_t c = rawData[6]; // End data read by reading ST2 register // Check if magnetic sensor overflow set, if not then report data - if(!(c & 0x08)) - { + if(!(c & 0x08)) { // Turn the MSB and LSB into a signed 16-bit value destination[0] = ((int16_t)rawData[1] << 8) | rawData[0]; - // Data stored as little Endian + // Data stored as little Endian destination[1] = ((int16_t)rawData[3] << 8) | rawData[2]; destination[2] = ((int16_t)rawData[5] << 8) | rawData[4]; } } } -int16_t MPU9250::readTempData() -{ +int16_t MPU9250::readTempData() { uint8_t rawData[2]; // x/y/z gyro register data stored here - readBytes(MPU9250_ADDRESS, TEMP_OUT_H, 2, &rawData[0]); // Read the two raw data registers sequentially into data array + readBytes(MPU9250_ADDRESS, TEMP_OUT_H, 2, &rawData[0]); // Read the two raw data registers sequentially into data array return ((int16_t)rawData[0] << 8) | rawData[1]; // Turn the MSB and LSB into a 16-bit value } // Calculate the time the last update took for use in the quaternion filters -void MPU9250::updateTime() -{ +void MPU9250::updateTime() { Now = micros(); - + // Set integration time by time elapsed since last filter update deltat = ((Now - lastUpdate) / 1000000.0f); lastUpdate = Now; @@ -125,19 +113,18 @@ void MPU9250::updateTime() sumCount++; } -void MPU9250::initAK8963(float * destination) -{ +void MPU9250::initAK8963(float * destination) { // First extract the factory calibration for each magnetometer axis uint8_t rawData[3]; // x/y/z gyro calibration data stored here - writeByte(AK8963_ADDRESS, AK8963_CNTL, 0x00); // Power down magnetometer + writeByte(AK8963_ADDRESS, AK8963_CNTL, 0x00); // Power down magnetometer delay(10); writeByte(AK8963_ADDRESS, AK8963_CNTL, 0x0F); // Enter Fuse ROM access mode delay(10); readBytes(AK8963_ADDRESS, AK8963_ASAX, 3, &rawData[0]); // Read the x-, y-, and z-axis calibration values - destination[0] = (float)(rawData[0] - 128)/256. + 1.; // Return x-axis sensitivity adjustment values, etc. - destination[1] = (float)(rawData[1] - 128)/256. + 1.; - destination[2] = (float)(rawData[2] - 128)/256. + 1.; - writeByte(AK8963_ADDRESS, AK8963_CNTL, 0x00); // Power down magnetometer + destination[0] = (float)(rawData[0] - 128) / 256. + 1.; // Return x-axis sensitivity adjustment values, etc. + destination[1] = (float)(rawData[1] - 128) / 256. + 1.; + destination[2] = (float)(rawData[2] - 128) / 256. + 1.; + writeByte(AK8963_ADDRESS, AK8963_CNTL, 0x00); // Power down magnetometer delay(10); // Configure the magnetometer for continuous read and highest resolution // set Mscale bit 4 to 1 (0) to enable 16 (14) bit resolution in CNTL register, @@ -146,117 +133,113 @@ void MPU9250::initAK8963(float * destination) delay(10); } -void MPU9250::initMPU9250() -{ - // wake up device - writeByte(MPU9250_ADDRESS, PWR_MGMT_1, 0x00); // Clear sleep mode bit (6), enable all sensors - delay(100); // Wait for all registers to reset +void MPU9250::initMPU9250() { + // wake up device + writeByte(MPU9250_ADDRESS, PWR_MGMT_1, 0x00); // Clear sleep mode bit (6), enable all sensors + delay(100); // Wait for all registers to reset - // get stable time source + // get stable time source writeByte(MPU9250_ADDRESS, PWR_MGMT_1, 0x01); // Auto select clock source to be PLL gyroscope reference if ready else - delay(200); - - // Configure Gyro and Thermometer - // Disable FSYNC and set thermometer and gyro bandwidth to 41 and 42 Hz, respectively; - // minimum delay time for this setting is 5.9 ms, which means sensor fusion update rates cannot - // be higher than 1 / 0.0059 = 170 Hz - // DLPF_CFG = bits 2:0 = 011; this limits the sample rate to 1000 Hz for both - // With the MPU9250, it is possible to get gyro sample rates of 32 kHz (!), 8 kHz, or 1 kHz - writeByte(MPU9250_ADDRESS, CONFIG, 0x03); + delay(200); - // Set sample rate = gyroscope output rate/(1 + SMPLRT_DIV) - writeByte(MPU9250_ADDRESS, SMPLRT_DIV, 0x04); // Use a 200 Hz rate; a rate consistent with the filter update rate - // determined inset in CONFIG above - - // Set gyroscope full scale range - // Range selects FS_SEL and AFS_SEL are 0 - 3, so 2-bit values are left-shifted into positions 4:3 + // Configure Gyro and Thermometer + // Disable FSYNC and set thermometer and gyro bandwidth to 41 and 42 Hz, respectively; + // minimum delay time for this setting is 5.9 ms, which means sensor fusion update rates cannot + // be higher than 1 / 0.0059 = 170 Hz + // DLPF_CFG = bits 2:0 = 011; this limits the sample rate to 1000 Hz for both + // With the MPU9250, it is possible to get gyro sample rates of 32 kHz (!), 8 kHz, or 1 kHz + writeByte(MPU9250_ADDRESS, CONFIG, 0x03); + + // Set sample rate = gyroscope output rate/(1 + SMPLRT_DIV) + writeByte(MPU9250_ADDRESS, SMPLRT_DIV, 0x04); // Use a 200 Hz rate; a rate consistent with the filter update rate + // determined inset in CONFIG above + + // Set gyroscope full scale range + // Range selects FS_SEL and AFS_SEL are 0 - 3, so 2-bit values are left-shifted into positions 4:3 uint8_t c = readByte(MPU9250_ADDRESS, GYRO_CONFIG); // get current GYRO_CONFIG register value - // c = c & ~0xE0; // Clear self-test bits [7:5] - c = c & ~0x02; // Clear Fchoice bits [1:0] + // c = c & ~0xE0; // Clear self-test bits [7:5] + c = c & ~0x02; // Clear Fchoice bits [1:0] c = c & ~0x18; // Clear AFS bits [4:3] c = c | Gscale << 3; // Set full scale range for the gyro - // c =| 0x00; // Set Fchoice for the gyro to 11 by writing its inverse to bits 1:0 of GYRO_CONFIG - writeByte(MPU9250_ADDRESS, GYRO_CONFIG, c ); // Write new GYRO_CONFIG value to register - - // Set accelerometer full-scale range configuration + // c =| 0x00; // Set Fchoice for the gyro to 11 by writing its inverse to bits 1:0 of GYRO_CONFIG + writeByte(MPU9250_ADDRESS, GYRO_CONFIG, c); // Write new GYRO_CONFIG value to register + + // Set accelerometer full-scale range configuration c = readByte(MPU9250_ADDRESS, ACCEL_CONFIG); // get current ACCEL_CONFIG register value - // c = c & ~0xE0; // Clear self-test bits [7:5] + // c = c & ~0xE0; // Clear self-test bits [7:5] c = c & ~0x18; // Clear AFS bits [4:3] - c = c | Ascale << 3; // Set full scale range for the accelerometer + c = c | Ascale << 3; // Set full scale range for the accelerometer writeByte(MPU9250_ADDRESS, ACCEL_CONFIG, c); // Write new ACCEL_CONFIG register value - // Set accelerometer sample rate configuration - // It is possible to get a 4 kHz sample rate from the accelerometer by choosing 1 for - // accel_fchoice_b bit [3]; in this case the bandwidth is 1.13 kHz + // Set accelerometer sample rate configuration + // It is possible to get a 4 kHz sample rate from the accelerometer by choosing 1 for + // accel_fchoice_b bit [3]; in this case the bandwidth is 1.13 kHz c = readByte(MPU9250_ADDRESS, ACCEL_CONFIG2); // get current ACCEL_CONFIG2 register value - c = c & ~0x0F; // Clear accel_fchoice_b (bit 3) and A_DLPFG (bits [2:0]) + c = c & ~0x0F; // Clear accel_fchoice_b (bit 3) and A_DLPFG (bits [2:0]) c = c | 0x03; // Set accelerometer rate to 1 kHz and bandwidth to 41 Hz writeByte(MPU9250_ADDRESS, ACCEL_CONFIG2, c); // Write new ACCEL_CONFIG2 register value - // The accelerometer, gyro, and thermometer are set to 1 kHz sample rates, - // but all these rates are further reduced by a factor of 5 to 200 Hz because of the SMPLRT_DIV setting + // The accelerometer, gyro, and thermometer are set to 1 kHz sample rates, + // but all these rates are further reduced by a factor of 5 to 200 Hz because of the SMPLRT_DIV setting // Configure Interrupts and Bypass Enable // Set interrupt pin active high, push-pull, hold interrupt pin level HIGH until interrupt cleared, - // clear on read of INT_STATUS, and enable I2C_BYPASS_EN so additional chips + // clear on read of INT_STATUS, and enable I2C_BYPASS_EN so additional chips // can join the I2C bus and all can be controlled by the Arduino as master - writeByte(MPU9250_ADDRESS, INT_PIN_CFG, 0x22); - writeByte(MPU9250_ADDRESS, INT_ENABLE, 0x01); // Enable data ready (bit 0) interrupt - delay(100); + writeByte(MPU9250_ADDRESS, INT_PIN_CFG, 0x22); + writeByte(MPU9250_ADDRESS, INT_ENABLE, 0x01); // Enable data ready (bit 0) interrupt + delay(100); } - // Function which accumulates gyro and accelerometer data after device // initialization. It calculates the average of the at-rest readings and then // loads the resulting offsets into accelerometer and gyro bias registers. -void MPU9250::calibrateMPU9250(float * gyroBias, float * accelBias) -{ +void MPU9250::calibrateMPU9250(float * gyroBias, float * accelBias) { uint8_t data[12]; // data array to hold accelerometer and gyro x, y, z, data uint16_t ii, packet_count, fifo_count; - int32_t gyro_bias[3] = {0, 0, 0}, accel_bias[3] = {0, 0, 0}; - + int32_t gyro_bias[3] = { 0, 0, 0 }, accel_bias[3] = { 0, 0, 0 }; + // reset device // Write a one to bit 7 reset bit; toggle reset device writeByte(MPU9250_ADDRESS, PWR_MGMT_1, 0x80); delay(100); - - // get stable time source; Auto select clock source to be PLL gyroscope - // reference if ready else use the internal oscillator, bits 2:0 = 001 - writeByte(MPU9250_ADDRESS, PWR_MGMT_1, 0x01); + + // get stable time source; Auto select clock source to be PLL gyroscope + // reference if ready else use the internal oscillator, bits 2:0 = 001 + writeByte(MPU9250_ADDRESS, PWR_MGMT_1, 0x01); writeByte(MPU9250_ADDRESS, PWR_MGMT_2, 0x00); - delay(200); + delay(200); // Configure device for bias calculation writeByte(MPU9250_ADDRESS, INT_ENABLE, 0x00); // Disable all interrupts - writeByte(MPU9250_ADDRESS, FIFO_EN, 0x00); // Disable FIFO + writeByte(MPU9250_ADDRESS, FIFO_EN, 0x00); // Disable FIFO writeByte(MPU9250_ADDRESS, PWR_MGMT_1, 0x00); // Turn on internal clock source writeByte(MPU9250_ADDRESS, I2C_MST_CTRL, 0x00); // Disable I2C master - writeByte(MPU9250_ADDRESS, USER_CTRL, 0x00); // Disable FIFO and I2C master modes - writeByte(MPU9250_ADDRESS, USER_CTRL, 0x0C); // Reset FIFO and DMP + writeByte(MPU9250_ADDRESS, USER_CTRL, 0x00); // Disable FIFO and I2C master modes + writeByte(MPU9250_ADDRESS, USER_CTRL, 0x0C); // Reset FIFO and DMP delay(15); - -// Configure MPU6050 gyro and accelerometer for bias calculation - writeByte(MPU9250_ADDRESS, CONFIG, 0x01); // Set low-pass filter to 188 Hz + + // Configure MPU6050 gyro and accelerometer for bias calculation + writeByte(MPU9250_ADDRESS, CONFIG, 0x01); // Set low-pass filter to 188 Hz writeByte(MPU9250_ADDRESS, SMPLRT_DIV, 0x00); // Set sample rate to 1 kHz writeByte(MPU9250_ADDRESS, GYRO_CONFIG, 0x00); // Set gyro full-scale to 250 degrees per second, maximum sensitivity writeByte(MPU9250_ADDRESS, ACCEL_CONFIG, 0x00); // Set accelerometer full-scale to 2 g, maximum sensitivity - + uint16_t gyrosensitivity = 131; // = 131 LSB/degrees/sec uint16_t accelsensitivity = 16384; // = 16384 LSB/g - // Configure FIFO to capture accelerometer and gyro data for bias calculation - writeByte(MPU9250_ADDRESS, USER_CTRL, 0x40); // Enable FIFO - writeByte(MPU9250_ADDRESS, FIFO_EN, 0x78); // Enable gyro and accelerometer sensors for FIFO (max size 512 bytes in MPU-9150) + // Configure FIFO to capture accelerometer and gyro data for bias calculation + writeByte(MPU9250_ADDRESS, USER_CTRL, 0x40); // Enable FIFO + writeByte(MPU9250_ADDRESS, FIFO_EN, 0x78); // Enable gyro and accelerometer sensors for FIFO (max size 512 bytes in MPU-9150) delay(40); // accumulate 40 samples in 40 milliseconds = 480 bytes -// At end of sample accumulation, turn off FIFO sensor read - writeByte(MPU9250_ADDRESS, FIFO_EN, 0x00); // Disable gyro and accelerometer sensors for FIFO + // At end of sample accumulation, turn off FIFO sensor read + writeByte(MPU9250_ADDRESS, FIFO_EN, 0x00); // Disable gyro and accelerometer sensors for FIFO readBytes(MPU9250_ADDRESS, FIFO_COUNTH, 2, &data[0]); // read FIFO sample count fifo_count = ((uint16_t)data[0] << 8) | data[1]; - packet_count = fifo_count/12;// How many sets of full gyro and accelerometer data for averaging - - for (ii = 0; ii < packet_count; ii++) - { - int16_t accel_temp[3] = {0, 0, 0}, gyro_temp[3] = {0, 0, 0}; + packet_count = fifo_count / 12; // How many sets of full gyro and accelerometer data for averaging + + for (ii = 0; ii < packet_count; ii++) { + int16_t accel_temp[3] = { 0, 0, 0 }, gyro_temp[3] = { 0, 0, 0 }; readBytes(MPU9250_ADDRESS, FIFO_R_W, 12, &data[0]); // read data for averaging accel_temp[0] = (int16_t) (((int16_t)data[0] << 8) | data[1] ); // Form signed 16-bit integer for each sample in FIFO accel_temp[1] = (int16_t) (((int16_t)data[2] << 8) | data[3] ); @@ -264,7 +247,7 @@ void MPU9250::calibrateMPU9250(float * gyroBias, float * accelBias) gyro_temp[0] = (int16_t) (((int16_t)data[6] << 8) | data[7] ); gyro_temp[1] = (int16_t) (((int16_t)data[8] << 8) | data[9] ); gyro_temp[2] = (int16_t) (((int16_t)data[10] << 8) | data[11]); - + accel_bias[0] += (int32_t) accel_temp[0]; // Sum individual signed 16-bit biases to get accumulated signed 32-bit biases accel_bias[1] += (int32_t) accel_temp[1]; accel_bias[2] += (int32_t) accel_temp[2]; @@ -278,57 +261,63 @@ void MPU9250::calibrateMPU9250(float * gyroBias, float * accelBias) gyro_bias[0] /= (int32_t) packet_count; gyro_bias[1] /= (int32_t) packet_count; gyro_bias[2] /= (int32_t) packet_count; - - if(accel_bias[2] > 0L) {accel_bias[2] -= (int32_t) accelsensitivity;} // Remove gravity from the z-axis accelerometer bias calculation - else {accel_bias[2] += (int32_t) accelsensitivity;} - -// Construct the gyro biases for push to the hardware gyro bias registers, which are reset to zero upon device startup - data[0] = (-gyro_bias[0]/4 >> 8) & 0xFF; // Divide by 4 to get 32.9 LSB per deg/s to conform to expected bias input format - data[1] = (-gyro_bias[0]/4) & 0xFF; // Biases are additive, so change sign on calculated average gyro biases - data[2] = (-gyro_bias[1]/4 >> 8) & 0xFF; - data[3] = (-gyro_bias[1]/4) & 0xFF; - data[4] = (-gyro_bias[2]/4 >> 8) & 0xFF; - data[5] = (-gyro_bias[2]/4) & 0xFF; - -// Push gyro biases to hardware registers + + if(accel_bias[2] > 0L) { + // Remove gravity from the z-axis accelerometer bias calculation + accel_bias[2] -= (int32_t)accelsensitivity; + }else { + accel_bias[2] += (int32_t) accelsensitivity; + } + + // Construct the gyro biases for push to the hardware gyro bias registers, which are reset to zero upon device startup + data[0] = (-gyro_bias[0]/4 >> 8) & 0xFF; // Divide by 4 to get 32.9 LSB per deg/s to conform to expected bias input format + data[1] = (-gyro_bias[0] / 4) & 0xFF; // Biases are additive, so change sign on calculated average gyro biases + data[2] = (-gyro_bias[1] / 4 >> 8) & 0xFF; + data[3] = (-gyro_bias[1] / 4) & 0xFF; + data[4] = (-gyro_bias[2] / 4 >> 8) & 0xFF; + data[5] = (-gyro_bias[2] / 4) & 0xFF; + + // Push gyro biases to hardware registers writeByte(MPU9250_ADDRESS, XG_OFFSET_H, data[0]); writeByte(MPU9250_ADDRESS, XG_OFFSET_L, data[1]); writeByte(MPU9250_ADDRESS, YG_OFFSET_H, data[2]); writeByte(MPU9250_ADDRESS, YG_OFFSET_L, data[3]); writeByte(MPU9250_ADDRESS, ZG_OFFSET_H, data[4]); writeByte(MPU9250_ADDRESS, ZG_OFFSET_L, data[5]); - -// Output scaled gyro biases for display in the main program - gyroBias[0] = (float) gyro_bias[0]/(float) gyrosensitivity; - gyroBias[1] = (float) gyro_bias[1]/(float) gyrosensitivity; - gyroBias[2] = (float) gyro_bias[2]/(float) gyrosensitivity; -// Construct the accelerometer biases for push to the hardware accelerometer bias registers. These registers contain -// factory trim values which must be added to the calculated accelerometer biases; on boot up these registers will hold -// non-zero values. In addition, bit 0 of the lower byte must be preserved since it is used for temperature -// compensation calculations. Accelerometer bias registers expect bias input as 2048 LSB per g, so that -// the accelerometer biases calculated above must be divided by 8. + // Output scaled gyro biases for display in the main program + gyroBias[0] = (float) gyro_bias[0] / (float) gyrosensitivity; + gyroBias[1] = (float) gyro_bias[1] / (float) gyrosensitivity; + gyroBias[2] = (float) gyro_bias[2] / (float) gyrosensitivity; - int32_t accel_bias_reg[3] = {0, 0, 0}; // A place to hold the factory accelerometer trim biases + // Construct the accelerometer biases for push to the hardware accelerometer bias registers. These registers contain + // factory trim values which must be added to the calculated accelerometer biases; on boot up these registers will hold + // non-zero values. In addition, bit 0 of the lower byte must be preserved since it is used for temperature + // compensation calculations. Accelerometer bias registers expect bias input as 2048 LSB per g, so that + // the accelerometer biases calculated above must be divided by 8. + + int32_t accel_bias_reg[3] = { 0, 0, 0 }; // A place to hold the factory accelerometer trim biases readBytes(MPU9250_ADDRESS, XA_OFFSET_H, 2, &data[0]); // Read factory accelerometer trim values accel_bias_reg[0] = (int32_t) (((int16_t)data[0] << 8) | data[1]); readBytes(MPU9250_ADDRESS, YA_OFFSET_H, 2, &data[0]); accel_bias_reg[1] = (int32_t) (((int16_t)data[0] << 8) | data[1]); readBytes(MPU9250_ADDRESS, ZA_OFFSET_H, 2, &data[0]); accel_bias_reg[2] = (int32_t) (((int16_t)data[0] << 8) | data[1]); - + uint32_t mask = 1uL; // Define mask for temperature compensation bit 0 of lower byte of accelerometer bias registers - uint8_t mask_bit[3] = {0, 0, 0}; // Define array to hold mask bit for each accelerometer bias axis - + uint8_t mask_bit[3] = { 0, 0, 0 }; // Define array to hold mask bit for each accelerometer bias axis + for(ii = 0; ii < 3; ii++) { - if((accel_bias_reg[ii] & mask)) mask_bit[ii] = 0x01; // If temperature compensation bit is set, record that fact in mask_bit + if((accel_bias_reg[ii] & mask)) { + mask_bit[ii] = 0x01; // If temperature compensation bit is set, record that fact in mask_bit + } } - + // Construct total accelerometer bias, including calculated average accelerometer bias from above - accel_bias_reg[0] -= (accel_bias[0]/8); // Subtract calculated averaged accelerometer bias scaled to 2048 LSB/g (16 g full scale) - accel_bias_reg[1] -= (accel_bias[1]/8); - accel_bias_reg[2] -= (accel_bias[2]/8); - + accel_bias_reg[0] -= (accel_bias[0] / 8); // Subtract calculated averaged accelerometer bias scaled to 2048 LSB/g (16 g full scale) + accel_bias_reg[1] -= (accel_bias[1] / 8); + accel_bias_reg[2] -= (accel_bias[2] / 8); + data[0] = (accel_bias_reg[0] >> 8) & 0xFF; data[1] = (accel_bias_reg[0]) & 0xFF; data[1] = data[1] | mask_bit[0]; // preserve temperature compensation bit when writing back to accelerometer bias registers @@ -338,10 +327,10 @@ void MPU9250::calibrateMPU9250(float * gyroBias, float * accelBias) data[4] = (accel_bias_reg[2] >> 8) & 0xFF; data[5] = (accel_bias_reg[2]) & 0xFF; data[5] = data[5] | mask_bit[2]; // preserve temperature compensation bit when writing back to accelerometer bias registers - -// Apparently this is not working for the acceleration biases in the MPU-9250 -// Are we handling the temperature correction bit properly? -// Push accelerometer biases to hardware registers + + // Apparently this is not working for the acceleration biases in the MPU-9250 + // Are we handling the temperature correction bit properly? + // Push accelerometer biases to hardware registers writeByte(MPU9250_ADDRESS, XA_OFFSET_H, data[0]); writeByte(MPU9250_ADDRESS, XA_OFFSET_L, data[1]); writeByte(MPU9250_ADDRESS, YA_OFFSET_H, data[2]); @@ -349,74 +338,72 @@ void MPU9250::calibrateMPU9250(float * gyroBias, float * accelBias) writeByte(MPU9250_ADDRESS, ZA_OFFSET_H, data[4]); writeByte(MPU9250_ADDRESS, ZA_OFFSET_L, data[5]); -// Output scaled accelerometer biases for display in the main program - accelBias[0] = (float)accel_bias[0]/(float)accelsensitivity; - accelBias[1] = (float)accel_bias[1]/(float)accelsensitivity; - accelBias[2] = (float)accel_bias[2]/(float)accelsensitivity; + // Output scaled accelerometer biases for display in the main program + accelBias[0] = (float)accel_bias[0] / (float)accelsensitivity; + accelBias[1] = (float)accel_bias[1] / (float)accelsensitivity; + accelBias[2] = (float)accel_bias[2] / (float)accelsensitivity; } - // Accelerometer and gyroscope self test; check calibration wrt factory settings -void MPU9250::MPU9250SelfTest(float * destination) // Should return percent deviation from factory trim values, +/- 14 or less deviation is a pass -{ - uint8_t rawData[6] = {0, 0, 0, 0, 0, 0}; +void MPU9250::MPU9250SelfTest(float * destination) { // Should return percent deviation from factory trim values, +/- 14 or less deviation is a pass + uint8_t rawData[6] = { 0, 0, 0, 0, 0, 0 }; uint8_t selfTest[6]; int16_t gAvg[3], aAvg[3], aSTAvg[3], gSTAvg[3]; float factoryTrim[6]; uint8_t FS = 0; - - writeByte(MPU9250_ADDRESS, SMPLRT_DIV, 0x00); // Set gyro sample rate to 1 kHz - writeByte(MPU9250_ADDRESS, CONFIG, 0x02); // Set gyro sample rate to 1 kHz and DLPF to 92 Hz - writeByte(MPU9250_ADDRESS, GYRO_CONFIG, 1< -#include + #include + #include -// See also MPU-9250 Register Map and Descriptions, Revision 4.0, -// RM-MPU-9250A-00, Rev. 1.4, 9/9/2013 for registers not listed in above -// document; the MPU9250 and MPU9150 are virtually identical but the latter has -// a different register map + // See also MPU-9250 Register Map and Descriptions, Revision 4.0, + // RM-MPU-9250A-00, Rev. 1.4, 9/9/2013 for registers not listed in above + // document; the MPU9250 and MPU9150 are virtually identical but the latter has + // a different register map -//Magnetometer Registers -#define AK8963_ADDRESS 0x0C -#define WHO_AM_I_AK8963 0x00 // should return 0x48 -#define INFO 0x01 -#define AK8963_ST1 0x02 // data ready status bit 0 -#define AK8963_XOUT_L 0x03 // data -#define AK8963_XOUT_H 0x04 -#define AK8963_YOUT_L 0x05 -#define AK8963_YOUT_H 0x06 -#define AK8963_ZOUT_L 0x07 -#define AK8963_ZOUT_H 0x08 -#define AK8963_ST2 0x09 // Data overflow bit 3 and data read error status bit 2 -#define AK8963_CNTL 0x0A // Power down (0000), single-measurement (0001), self-test (1000) and Fuse ROM (1111) modes on bits 3:0 -#define AK8963_ASTC 0x0C // Self test control -#define AK8963_I2CDIS 0x0F // I2C disable -#define AK8963_ASAX 0x10 // Fuse ROM x-axis sensitivity adjustment value -#define AK8963_ASAY 0x11 // Fuse ROM y-axis sensitivity adjustment value -#define AK8963_ASAZ 0x12 // Fuse ROM z-axis sensitivity adjustment value + //Magnetometer Registers + #define AK8963_ADDRESS 0x0C + #define WHO_AM_I_AK8963 0x00 // should return 0x48 + #define INFO 0x01 + #define AK8963_ST1 0x02 // data ready status bit 0 + #define AK8963_XOUT_L 0x03 // data + #define AK8963_XOUT_H 0x04 + #define AK8963_YOUT_L 0x05 + #define AK8963_YOUT_H 0x06 + #define AK8963_ZOUT_L 0x07 + #define AK8963_ZOUT_H 0x08 + #define AK8963_ST2 0x09 // Data overflow bit 3 and data read error status bit 2 + #define AK8963_CNTL 0x0A // Power down (0000), single-measurement (0001), self-test (1000) and Fuse ROM (1111) modes on bits 3:0 + #define AK8963_ASTC 0x0C // Self test control + #define AK8963_I2CDIS 0x0F // I2C disable + #define AK8963_ASAX 0x10 // Fuse ROM x-axis sensitivity adjustment value + #define AK8963_ASAY 0x11 // Fuse ROM y-axis sensitivity adjustment value + #define AK8963_ASAZ 0x12 // Fuse ROM z-axis sensitivity adjustment value -#define SELF_TEST_X_GYRO 0x00 -#define SELF_TEST_Y_GYRO 0x01 -#define SELF_TEST_Z_GYRO 0x02 + #define SELF_TEST_X_GYRO 0x00 + #define SELF_TEST_Y_GYRO 0x01 + #define SELF_TEST_Z_GYRO 0x02 -/*#define X_FINE_GAIN 0x03 // [7:0] fine gain -#define Y_FINE_GAIN 0x04 -#define Z_FINE_GAIN 0x05 -#define XA_OFFSET_H 0x06 // User-defined trim values for accelerometer -#define XA_OFFSET_L_TC 0x07 -#define YA_OFFSET_H 0x08 -#define YA_OFFSET_L_TC 0x09 -#define ZA_OFFSET_H 0x0A -#define ZA_OFFSET_L_TC 0x0B */ + /*#define X_FINE_GAIN 0x03 // [7:0] fine gain + #define Y_FINE_GAIN 0x04 + #define Z_FINE_GAIN 0x05 + #define XA_OFFSET_H 0x06 // User-defined trim values for accelerometer + #define XA_OFFSET_L_TC 0x07 + #define YA_OFFSET_H 0x08 + #define YA_OFFSET_L_TC 0x09 + #define ZA_OFFSET_H 0x0A + #define ZA_OFFSET_L_TC 0x0B */ -#define SELF_TEST_X_ACCEL 0x0D -#define SELF_TEST_Y_ACCEL 0x0E -#define SELF_TEST_Z_ACCEL 0x0F + #define SELF_TEST_X_ACCEL 0x0D + #define SELF_TEST_Y_ACCEL 0x0E + #define SELF_TEST_Z_ACCEL 0x0F -#define SELF_TEST_A 0x10 + #define SELF_TEST_A 0x10 -#define XG_OFFSET_H 0x13 // User-defined trim values for gyroscope -#define XG_OFFSET_L 0x14 -#define YG_OFFSET_H 0x15 -#define YG_OFFSET_L 0x16 -#define ZG_OFFSET_H 0x17 -#define ZG_OFFSET_L 0x18 -#define SMPLRT_DIV 0x19 -#define CONFIG 0x1A -#define GYRO_CONFIG 0x1B -#define ACCEL_CONFIG 0x1C -#define ACCEL_CONFIG2 0x1D -#define LP_ACCEL_ODR 0x1E -#define WOM_THR 0x1F + #define XG_OFFSET_H 0x13 // User-defined trim values for gyroscope + #define XG_OFFSET_L 0x14 + #define YG_OFFSET_H 0x15 + #define YG_OFFSET_L 0x16 + #define ZG_OFFSET_H 0x17 + #define ZG_OFFSET_L 0x18 + #define SMPLRT_DIV 0x19 + #define CONFIG 0x1A + #define GYRO_CONFIG 0x1B + #define ACCEL_CONFIG 0x1C + #define ACCEL_CONFIG2 0x1D + #define LP_ACCEL_ODR 0x1E + #define WOM_THR 0x1F -// Duration counter threshold for motion interrupt generation, 1 kHz rate, -// LSB = 1 ms -#define MOT_DUR 0x20 -// Zero-motion detection threshold bits [7:0] -#define ZMOT_THR 0x21 -// Duration counter threshold for zero motion interrupt generation, 16 Hz rate, -// LSB = 64 ms -#define ZRMOT_DUR 0x22 + // Duration counter threshold for motion interrupt generation, 1 kHz rate, + // LSB = 1 ms + #define MOT_DUR 0x20 + // Zero-motion detection threshold bits [7:0] + #define ZMOT_THR 0x21 + // Duration counter threshold for zero motion interrupt generation, 16 Hz rate, + // LSB = 64 ms + #define ZRMOT_DUR 0x22 -#define FIFO_EN 0x23 -#define I2C_MST_CTRL 0x24 -#define I2C_SLV0_ADDR 0x25 -#define I2C_SLV0_REG 0x26 -#define I2C_SLV0_CTRL 0x27 -#define I2C_SLV1_ADDR 0x28 -#define I2C_SLV1_REG 0x29 -#define I2C_SLV1_CTRL 0x2A -#define I2C_SLV2_ADDR 0x2B -#define I2C_SLV2_REG 0x2C -#define I2C_SLV2_CTRL 0x2D -#define I2C_SLV3_ADDR 0x2E -#define I2C_SLV3_REG 0x2F -#define I2C_SLV3_CTRL 0x30 -#define I2C_SLV4_ADDR 0x31 -#define I2C_SLV4_REG 0x32 -#define I2C_SLV4_DO 0x33 -#define I2C_SLV4_CTRL 0x34 -#define I2C_SLV4_DI 0x35 -#define I2C_MST_STATUS 0x36 -#define INT_PIN_CFG 0x37 -#define INT_ENABLE 0x38 -#define DMP_INT_STATUS 0x39 // Check DMP interrupt -#define INT_STATUS 0x3A -#define ACCEL_XOUT_H 0x3B -#define ACCEL_XOUT_L 0x3C -#define ACCEL_YOUT_H 0x3D -#define ACCEL_YOUT_L 0x3E -#define ACCEL_ZOUT_H 0x3F -#define ACCEL_ZOUT_L 0x40 -#define TEMP_OUT_H 0x41 -#define TEMP_OUT_L 0x42 -#define GYRO_XOUT_H 0x43 -#define GYRO_XOUT_L 0x44 -#define GYRO_YOUT_H 0x45 -#define GYRO_YOUT_L 0x46 -#define GYRO_ZOUT_H 0x47 -#define GYRO_ZOUT_L 0x48 -#define EXT_SENS_DATA_00 0x49 -#define EXT_SENS_DATA_01 0x4A -#define EXT_SENS_DATA_02 0x4B -#define EXT_SENS_DATA_03 0x4C -#define EXT_SENS_DATA_04 0x4D -#define EXT_SENS_DATA_05 0x4E -#define EXT_SENS_DATA_06 0x4F -#define EXT_SENS_DATA_07 0x50 -#define EXT_SENS_DATA_08 0x51 -#define EXT_SENS_DATA_09 0x52 -#define EXT_SENS_DATA_10 0x53 -#define EXT_SENS_DATA_11 0x54 -#define EXT_SENS_DATA_12 0x55 -#define EXT_SENS_DATA_13 0x56 -#define EXT_SENS_DATA_14 0x57 -#define EXT_SENS_DATA_15 0x58 -#define EXT_SENS_DATA_16 0x59 -#define EXT_SENS_DATA_17 0x5A -#define EXT_SENS_DATA_18 0x5B -#define EXT_SENS_DATA_19 0x5C -#define EXT_SENS_DATA_20 0x5D -#define EXT_SENS_DATA_21 0x5E -#define EXT_SENS_DATA_22 0x5F -#define EXT_SENS_DATA_23 0x60 -#define MOT_DETECT_STATUS 0x61 -#define I2C_SLV0_DO 0x63 -#define I2C_SLV1_DO 0x64 -#define I2C_SLV2_DO 0x65 -#define I2C_SLV3_DO 0x66 -#define I2C_MST_DELAY_CTRL 0x67 -#define SIGNAL_PATH_RESET 0x68 -#define MOT_DETECT_CTRL 0x69 -#define USER_CTRL 0x6A // Bit 7 enable DMP, bit 3 reset DMP -#define PWR_MGMT_1 0x6B // Device defaults to the SLEEP mode -#define PWR_MGMT_2 0x6C -#define DMP_BANK 0x6D // Activates a specific bank in the DMP -#define DMP_RW_PNT 0x6E // Set read/write pointer to a specific start address in specified DMP bank -#define DMP_REG 0x6F // Register in DMP from which to read or to which to write -#define DMP_REG_1 0x70 -#define DMP_REG_2 0x71 -#define FIFO_COUNTH 0x72 -#define FIFO_COUNTL 0x73 -#define FIFO_R_W 0x74 -#define WHO_AM_I_MPU9250 0x75 // Should return 0x71 -#define XA_OFFSET_H 0x77 -#define XA_OFFSET_L 0x78 -#define YA_OFFSET_H 0x7A -#define YA_OFFSET_L 0x7B -#define ZA_OFFSET_H 0x7D -#define ZA_OFFSET_L 0x7E + #define FIFO_EN 0x23 + #define I2C_MST_CTRL 0x24 + #define I2C_SLV0_ADDR 0x25 + #define I2C_SLV0_REG 0x26 + #define I2C_SLV0_CTRL 0x27 + #define I2C_SLV1_ADDR 0x28 + #define I2C_SLV1_REG 0x29 + #define I2C_SLV1_CTRL 0x2A + #define I2C_SLV2_ADDR 0x2B + #define I2C_SLV2_REG 0x2C + #define I2C_SLV2_CTRL 0x2D + #define I2C_SLV3_ADDR 0x2E + #define I2C_SLV3_REG 0x2F + #define I2C_SLV3_CTRL 0x30 + #define I2C_SLV4_ADDR 0x31 + #define I2C_SLV4_REG 0x32 + #define I2C_SLV4_DO 0x33 + #define I2C_SLV4_CTRL 0x34 + #define I2C_SLV4_DI 0x35 + #define I2C_MST_STATUS 0x36 + #define INT_PIN_CFG 0x37 + #define INT_ENABLE 0x38 + #define DMP_INT_STATUS 0x39 // Check DMP interrupt + #define INT_STATUS 0x3A + #define ACCEL_XOUT_H 0x3B + #define ACCEL_XOUT_L 0x3C + #define ACCEL_YOUT_H 0x3D + #define ACCEL_YOUT_L 0x3E + #define ACCEL_ZOUT_H 0x3F + #define ACCEL_ZOUT_L 0x40 + #define TEMP_OUT_H 0x41 + #define TEMP_OUT_L 0x42 + #define GYRO_XOUT_H 0x43 + #define GYRO_XOUT_L 0x44 + #define GYRO_YOUT_H 0x45 + #define GYRO_YOUT_L 0x46 + #define GYRO_ZOUT_H 0x47 + #define GYRO_ZOUT_L 0x48 + #define EXT_SENS_DATA_00 0x49 + #define EXT_SENS_DATA_01 0x4A + #define EXT_SENS_DATA_02 0x4B + #define EXT_SENS_DATA_03 0x4C + #define EXT_SENS_DATA_04 0x4D + #define EXT_SENS_DATA_05 0x4E + #define EXT_SENS_DATA_06 0x4F + #define EXT_SENS_DATA_07 0x50 + #define EXT_SENS_DATA_08 0x51 + #define EXT_SENS_DATA_09 0x52 + #define EXT_SENS_DATA_10 0x53 + #define EXT_SENS_DATA_11 0x54 + #define EXT_SENS_DATA_12 0x55 + #define EXT_SENS_DATA_13 0x56 + #define EXT_SENS_DATA_14 0x57 + #define EXT_SENS_DATA_15 0x58 + #define EXT_SENS_DATA_16 0x59 + #define EXT_SENS_DATA_17 0x5A + #define EXT_SENS_DATA_18 0x5B + #define EXT_SENS_DATA_19 0x5C + #define EXT_SENS_DATA_20 0x5D + #define EXT_SENS_DATA_21 0x5E + #define EXT_SENS_DATA_22 0x5F + #define EXT_SENS_DATA_23 0x60 + #define MOT_DETECT_STATUS 0x61 + #define I2C_SLV0_DO 0x63 + #define I2C_SLV1_DO 0x64 + #define I2C_SLV2_DO 0x65 + #define I2C_SLV3_DO 0x66 + #define I2C_MST_DELAY_CTRL 0x67 + #define SIGNAL_PATH_RESET 0x68 + #define MOT_DETECT_CTRL 0x69 + #define USER_CTRL 0x6A // Bit 7 enable DMP, bit 3 reset DMP + #define PWR_MGMT_1 0x6B // Device defaults to the SLEEP mode + #define PWR_MGMT_2 0x6C + #define DMP_BANK 0x6D // Activates a specific bank in the DMP + #define DMP_RW_PNT 0x6E // Set read/write pointer to a specific start address in specified DMP bank + #define DMP_REG 0x6F // Register in DMP from which to read or to which to write + #define DMP_REG_1 0x70 + #define DMP_REG_2 0x71 + #define FIFO_COUNTH 0x72 + #define FIFO_COUNTL 0x73 + #define FIFO_R_W 0x74 + #define WHO_AM_I_MPU9250 0x75 // Should return 0x71 + #define XA_OFFSET_H 0x77 + #define XA_OFFSET_L 0x78 + #define YA_OFFSET_H 0x7A + #define YA_OFFSET_L 0x7B + #define ZA_OFFSET_H 0x7D + #define ZA_OFFSET_L 0x7E -// Using the MPU-9250 breakout board, ADO is set to 0 -// Seven-bit device address is 110100 for ADO = 0 and 110101 for ADO = 1 -#define ADO 0 -#if ADO -#define MPU9250_ADDRESS 0x69 // Device address when ADO = 1 -#else -#define MPU9250_ADDRESS 0x68 // Device address when ADO = 0 -#define AK8963_ADDRESS 0x0C // Address of magnetometer -#endif // AD0 + // Using the MPU-9250 breakout board, ADO is set to 0 + // Seven-bit device address is 110100 for ADO = 0 and 110101 for ADO = 1 + #define ADO 0 + #if ADO + #define MPU9250_ADDRESS 0x69 // Device address when ADO = 1 + #else + #define MPU9250_ADDRESS 0x68 // Device address when ADO = 0 + #define AK8963_ADDRESS 0x0C // Address of magnetometer + #endif // AD0 -class MPU9250 -{ - protected: - // Set initial input parameters - enum Ascale { - AFS_2G = 0, - AFS_4G, - AFS_8G, - AFS_16G - }; + class MPU9250 { + protected: + // Set initial input parameters + enum Ascale { + AFS_2G = 0, + AFS_4G, + AFS_8G, + AFS_16G + }; - enum Gscale { - GFS_250DPS = 0, - GFS_500DPS, - GFS_1000DPS, - GFS_2000DPS - }; + enum Gscale { + GFS_250DPS = 0, + GFS_500DPS, + GFS_1000DPS, + GFS_2000DPS + }; - enum Mscale { - MFS_14BITS = 0, // 0.6 mG per LSB - MFS_16BITS // 0.15 mG per LSB - }; + enum Mscale { + MFS_14BITS = 0, // 0.6 mG per LSB + MFS_16BITS // 0.15 mG per LSB + }; - // Specify sensor full scale - uint8_t Gscale = GFS_250DPS; - uint8_t Ascale = AFS_2G; - // Choose either 14-bit or 16-bit magnetometer resolution - uint8_t Mscale = MFS_16BITS; - // 2 for 8 Hz, 6 for 100 Hz continuous magnetometer data read - uint8_t Mmode = 0x02; + // Specify sensor full scale + uint8_t Gscale = GFS_250DPS; + uint8_t Ascale = AFS_2G; + // Choose either 14-bit or 16-bit magnetometer resolution + uint8_t Mscale = MFS_16BITS; + // 2 for 8 Hz, 6 for 100 Hz continuous magnetometer data read + uint8_t Mmode = 0x02; - public: - float pitch, yaw, roll; - float temperature; // Stores the real internal chip temperature in Celsius - int16_t tempCount; // Temperature raw count output - uint32_t delt_t = 0; // Used to control display output rate + public: + float pitch, yaw, roll; + float temperature; // Stores the real internal chip temperature in Celsius + int16_t tempCount; // Temperature raw count output + uint32_t delt_t = 0; // Used to control display output rate - uint32_t count = 0, sumCount = 0; // used to control display output rate - float deltat = 0.0f, sum = 0.0f; // integration interval for both filter schemes - uint32_t lastUpdate = 0, firstUpdate = 0; // used to calculate integration interval - uint32_t Now = 0; // used to calculate integration interval + uint32_t count = 0, sumCount = 0; // used to control display output rate + float deltat = 0.0f, sum = 0.0f; // integration interval for both filter schemes + uint32_t lastUpdate = 0, firstUpdate = 0; // used to calculate integration interval + uint32_t Now = 0; // used to calculate integration interval - int16_t gyroCount[3]; // Stores the 16-bit signed gyro sensor output - int16_t magCount[3]; // Stores the 16-bit signed magnetometer sensor output - // Scale resolutions per LSB for the sensors - float aRes, gRes, mRes; - // Variables to hold latest sensor data values - float ax, ay, az, gx, gy, gz, mx, my, mz; - // Factory mag calibration and mag bias - float magCalibration[3] = {0, 0, 0}, magbias[3] = {0, 0, 0}; - // Bias corrections for gyro and accelerometer - float gyroBias[3] = {0, 0, 0}, accelBias[3] = {0, 0, 0}; - float SelfTest[6]; - // Stores the 16-bit signed accelerometer sensor output - int16_t accelCount[3]; - - public: - void getMres(); - void getGres(); - void getAres(); - void readAccelData(int16_t *); - void readGyroData(int16_t *); - void readMagData(int16_t *); - int16_t readTempData(); - void updateTime(); - void initAK8963(float *); - void initMPU9250(); - void calibrateMPU9250(float * gyroBias, float * accelBias); - void MPU9250SelfTest(float * destination); - void writeByte(uint8_t, uint8_t, uint8_t) __attribute__ ((deprecated)); - uint8_t readByte(uint8_t, uint8_t) __attribute__ ((deprecated)); - void readBytes(uint8_t, uint8_t, uint8_t, uint8_t *) __attribute__ ((deprecated)); -}; // class MPU9250 + int16_t gyroCount[3]; // Stores the 16-bit signed gyro sensor output + int16_t magCount[3]; // Stores the 16-bit signed magnetometer sensor output + // Scale resolutions per LSB for the sensors + float aRes, gRes, mRes; + // Variables to hold latest sensor data values + float ax, ay, az, gx, gy, gz, mx, my, mz; + // Factory mag calibration and mag bias + float magCalibration[3] = {0, 0, 0}, magbias[3] = {0, 0, 0}; + // Bias corrections for gyro and accelerometer + float gyroBias[3] = {0, 0, 0}, accelBias[3] = {0, 0, 0}; + float SelfTest[6]; + // Stores the 16-bit signed accelerometer sensor output + int16_t accelCount[3]; + + public: + void getMres(); + void getGres(); + void getAres(); + void readAccelData(int16_t *); + void readGyroData(int16_t *); + void readMagData(int16_t *); + int16_t readTempData(); + void updateTime(); + void initAK8963(float *); + void initMPU9250(); + void calibrateMPU9250(float * gyroBias, float * accelBias); + void MPU9250SelfTest(float * destination); + void writeByte(uint8_t, uint8_t, uint8_t) __attribute__ ((deprecated)); + uint8_t readByte(uint8_t, uint8_t) __attribute__ ((deprecated)); + void readBytes(uint8_t, uint8_t, uint8_t, uint8_t *) __attribute__ ((deprecated)); + }; // class MPU9250 #endif // _MPU9250_H_ diff --git a/src/utility/Power.cpp b/src/utility/Power.cpp index 3c6949e..1d3959c 100644 --- a/src/utility/Power.cpp +++ b/src/utility/Power.cpp @@ -11,282 +11,254 @@ #include // ================ Power IC IP5306 =================== -#define IP5306_ADDR (117) // 0x75 -#define IP5306_REG_SYS_CTL0 (0x00) -#define IP5306_REG_SYS_CTL1 (0x01) -#define IP5306_REG_READ0 (0x70) -#define IP5306_REG_READ1 (0x71) -#define IP5306_REG_READ3 (0x78) +#define IP5306_ADDR (117) // 0x75 +#define IP5306_REG_SYS_CTL0 (0x00) +#define IP5306_REG_SYS_CTL1 (0x01) +#define IP5306_REG_READ0 (0x70) +#define IP5306_REG_READ1 (0x71) +#define IP5306_REG_READ3 (0x78) //- REG_CTL0 -#define BOOST_ENABLET_BIT (0x20) -#define CHARGE_OUT_BIT (0x10) -#define BOOT_ON_LOAD_BIT (0x04) -#define BOOST_OUT_BIT (0x02) +#define BOOST_ENABLET_BIT (0x20) +#define CHARGE_OUT_BIT (0x10) +#define BOOT_ON_LOAD_BIT (0x04) +#define BOOST_OUT_BIT (0x02) //- REG_CTL1 -#define BOOST_SET_BIT (0x80) -#define WLED_SET_BIT (0x40) -#define BOOST_ENABLE_BIT (0x20) -#define VIN_ENABLE_BIT (0x04) +#define BOOST_SET_BIT (0x80) +#define WLED_SET_BIT (0x40) +#define BOOST_ENABLE_BIT (0x20) +#define VIN_ENABLE_BIT (0x04) //- REG_READ0 -#define CHARGE_ENABLE_BIT (0x08) +#define CHARGE_ENABLE_BIT (0x08) //- REG_READ1 -#define CHARGE_FULL_BIT (0x08) +#define CHARGE_FULL_BIT (0x08) //- REG_READ2 -#define LIGHT_LOAD_BIT (0x20) +#define LIGHT_LOAD_BIT (0x20) #define LOWPOWER_SHUTDOWN_BIT (0x01) extern M5Stack M5; -POWER::POWER() -{ +POWER::POWER() { } -void POWER::begin(){ - Wire.begin(21, 22); +void POWER::begin() { + Wire.begin(21, 22); } -static bool getI2CReg(uint8_t *result, uint8_t address, uint8_t *reg) -{ - return(M5.I2C.readByte(address,*reg,result)); +static bool getI2CReg(uint8_t *result, uint8_t address, uint8_t *reg) { + return (M5.I2C.readByte(address, *reg, result)); } -static bool setI2CReg(uint8_t address, uint8_t reg, uint8_t value) -{ - return(M5.I2C.writeByte(address,reg,value)); +static bool setI2CReg(uint8_t address, uint8_t reg, uint8_t value) { + return (M5.I2C.writeByte(address, reg, value)); } - bool POWER::setPowerBoostOnOff(bool en) { - uint8_t data; - if (M5.I2C.readByte(IP5306_ADDR,IP5306_REG_SYS_CTL1,&data)) { - return M5.I2C.writeByte(IP5306_ADDR, IP5306_REG_SYS_CTL1 - ,en ? (data | BOOST_SET_BIT) - : (data &(~BOOST_SET_BIT))); - } - return false; + uint8_t data; + if (M5.I2C.readByte(IP5306_ADDR, IP5306_REG_SYS_CTL1, &data) == true) { + return M5.I2C.writeByte(IP5306_ADDR, IP5306_REG_SYS_CTL1, en ? (data | BOOST_SET_BIT) : (data & (~BOOST_SET_BIT))); + } + return false; } - bool POWER::setPowerBoostSet(bool en) { - uint8_t data; - if (M5.I2C.readByte(IP5306_ADDR,IP5306_REG_SYS_CTL1,&data)) { - return M5.I2C.writeByte(IP5306_ADDR, IP5306_REG_SYS_CTL1 - ,en ? (data | BOOST_ENABLE_BIT) - : (data &(~BOOST_ENABLE_BIT))); - } - return false; + uint8_t data; + if (M5.I2C.readByte(IP5306_ADDR, IP5306_REG_SYS_CTL1, &data) == true) { + return M5.I2C.writeByte(IP5306_ADDR, IP5306_REG_SYS_CTL1, en ? (data | BOOST_ENABLE_BIT) : (data & (~BOOST_ENABLE_BIT))); + } + return false; } bool POWER::setPowerVin(bool en) { - uint8_t data; - if (M5.I2C.readByte(IP5306_ADDR,IP5306_REG_SYS_CTL1,&data)) { - return M5.I2C.writeByte(IP5306_ADDR, IP5306_REG_SYS_CTL1 - ,en ? (data | VIN_ENABLE_BIT) - : (data &(~VIN_ENABLE_BIT))); - } - return false; + uint8_t data; + if (M5.I2C.readByte(IP5306_ADDR, IP5306_REG_SYS_CTL1, &data) == true) { + return M5.I2C.writeByte(IP5306_ADDR, IP5306_REG_SYS_CTL1, en ? (data | VIN_ENABLE_BIT) : (data & (~VIN_ENABLE_BIT))); + } + return false; } - bool POWER::setPowerWLEDSet(bool en) { - uint8_t data; - if (M5.I2C.readByte(IP5306_ADDR,IP5306_REG_SYS_CTL1,&data)) { - return M5.I2C.writeByte(IP5306_ADDR, IP5306_REG_SYS_CTL1 - ,en ? (data | WLED_SET_BIT) - : (data &(~WLED_SET_BIT))); - } - return false; + uint8_t data; + if (M5.I2C.readByte(IP5306_ADDR, IP5306_REG_SYS_CTL1, &data) == true) { + return M5.I2C.writeByte(IP5306_ADDR, IP5306_REG_SYS_CTL1, en ? (data | WLED_SET_BIT) : (data & (~WLED_SET_BIT))); + } + return false; } - - /* - default: false - false: when the current is too small, ip5306 will automatically shut down + default: false + false: when the current is too small, ip5306 will automatically shut down */ bool POWER::setKeepLightLoad(bool en) { - uint8_t data; - if (M5.I2C.readByte(IP5306_ADDR,IP5306_REG_SYS_CTL0,&data)) { - return M5.I2C.writeByte(IP5306_ADDR, IP5306_REG_SYS_CTL0 - ,!en ? (data | LIGHT_LOAD_BIT) - : (data &(~LIGHT_LOAD_BIT))); - } - return false; + uint8_t data; + if (M5.I2C.readByte(IP5306_ADDR, IP5306_REG_SYS_CTL0, &data) == true) { + return M5.I2C.writeByte(IP5306_ADDR, IP5306_REG_SYS_CTL0, !en ? (data | LIGHT_LOAD_BIT) : (data & (~LIGHT_LOAD_BIT))); + } + return false; } // true: Output normally open bool POWER::setPowerBoostKeepOn(bool en) { - uint8_t data; - if (M5.I2C.readByte(IP5306_ADDR,IP5306_REG_SYS_CTL0,&data)) { - return M5.I2C.writeByte(IP5306_ADDR, IP5306_REG_SYS_CTL0 - ,en ? (data | BOOST_OUT_BIT) - : (data &(~BOOST_OUT_BIT))); - } - return false; + uint8_t data; + if (M5.I2C.readByte(IP5306_ADDR, IP5306_REG_SYS_CTL0, &data) == true) { + return M5.I2C.writeByte(IP5306_ADDR, IP5306_REG_SYS_CTL0, en ? (data | BOOST_OUT_BIT) : (data & (~BOOST_OUT_BIT))); + } + return false; } // true: if come low battery , the system going shutdown bool POWER::setLowPowerShutdown(bool en) { - uint8_t data; - if (M5.I2C.readByte(IP5306_ADDR,IP5306_REG_SYS_CTL1,&data)) { - return M5.I2C.writeByte(IP5306_ADDR, IP5306_REG_SYS_CTL1 - ,en ? (data | LOWPOWER_SHUTDOWN_BIT) - : (data &(~LOWPOWER_SHUTDOWN_BIT))); - } - return false; + uint8_t data; + if (M5.I2C.readByte(IP5306_ADDR, IP5306_REG_SYS_CTL1, &data) == true) { + return M5.I2C.writeByte(IP5306_ADDR, IP5306_REG_SYS_CTL1, en ? (data | LOWPOWER_SHUTDOWN_BIT) : (data & (~LOWPOWER_SHUTDOWN_BIT))); + } + return false; } /* - default: true - true: If enough load is connected, the power will turn on. + default: true + true: If enough load is connected, the power will turn on. */ bool POWER::setAutoBootOnLoad(bool en) { - uint8_t data; - if (M5.I2C.readByte(IP5306_ADDR,IP5306_REG_SYS_CTL0,&data)) { - return M5.I2C.writeByte(IP5306_ADDR, IP5306_REG_SYS_CTL0 - ,en ? (data | BOOT_ON_LOAD_BIT) - : (data &(~BOOT_ON_LOAD_BIT))); - } - return false; + uint8_t data; + if (M5.I2C.readByte(IP5306_ADDR, IP5306_REG_SYS_CTL0, &data) == true) { + return M5.I2C.writeByte(IP5306_ADDR, IP5306_REG_SYS_CTL0, en ? (data | BOOT_ON_LOAD_BIT) : (data & (~BOOT_ON_LOAD_BIT))); + } + return false; } // if charge full,try set charge enable->disable->enable,can be recharged -bool POWER::setCharge(bool en){ - uint8_t data; - if (M5.I2C.readByte(IP5306_ADDR,IP5306_REG_SYS_CTL0,&data)) { - return M5.I2C.writeByte(IP5306_ADDR, IP5306_REG_SYS_CTL0 - ,en ? (data | CHARGE_OUT_BIT) - : (data &(~CHARGE_OUT_BIT))); - } - return false; +bool POWER::setCharge(bool en) { + uint8_t data; + if (M5.I2C.readByte(IP5306_ADDR, IP5306_REG_SYS_CTL0, &data) == true) { + return M5.I2C.writeByte(IP5306_ADDR, IP5306_REG_SYS_CTL0, en ? (data | CHARGE_OUT_BIT) : (data & (~CHARGE_OUT_BIT))); + } + return false; } // full return true, else return false -bool POWER::isChargeFull(){ - uint8_t data; - return (M5.I2C.readByte(IP5306_ADDR, IP5306_REG_READ1,&data)) +bool POWER::isChargeFull() { + uint8_t data; + return (M5.I2C.readByte(IP5306_ADDR, IP5306_REG_READ1, &data)) ? (data & CHARGE_FULL_BIT) : false; } // test if ip5306 is an i2c version -bool POWER::canControl(){ - return M5.I2C.writeCommand(IP5306_ADDR,IP5306_REG_READ0); +bool POWER::canControl() { + return M5.I2C.writeCommand(IP5306_ADDR, IP5306_REG_READ0); } //true:charge, false:discharge -bool POWER::isCharging(){ - uint8_t data; - return (M5.I2C.readByte(IP5306_ADDR, IP5306_REG_READ0,&data)) +bool POWER::isCharging() { + uint8_t data; + return (M5.I2C.readByte(IP5306_ADDR, IP5306_REG_READ0, &data)) ? (data & CHARGE_ENABLE_BIT) : false; } // Return percentage * 100 int8_t POWER::getBatteryLevel() { - uint8_t data; - if (M5.I2C.readByte(IP5306_ADDR, IP5306_REG_READ3,&data)) { - switch (data & 0xF0) { - case 0x00: return 100; - case 0x80: return 75; - case 0xC0: return 50; - case 0xE0: return 25; - default: return 0; - } + uint8_t data; + if (M5.I2C.readByte(IP5306_ADDR, IP5306_REG_READ3, &data) == true) { + switch (data & 0xF0) { + case 0x00: + return 100; + case 0x80: + return 75; + case 0xC0: + return 50; + case 0xE0: + return 25; + default: + return 0; } - return -1; + } + return -1; } void POWER::setWakeupButton(uint8_t button) { - _wakeupPin = button; + _wakeupPin = button; } void POWER::reset() { - - esp_restart(); + esp_restart(); } -bool POWER::isResetbySoftware() -{ - RESET_REASON reset_reason=rtc_get_reset_reason(0); - return( reset_reason==SW_RESET || - reset_reason==SW_CPU_RESET); +bool POWER::isResetbySoftware() { + RESET_REASON reset_reason = rtc_get_reset_reason(0); + return (reset_reason == SW_RESET || + reset_reason == SW_CPU_RESET); } -bool POWER::isResetbyWatchdog() -{ - RESET_REASON reset_reason=rtc_get_reset_reason(0); - return( reset_reason==TG0WDT_SYS_RESET || - reset_reason==TG1WDT_SYS_RESET || - reset_reason==OWDT_RESET || - reset_reason==RTCWDT_CPU_RESET || - reset_reason==RTCWDT_RTC_RESET || - reset_reason==TGWDT_CPU_RESET ); +bool POWER::isResetbyWatchdog() { + RESET_REASON reset_reason = rtc_get_reset_reason(0); + return (reset_reason == TG0WDT_SYS_RESET || + reset_reason == TG1WDT_SYS_RESET || + reset_reason == OWDT_RESET || + reset_reason == RTCWDT_CPU_RESET || + reset_reason == RTCWDT_RTC_RESET || + reset_reason == TGWDT_CPU_RESET); } -bool POWER::isResetbyDeepsleep() -{ - RESET_REASON reset_reason=rtc_get_reset_reason(0); - return( reset_reason==DEEPSLEEP_RESET); +bool POWER::isResetbyDeepsleep() { + RESET_REASON reset_reason = rtc_get_reset_reason(0); + return (reset_reason == DEEPSLEEP_RESET); } -bool POWER::isResetbyPowerSW() -{ - RESET_REASON reset_reason=rtc_get_reset_reason(0); - return(reset_reason==POWERON_RESET); +bool POWER::isResetbyPowerSW() { + RESET_REASON reset_reason = rtc_get_reset_reason(0); + return (reset_reason == POWERON_RESET); } -void POWER::deepSleep(uint64_t time_in_us){ +void POWER::deepSleep(uint64_t time_in_us) { - #ifdef M5STACK_FIRE - // Keep power keep boost on - setPowerBoostKeepOn(true); - #endif +#ifdef M5STACK_FIRE + // Keep power keep boost on + setPowerBoostKeepOn(true); +#endif - // power off the Lcd - M5.Lcd.setBrightness(0); - M5.Lcd.sleep(); + // power off the Lcd + M5.Lcd.setBrightness(0); + M5.Lcd.sleep(); - // ESP32 into deep sleep - esp_sleep_enable_ext0_wakeup((gpio_num_t)_wakeupPin , LOW); + // ESP32 into deep sleep + esp_sleep_enable_ext0_wakeup((gpio_num_t)_wakeupPin, LOW); - while(digitalRead(_wakeupPin) == LOW) { - delay(10); - } + while (digitalRead(_wakeupPin) == LOW) { + delay(10); + } - (time_in_us==0)?esp_deep_sleep_start():esp_deep_sleep(time_in_us); + (time_in_us == 0) ? esp_deep_sleep_start() : esp_deep_sleep(time_in_us); } -void POWER::lightSleep(uint64_t time_in_us){ +void POWER::lightSleep(uint64_t time_in_us) { - #ifdef M5STACK_FIRE - // Keep power keep boost on - setPowerBoostKeepOn(true); - #endif +#ifdef M5STACK_FIRE + // Keep power keep boost on + setPowerBoostKeepOn(true); +#endif - // power off the Lcd - M5.Lcd.setBrightness(0); - M5.Lcd.sleep(); + // power off the Lcd + M5.Lcd.setBrightness(0); + M5.Lcd.sleep(); - // ESP32 into deep sleep - esp_sleep_enable_ext0_wakeup((gpio_num_t)_wakeupPin , LOW); - esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH,ESP_PD_OPTION_AUTO); + // ESP32 into deep sleep + esp_sleep_enable_ext0_wakeup((gpio_num_t)_wakeupPin, LOW); + esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_AUTO); - while(digitalRead(_wakeupPin) == LOW) { - delay(10); - } - if(time_in_us>0){ - esp_sleep_enable_timer_wakeup(time_in_us); - } - esp_light_sleep_start(); + while (digitalRead(_wakeupPin) == LOW) { + delay(10); + } + if (time_in_us > 0) { + esp_sleep_enable_timer_wakeup(time_in_us); + } + esp_light_sleep_start(); - // power on the Lcd - M5.Lcd.wakeup(); - M5.Lcd.setBrightness(200); + // power on the Lcd + M5.Lcd.wakeup(); + M5.Lcd.setBrightness(200); } - - diff --git a/src/utility/Power.h b/src/utility/Power.h index 78d23fe..f998cad 100644 --- a/src/utility/Power.h +++ b/src/utility/Power.h @@ -6,53 +6,50 @@ * https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html * *----------------------------------------------------------------------*/ #ifndef Power_h -#define Power_h -#include -#include + #define Power_h + #include + #include -class POWER -{ - public: - POWER(); - bool canControl(); - void begin(); - - // -- control for power - bool setKeepLightLoad(bool en); - bool setPowerBoostKeepOn(bool en); - bool setAutoBootOnLoad(bool en); - bool setLowPowerShutdown(bool en); - bool setPowerBoostOnOff(bool en); - bool setPowerBoostSet(bool en); - bool setPowerVin(bool en); - bool setPowerWLEDSet(bool en); - - // -- control for battery - bool setCharge(bool en); - bool isChargeFull(); - bool isCharging(); - int8_t getBatteryLevel(); - bool batteryMode(bool en); - - // -- configuration for wakeup - void setWakeupButton(uint8_t button); - - // -- get resson for startup - bool isResetbyWatchdog(); - bool isResetbyDeepsleep(); - bool isResetbySoftware(); - bool isResetbyPowerSW(); - - // -- sleep - void deepSleep(uint64_t time_in_us=0); - void lightSleep(uint64_t time_in_us=0); + class POWER { + public: + POWER(); + bool canControl(); + void begin(); - // -- software reset - void reset(); + // -- control for power + bool setKeepLightLoad(bool en); + bool setPowerBoostKeepOn(bool en); + bool setAutoBootOnLoad(bool en); + bool setLowPowerShutdown(bool en); + bool setPowerBoostOnOff(bool en); + bool setPowerBoostSet(bool en); + bool setPowerVin(bool en); + bool setPowerWLEDSet(bool en); + // -- control for battery + bool setCharge(bool en); + bool isChargeFull(); + bool isCharging(); + int8_t getBatteryLevel(); + bool batteryMode(bool en); + // -- configuration for wakeup + void setWakeupButton(uint8_t button); - private: - uint8_t _wakeupPin; -}; + // -- get resson for startup + bool isResetbyWatchdog(); + bool isResetbyDeepsleep(); + bool isResetbySoftware(); + bool isResetbyPowerSW(); + + // -- sleep + void deepSleep(uint64_t time_in_us=0); + void lightSleep(uint64_t time_in_us=0); + + // -- software reset + void reset(); + + private: + uint8_t _wakeupPin; + }; #endif diff --git a/src/utility/Speaker.cpp b/src/utility/Speaker.cpp index c187a8c..56e8a75 100644 --- a/src/utility/Speaker.cpp +++ b/src/utility/Speaker.cpp @@ -1,75 +1,75 @@ #include "Speaker.h" SPEAKER::SPEAKER(void) { - _volume = 8; + _volume = 8; } void SPEAKER::begin() { - ledcSetup(TONE_PIN_CHANNEL, 0, 13); - ledcAttachPin(SPEAKER_PIN, TONE_PIN_CHANNEL); - // digitalWrite(SPEAKER_PIN, 0); - setBeep(1000, 100); + ledcSetup(TONE_PIN_CHANNEL, 0, 13); + ledcAttachPin(SPEAKER_PIN, TONE_PIN_CHANNEL); + // digitalWrite(SPEAKER_PIN, 0); + setBeep(1000, 100); } void SPEAKER::end() { - ledcDetachPin(SPEAKER_PIN); + ledcDetachPin(SPEAKER_PIN); } void SPEAKER::tone(uint16_t frequency) { - ledcWriteTone(TONE_PIN_CHANNEL, frequency); + ledcWriteTone(TONE_PIN_CHANNEL, frequency); } void SPEAKER::tone(uint16_t frequency, uint32_t duration) { - tone(frequency); - _count = millis() + duration; - speaker_on = 1; + tone(frequency); + _count = millis() + duration; + speaker_on = 1; } void SPEAKER::beep() { - tone(_beep_freq, _beep_duration); + tone(_beep_freq, _beep_duration); } void SPEAKER::setBeep(uint16_t frequency, uint16_t duration) { - _beep_freq = frequency; - _beep_duration = duration; + _beep_freq = frequency; + _beep_duration = duration; } void SPEAKER::setVolume(uint8_t volume) { - _volume = 11 - volume; + _volume = 11 - volume; } void SPEAKER::mute() { - ledcWriteTone(TONE_PIN_CHANNEL, 0); - digitalWrite(SPEAKER_PIN, 0); + ledcWriteTone(TONE_PIN_CHANNEL, 0); + digitalWrite(SPEAKER_PIN, 0); } void SPEAKER::update() { - if(speaker_on) { - if(millis() > _count) { - speaker_on = 0; - mute(); - } + if(speaker_on) { + if(millis() > _count) { + speaker_on = 0; + mute(); } + } } void SPEAKER::write(uint8_t value) { - dacWrite(SPEAKER_PIN, value); + dacWrite(SPEAKER_PIN, value); } void SPEAKER::playMusic(const uint8_t* music_data, uint16_t sample_rate) { - uint32_t length = strlen((char*)music_data); - uint16_t delay_interval = ((uint32_t)1000000/sample_rate); - if(_volume != 11) { - for(int i=0; i=0; t--) { - dacWrite(SPEAKER_PIN, t); - delay(2); - } + uint32_t length = strlen((char*)music_data); + uint16_t delay_interval = ((uint32_t)1000000 / sample_rate); + if(_volume != 11) { + for(int i = 0; i < length; i++) { + dacWrite(SPEAKER_PIN, music_data[i] / _volume); + delayMicroseconds(delay_interval); } - // ledcSetup(TONE_PIN_CHANNEL, 0, 13); - ledcAttachPin(SPEAKER_PIN, TONE_PIN_CHANNEL); + + for(int t = music_data[length - 1] / _volume; t >= 0; t--) { + dacWrite(SPEAKER_PIN, t); + delay(2); + } + } + // ledcSetup(TONE_PIN_CHANNEL, 0, 13); + ledcAttachPin(SPEAKER_PIN, TONE_PIN_CHANNEL); } diff --git a/src/utility/Speaker.h b/src/utility/Speaker.h index daf3893..6935c3c 100644 --- a/src/utility/Speaker.h +++ b/src/utility/Speaker.h @@ -1,36 +1,40 @@ #ifndef _SPEAKER_H_ -#define _SPEAKER_H_ + #define _SPEAKER_H_ -#include "Arduino.h" -#include "Config.h" + #include "Arduino.h" + #include "Config.h" -extern "C" { -#include "esp32-hal-dac.h" -} + #ifdef __cplusplus + extern "C" + { + #endif /* __cplusplus */ + #include "esp32-hal-dac.h" + #ifdef __cplusplus + } + #endif /* __cplusplus */ -class SPEAKER { -public: - SPEAKER(void); - - void begin(); - void end(); - void mute(); - void tone(uint16_t frequency); - void tone(uint16_t frequency, uint32_t duration); - void beep(); - void setBeep(uint16_t frequency, uint16_t duration); - void update(); - - void write(uint8_t value); - void setVolume(uint8_t volume); - void playMusic(const uint8_t* music_data, uint16_t sample_rate); + class SPEAKER { + public: + SPEAKER(void); -private: - uint32_t _count; - uint8_t _volume; - uint16_t _beep_duration; - uint16_t _beep_freq; - bool speaker_on; -}; + void begin(); + void end(); + void mute(); + void tone(uint16_t frequency); + void tone(uint16_t frequency, uint32_t duration); + void beep(); + void setBeep(uint16_t frequency, uint16_t duration); + void update(); -#endif \ No newline at end of file + void write(uint8_t value); + void setVolume(uint8_t volume); + void playMusic(const uint8_t *music_data, uint16_t sample_rate); + + private: + uint32_t _count; + uint8_t _volume; + uint16_t _beep_duration; + uint16_t _beep_freq; + bool speaker_on; + }; +#endif diff --git a/src/utility/Sprite.cpp b/src/utility/Sprite.cpp index 5ec65fb..a352ef3 100644 --- a/src/utility/Sprite.cpp +++ b/src/utility/Sprite.cpp @@ -14,13 +14,12 @@ ** Function name: TFT_eSprite ** Description: Class constructor *************************************************************************************x*/ -TFT_eSprite::TFT_eSprite(TFT_eSPI *tft) -{ +TFT_eSprite::TFT_eSprite(TFT_eSPI *tft) { _tft = tft; // Pointer to tft class so we can call member functions _iwidth = 0; // Initialise width and height to 0 (it does not exist yet) _iheight = 0; - _bpp = 16; + _bpp = 16; _iswapBytes = false; // Do not swap pushImage colour bytes by default _created = false; @@ -45,13 +44,14 @@ TFT_eSprite::TFT_eSprite(TFT_eSPI *tft) ** Description: Create a sprite (bitmap) of defined width and height *************************************************************************************x*/ // cast returned value to (uint8_t*) for 8 bit or (uint16_t*) for 16 bit colours -void* TFT_eSprite::createSprite(int16_t w, int16_t h, uint8_t frames) -{ - - if ( _created ) return _img8_1; - - if ( w < 1 || h < 1 ) return NULL; +void* TFT_eSprite::createSprite(int16_t w, int16_t h, uint8_t frames) { + if (_created) { + return _img8_1; + } + if (w < 1 || h < 1) { + return NULL; + } _iwidth = _dwidth = _bitwidth = w; _iheight = _dheight = h; @@ -65,8 +65,8 @@ void* TFT_eSprite::createSprite(int16_t w, int16_t h, uint8_t frames) _sh = h; _scolor = TFT_BLACK; - _xpivot = w/2; - _ypivot = h/2; + _xpivot = w / 2; + _ypivot = h / 2; _img8 = (uint8_t*) callocSprite(w, h, frames); _img8_1 = _img8; @@ -75,14 +75,12 @@ void* TFT_eSprite::createSprite(int16_t w, int16_t h, uint8_t frames) // This is to make it clear what pointer size is expected to be used // but casting in the user sketch is needed due to the use of void* - if (_bpp == 1) - { - w = (w+7) & 0xFFF8; - _img8_2 = _img8 + ( (w>>3) * h + 1 ); + if (_bpp == 1) { + w = (w + 7) & 0xFFF8; + _img8_2 = _img8 + ( (w >> 3) * h + 1 ); } - if (_img8) - { + if (_img8) { _created = true; return _img8; } @@ -96,51 +94,59 @@ void* TFT_eSprite::createSprite(int16_t w, int16_t h, uint8_t frames) ** Description: Allocate a memory area for the Sprite and return pointer *************************************************************************************x*/ -void* TFT_eSprite::callocSprite(int16_t w, int16_t h, uint8_t frames) -{ +void* TFT_eSprite::callocSprite(int16_t w, int16_t h, uint8_t frames) { // Add one extra "off screen" pixel to point out-of-bounds setWindow() coordinates // this means push/writeColor functions do not need additional bounds checks and // hence will run faster in normal circumstances. uint8_t* ptr8 = NULL; - if (_bpp == 16) - { + if (_bpp == 16) { -#if defined (ESP32) && defined (CONFIG_SPIRAM_SUPPORT) - if ( psramFound() ) ptr8 = ( uint8_t*) ps_calloc(w * h + 1, sizeof(uint16_t)); - else -#endif - ptr8 = ( uint8_t*) calloc(w * h + 1, sizeof(uint16_t)); - } - - else if (_bpp == 8) - { -#if defined (ESP32) && defined (CONFIG_SPIRAM_SUPPORT) - if ( psramFound() ) ptr8 = ( uint8_t*) ps_calloc(w * h + 1, sizeof(uint8_t)); - else -#endif - ptr8 = ( uint8_t*) calloc(w * h + 1, sizeof(uint8_t)); - } - - else // Must be 1 bpp - { - //_dwidth Display width+height in pixels always in rotation 0 orientation - //_dheight Not swapped for sprite rotations + #if defined (ESP32) && defined (CONFIG_SPIRAM_SUPPORT) + if (psramFound()) { + ptr8 = (uint8_t *)ps_calloc(w * h + 1, sizeof(uint16_t)); + } else { + #else + { + #endif + ptr8 = (uint8_t*) calloc(w * h + 1, sizeof(uint16_t)); + } + } else if (_bpp == 8) { + #if defined (ESP32) && defined (CONFIG_SPIRAM_SUPPORT) + if (psramFound()) { + ptr8 = (uint8_t*) ps_calloc(w * h + 1, sizeof(uint8_t)); + } else { + #else + { + #endif + ptr8 = (uint8_t*) calloc(w * h + 1, sizeof(uint8_t)); + } + } else { + // Must be 1 bpp + // _dwidth Display width+height in pixels always in rotation 0 orientation + // _dheight Not swapped for sprite rotations // Note: for 1bpp _iwidth and _iheight are swapped during Sprite rotations w = (w+7) & 0xFFF8; // width should be the multiple of 8 bits to be compatible with epdpaint _iwidth = w; // _iwidth is rounded up to be multiple of 8, so might not be = _dwidth _bitwidth = w; - if (frames > 2) frames = 2; // Currently restricted to 2 frame buffers - if (frames < 1) frames = 1; -#if defined (ESP32) && defined (CONFIG_SPIRAM_SUPPORT) - if ( psramFound() ) ptr8 = ( uint8_t*) ps_calloc(frames * (w>>3) * h + frames, sizeof(uint8_t)); - else -#endif - ptr8 = ( uint8_t*) calloc(frames * (w>>3) * h + frames, sizeof(uint8_t)); + if (frames > 2) { + frames = 2; // Currently restricted to 2 frame buffers + } + if (frames < 1) { + frames = 1; + } + #if defined (ESP32) && defined (CONFIG_SPIRAM_SUPPORT) + if (psramFound()) { + ptr8 = (uint8_t*) ps_calloc(frames * (w >> 3) * h + frames, sizeof(uint8_t)); + } else{ + #else + { + #endif + ptr8 = (uint8_t*) calloc(frames * (w >> 3) * h + frames, sizeof(uint8_t)); + } } - return ptr8; } @@ -149,8 +155,7 @@ void* TFT_eSprite::callocSprite(int16_t w, int16_t h, uint8_t frames) ** Description: For 1 bpp Sprites, select the frame used for graphics *************************************************************************************x*/ // Frames are numbered 1 and 2 -void* TFT_eSprite::frameBuffer(int8_t f) -{ +void* TFT_eSprite::frameBuffer(int8_t f) { if (!_created) return NULL; if (_bpp == 16) return _img; @@ -168,19 +173,21 @@ void* TFT_eSprite::frameBuffer(int8_t f) ** Description: Set bits per pixel for colour (1, 8 or 16) *************************************************************************************x*/ -void* TFT_eSprite::setColorDepth(int8_t b) -{ +void* TFT_eSprite::setColorDepth(int8_t b) { // Can't change an existing sprite's colour depth so delete it - if (_created) free(_img8_1); - + if (_created) { + free(_img8_1); + } // Now define the new colour depth - if ( b > 8 ) _bpp = 16; // Bytes per pixel - else if ( b > 1 ) _bpp = 8; - else _bpp = 1; - + if (b > 8) { + _bpp = 16; // Bytes per pixel + } else if (b > 1) { + _bpp = 8; + } else { + _bpp = 1; + } // If it existed, re-create the sprite with the new colour depth - if (_created) - { + if (_created) { _created = false; return createSprite(_iwidth, _iheight); } @@ -194,10 +201,12 @@ void* TFT_eSprite::setColorDepth(int8_t b) ** Description: Get bits per pixel for colour (1, 8 or 16) *************************************************************************************x*/ -int8_t TFT_eSprite::getColorDepth(void) -{ - if (_created) return _bpp; - else return 0; +int8_t TFT_eSprite::getColorDepth(void) { + if (_created) { + return _bpp; + } else { + return 0; + } } @@ -205,9 +214,10 @@ int8_t TFT_eSprite::getColorDepth(void) ** Function name: setBitmapColor ** Description: Set the foreground foreground and background colour ***************************************************************************************/ -void TFT_eSprite::setBitmapColor(uint16_t c, uint16_t b) -{ - if (c == b) b = ~c; +void TFT_eSprite::setBitmapColor(uint16_t c, uint16_t b) { + if (c == b) { + b = ~c; + } _tft->bitmap_fg = c; _tft->bitmap_bg = b; } @@ -217,12 +227,11 @@ void TFT_eSprite::setBitmapColor(uint16_t c, uint16_t b) ** Function name: deleteSprite ** Description: Delete the sprite to free up memory (RAM) *************************************************************************************x*/ -void TFT_eSprite::deleteSprite(void) -{ - if (!_created ) return; - +void TFT_eSprite::deleteSprite(void) { + if (!_created) { + return; + } free(_img8_1); - _created = false; } @@ -231,8 +240,7 @@ void TFT_eSprite::deleteSprite(void) ** Function name: setPivot ** Description: Set the pivot point in this Sprite *************************************************************************************x*/ -void TFT_eSprite::setPivot(int16_t x, int16_t y) -{ +void TFT_eSprite::setPivot(int16_t x, int16_t y) { _xpivot = x; _ypivot = y; } @@ -242,8 +250,7 @@ void TFT_eSprite::setPivot(int16_t x, int16_t y) ** Function name: getPivotX ** Description: Get the x pivot position ***************************************************************************************/ -int16_t TFT_eSprite::getPivotX(void) -{ +int16_t TFT_eSprite::getPivotX(void) { return _xpivot; } @@ -252,8 +259,7 @@ int16_t TFT_eSprite::getPivotX(void) ** Function name: getPivotY ** Description: Get the y pivot position ***************************************************************************************/ -int16_t TFT_eSprite::getPivotY(void) -{ +int16_t TFT_eSprite::getPivotY(void) { return _ypivot; } @@ -262,9 +268,10 @@ int16_t TFT_eSprite::getPivotY(void) ** Function name: pushRotated ** Description: Push a rotated copy of the Sprite to TFT screen *************************************************************************************x*/ -bool TFT_eSprite::pushRotated(int16_t angle, int32_t transp) -{ - if ( !_created ) return false; +bool TFT_eSprite::pushRotated(int16_t angle, int32_t transp) { + if (!_created) { + return false; + } // Trig values for the rotation float radAngle = -angle * 0.0174532925; // Convert degrees to radians @@ -290,16 +297,33 @@ bool TFT_eSprite::pushRotated(int16_t angle, int32_t transp) // _tft->drawRect(min_x, min_y, max_x - min_x + 1, max_y - min_y + 1, TFT_GREEN); // Return if bounding box is outside of TFT area - if (min_x > _tft->width()) return true; - if (min_y > _tft->height()) return true; - if (max_x < 0) return true; - if (max_y < 0) return true; + if (min_x > _tft->width()) { + return true; + } + + if (min_y > _tft->height()) { + return true; + } + if (max_x < 0) { + return true; + } + if (max_y < 0) { + return true; + } // Clip bounding box to be within TFT area - if (min_x < 0) min_x = 0; - if (min_y < 0) min_y = 0; - if (max_x > _tft->width()) max_x = _tft->width(); - if (max_y > _tft->height()) max_y = _tft->height(); + if (min_x < 0) { + min_x = 0; + } + if (min_y < 0) { + min_y = 0; + } + if (max_x > _tft->width()) { + max_x = _tft->width(); + } + if (max_y > _tft->height()) { + max_y = _tft->height(); + } _tft->startWrite(); // ESP32: avoid transaction overhead for every tft pixel @@ -313,8 +337,7 @@ bool TFT_eSprite::pushRotated(int16_t angle, int32_t transp) int32_t yt = y - _tft->_ypivot; int32_t xs = (int32_t)round(cxt - sinra * yt); // Do not calculate ys unless xs is in bounds - if (xs >= 0 && xs < width()) - { + if (xs >= 0 && xs < width()) { int32_t ys = (int32_t)round(sxt + cosra * yt); // Check if ys is in bounds if (ys >= 0 && ys < height()) { @@ -322,8 +345,9 @@ bool TFT_eSprite::pushRotated(int16_t angle, int32_t transp) if (rp != transp) _tft->drawPixel(x, y, rp); column_drawn = true; } + } else if (column_drawn) { + y = max_y; // Skip remaining column pixels } - else if (column_drawn) y = max_y; // Skip remaining column pixels } } @@ -337,10 +361,13 @@ bool TFT_eSprite::pushRotated(int16_t angle, int32_t transp) ** Function name: pushRotated ** Description: Push a rotated copy of the Sprite to another Sprite *************************************************************************************x*/ -bool TFT_eSprite::pushRotated(TFT_eSprite *spr, int16_t angle, int32_t transp) -{ - if ( !_created ) return false; // Check this Sprite is created - if ( !spr->_created ) return false; // Ckeck destination Sprite is created +bool TFT_eSprite::pushRotated(TFT_eSprite *spr, int16_t angle, int32_t transp) { + if (!_created) { + return false; // Check this Sprite is created + } + if (!spr->_created) { + return false; // Ckeck destination Sprite is created + } // Trig values for the rotation float radAngle = -angle * 0.0174532925; // Convert degrees to radians @@ -367,41 +394,53 @@ bool TFT_eSprite::pushRotated(TFT_eSprite *spr, int16_t angle, int32_t transp) // spr->drawRect(min_x, min_y, max_x - min_x + 1, max_y - min_y + 1, TFT_GREEN); // Return if bounding box is completely outside of destination Sprite - if (min_x > spr->width()) return true; - if (min_y > spr->height()) return true; - if (max_x < 0) return true; - if (max_y < 0) return true; - + if (min_x > spr->width()) { + return true; + } + if (min_y > spr->height()) { + return true; + } + if (max_x < 0) { + return true; + } + if (max_y < 0) { + return true; + } // Clip bounding box if it is partially within destination Sprite - if (min_x < 0) min_x = 0; - if (min_y < 0) min_y = 0; - if (max_x > spr->width()) max_x = spr->width(); - if (max_y > spr->height()) max_y = spr->height(); - + if (min_x < 0) { + min_x = 0; + } + if (min_y < 0) { + min_y = 0; + } + if (max_x > spr->width()) { + max_x = spr->width(); + } + if (max_y > spr->height()) { + max_y = spr->height(); + } // Scan destination bounding box and fetch transformed pixels from source Sprite - for (int32_t x = min_x; x <= max_x; x++) - { + for (int32_t x = min_x; x <= max_x; x++) { int32_t xt = x - spr->_xpivot; float cxt = cosra * xt + _xpivot; float sxt = sinra * xt + _ypivot; bool column_drawn = false; - for (int32_t y = min_y; y <= max_y; y++) - { + for (int32_t y = min_y; y <= max_y; y++) { int32_t yt = y - spr->_ypivot; int32_t xs = (int32_t)round(cxt - sinra * yt); // Do not calculate ys unless xs is in bounds - if (xs >= 0 && xs < width()) - { + if (xs >= 0 && xs < width()) { int32_t ys = (int32_t)round(sxt + cosra * yt); // Check if ys is in bounds - if (ys >= 0 && ys < height()) - { + if (ys >= 0 && ys < height()) { int32_t rp = readPixel(xs, ys); if (rp != transp) spr->drawPixel(x, y, rp); column_drawn = true; } } - else if (column_drawn) y = max_y; // Skip the remaining pixels below the Sprite + else if (column_drawn) { + y = max_y; // Skip the remaining pixels below the Sprite + } } } @@ -414,8 +453,7 @@ bool TFT_eSprite::pushRotated(TFT_eSprite *spr, int16_t angle, int32_t transp) ** Description: Get bounding box of a rotated Sprite wrt pivot *************************************************************************************x*/ void TFT_eSprite::getRotatedBounds(float sina, float cosa, int16_t w, int16_t h, int16_t xp, int16_t yp, - int16_t *min_x, int16_t *min_y, int16_t *max_x, int16_t *max_y) -{ + int16_t *min_x, int16_t *min_y, int16_t *max_x, int16_t *max_y) { w -= xp; // w is now right edge coordinate relative to xp h -= yp; // h is now bottom edge coordinate relative to yp @@ -434,25 +472,48 @@ void TFT_eSprite::getRotatedBounds(float sina, float cosa, int16_t w, int16_t h, // Find bounding box extremes, enlarge box to accomodate rounding errors *min_x = x0-2; - if (x1 < *min_x) *min_x = x1-2; - if (x2 < *min_x) *min_x = x2-2; - if (x3 < *min_x) *min_x = x3-2; + if (x1 < *min_x) { + *min_x = x1-2; + } + if (x2 < *min_x) { + *min_x = x2-2; + } + if (x3 < *min_x) { + *min_x = x3-2; + } *max_x = x0+2; - if (x1 > *max_x) *max_x = x1+2; - if (x2 > *max_x) *max_x = x2+2; - if (x3 > *max_x) *max_x = x3+2; + if (x1 > *max_x) { + *max_x = x1+2; + } + if (x2 > *max_x) { + *max_x = x2+2; + } + if (x3 > *max_x) { + *max_x = x3+2; + } *min_y = y0-2; - if (y1 < *min_y) *min_y = y1-2; - if (y2 < *min_y) *min_y = y2-2; - if (y3 < *min_y) *min_y = y3-2; + if (y1 < *min_y) { + *min_y = y1-2; + } + if (y2 < *min_y) { + *min_y = y2-2; + } + if (y3 < *min_y) { + *min_y = y3-2; + } *max_y = y0+2; - if (y1 > *max_y) *max_y = y1+2; - if (y2 > *max_y) *max_y = y2+2; - if (y3 > *max_y) *max_y = y3+2; - + if (y1 > *max_y) { + *max_y = y1+2; + } + if (y2 > *max_y) { + *max_y = y2+2; + } + if (y3 > *max_y) { + *max_y = y3+2; + } } @@ -460,13 +521,16 @@ void TFT_eSprite::getRotatedBounds(float sina, float cosa, int16_t w, int16_t h, ** Function name: pushSprite ** Description: Push the sprite to the TFT at x, y *************************************************************************************x*/ -void TFT_eSprite::pushSprite(int32_t x, int32_t y) -{ - if (!_created) return; +void TFT_eSprite::pushSprite(int32_t x, int32_t y) { + if (!_created) { + return; + } - if (_bpp == 16) _tft->pushImage(x, y, _iwidth, _iheight, _img ); - - else _tft->pushImage(x, y, _dwidth, _dheight, _img8, (bool)(_bpp == 8)); + if (_bpp == 16) { + _tft->pushImage(x, y, _iwidth, _iheight, _img ); + } else { + _tft->pushImage(x, y, _dwidth, _dheight, _img8, (bool)(_bpp == 8)); + } } @@ -474,17 +538,18 @@ void TFT_eSprite::pushSprite(int32_t x, int32_t y) ** Function name: pushSprite ** Description: Push the sprite to the TFT at x, y with transparent colour *************************************************************************************x*/ -void TFT_eSprite::pushSprite(int32_t x, int32_t y, uint16_t transp) -{ - if (!_created) return; - - if (_bpp == 16) _tft->pushImage(x, y, _iwidth, _iheight, _img, transp ); - else if (_bpp == 8) - { - transp = (uint8_t)((transp & 0xE000)>>8 | (transp & 0x0700)>>6 | (transp & 0x0018)>>3); +void TFT_eSprite::pushSprite(int32_t x, int32_t y, uint16_t transp) { + if (!_created) { + return; + } + if (_bpp == 16) { + _tft->pushImage(x, y, _iwidth, _iheight, _img, transp ); + } else if (_bpp == 8) { + transp = (uint8_t)((transp & 0xE000) >> 8 | (transp & 0x0700) >> 6 | (transp & 0x0018) >> 3); _tft->pushImage(x, y, _dwidth, _dheight, _img8, (uint8_t)transp, (bool)true); + } else { + _tft->pushImage(x, y, _dwidth, _dheight, _img8, 0, (bool)false); } - else _tft->pushImage(x, y, _dwidth, _dheight, _img8, 0, (bool)false); } @@ -492,21 +557,19 @@ void TFT_eSprite::pushSprite(int32_t x, int32_t y, uint16_t transp) ** Function name: readPixel ** Description: Read 565 colour of a pixel at defined coordinates *************************************************************************************x*/ -uint16_t TFT_eSprite::readPixel(int32_t x, int32_t y) -{ - if ((x < 0) || (x >= _iwidth) || (y < 0) || (y >= _iheight) || !_created) return 0; +uint16_t TFT_eSprite::readPixel(int32_t x, int32_t y) { - if (_bpp == 16) - { + if ((x < 0) || (x >= _iwidth) || (y < 0) || (y >= _iheight) || !_created) { + return 0; + } + if (_bpp == 16) { uint16_t color = _img[x + y * _iwidth]; return (color >> 8) | (color << 8); } - if (_bpp == 8) - { + if (_bpp == 8) { uint16_t color = _img8[x + y * _iwidth]; - if (color != 0) - { + if (color != 0) { uint8_t blue[] = {0, 11, 21, 31}; color = (color & 0xE0)<<8 | (color & 0xC0)<<5 | (color & 0x1C)<<6 | (color & 0x1C)<<3 @@ -515,26 +578,20 @@ uint16_t TFT_eSprite::readPixel(int32_t x, int32_t y) return color; } - if (_rotation == 1) - { + if (_rotation == 1) { uint16_t tx = x; x = _dwidth - y - 1; y = tx; - } - else if (_rotation == 2) - { + } else if (_rotation == 2) { x = _dwidth - x - 1; y = _dheight - y - 1; - } - else if (_rotation == 3) - { + } else if (_rotation == 3) { uint16_t tx = x; x = y; y = _dheight - tx - 1; } - uint16_t color = (_img8[(x + y * _bitwidth)>>3] << (x & 0x7)) & 0x80; - + uint16_t color = (_img8[(x + y * _bitwidth) >> 3] << (x & 0x7)) & 0x80; return color >> 7; } @@ -543,11 +600,13 @@ uint16_t TFT_eSprite::readPixel(int32_t x, int32_t y) ** Function name: pushImage ** Description: push 565 colour image into a defined area of a sprite *************************************************************************************x*/ -void TFT_eSprite::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *data) -{ - if ((x >= _iwidth) || (y >= _iheight) || (w == 0) || (h == 0) || !_created) return; - if ((x + w < 0) || (y + h < 0)) return; - +void TFT_eSprite::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *data) { + if ((x >= _iwidth) || (y >= _iheight) || (w == 0) || (h == 0) || !_created) { + return; + } + if ((x + w < 0) || (y + h < 0)) { + return; + } int32_t xo = 0; int32_t yo = 0; @@ -557,59 +616,60 @@ void TFT_eSprite::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint16_ uint32_t ws = w; uint32_t hs = h; - if (x < 0) { xo = -x; xs = 0; } - if (y < 0) { yo = -y; ys = 0; } + if (x < 0) { + xo = -x; + xs = 0; + } + if (y < 0) { + yo = -y; + ys = 0; + } - if (xs + w >= _iwidth) ws = _iwidth - xs; - if (ys + h >= _iheight) hs = _iheight - ys; - - if (_bpp == 16) // Plot a 16 bpp image into a 16 bpp Sprite - { - for (uint32_t yp = yo; yp < yo + hs; yp++) - { + if (xs + w >= _iwidth) { + ws = _iwidth - xs; + } + if (ys + h >= _iheight) { + hs = _iheight - ys; + } + // Plot a 16 bpp image into a 16 bpp Sprite + if (_bpp == 16) { + for (uint32_t yp = yo; yp < yo + hs; yp++) { x = xs; - for (uint32_t xp = xo; xp < xo + ws; xp++) - { + for (uint32_t xp = xo; xp < xo + ws; xp++) { uint16_t color = data[xp + yp * w]; - if(!_iswapBytes) color = color<<8 | color>>8; + if (!_iswapBytes) { + color = color<<8 | color >> 8; + } _img[x + ys * _iwidth] = color; x++; } ys++; } - } - else if (_bpp == 8) // Plot a 16 bpp image into a 8 bpp Sprite - { - for (uint32_t yp = yo; yp < yo + hs; yp++) - { + } else if (_bpp == 8) { + // Plot a 16 bpp image into a 8 bpp Sprite + for (uint32_t yp = yo; yp < yo + hs; yp++) { x = xs; - for (uint32_t xp = xo; xp < xo + ws; xp++) - { + for (uint32_t xp = xo; xp < xo + ws; xp++) { uint16_t color = data[xp + yp * w]; - if(_iswapBytes) color = color<<8 | color>>8; - _img8[x + ys * _iwidth] = (uint8_t)((color & 0xE000)>>8 | (color & 0x0700)>>6 | (color & 0x0018)>>3); + if (_iswapBytes) { + color = color<<8 | color >> 8; + } + _img8[x + ys * _iwidth] = (uint8_t)((color & 0xE000) >> 8 | (color & 0x0700) >> 6 | (color & 0x0018) >> 3); x++; } ys++; } - } - - else // 1bpp - { + } else { + // 1bpp // Move coordinate rotation to support fn - if (_rotation == 1) - { + if (_rotation == 1) { int32_t tx = x; x = _dwidth - y - 1; y = tx; - } - else if (_rotation == 2) - { + } else if (_rotation == 2) { x = _dwidth - x - 1; y = _dheight - y - 1; - } - else if (_rotation == 3) - { + } else if (_rotation == 3) { int32_t tx = x; x = y; y = _dheight - tx - 1; @@ -617,13 +677,11 @@ void TFT_eSprite::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint16_ // Plot a 1bpp image into a 1bpp Sprite uint8_t* pdata = (uint8_t* ) data; uint32_t ww = (w+7) & 0xFFF8; - for (int32_t yp = 0; yp>3; + for (int32_t yp = 0; yp> 3; uint32_t yyp = y + yp; - for (int32_t xp = 0; xp>3) + yw] & (0x80 >> (xp & 0x7)) ); + for (int32_t xp = 0; xp> 3) + yw] & (0x80 >> (xp & 0x7)) ); drawPixel(x+xp, yyp, readPixel); } } @@ -635,98 +693,88 @@ void TFT_eSprite::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint16_ ** Function name: pushImage ** Description: push 565 colour FLASH (PROGMEM) image into a defined area *************************************************************************************x*/ -void TFT_eSprite::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, const uint16_t *data) -{ -#ifdef ESP32 - pushImage(x, y, w, h, (uint16_t*) data); -#else - // Partitioned memory FLASH processor - if ((x >= _iwidth) || (y >= _iheight) || (w == 0) || (h == 0) || !_created) return; - if ((x + w < 0) || (y + h < 0)) return; +void TFT_eSprite::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, const uint16_t *data) { + #ifdef ESP32 + pushImage(x, y, w, h, (uint16_t*) data); + #else + // Partitioned memory FLASH processor + if ((x >= _iwidth) || (y >= _iheight) || (w == 0) || (h == 0) || !_created) return; + if ((x + w < 0) || (y + h < 0)) return; - int32_t xo = 0; - int32_t yo = 0; + int32_t xo = 0; + int32_t yo = 0; - int32_t xs = x; - int32_t ys = y; + int32_t xs = x; + int32_t ys = y; - uint32_t ws = w; - uint32_t hs = h; + uint32_t ws = w; + uint32_t hs = h; - if (x < 0) { xo = -x; xs = 0; } - if (y < 0) { yo = -y; ys = 0; } + if (x < 0) { xo = -x; xs = 0; } + if (y < 0) { yo = -y; ys = 0; } - if (xs + w >= _iwidth) ws = _iwidth - xs; - if (ys + h >= _iheight) hs = _iheight - ys; + if (xs + w >= _iwidth) ws = _iwidth - xs; + if (ys + h >= _iheight) hs = _iheight - ys; - if (_bpp == 16) // Plot a 16 bpp image into a 16 bpp Sprite - { - for (uint32_t yp = yo; yp < yo + hs; yp++) - { - x = xs; - for (uint32_t xp = xo; xp < xo + ws; xp++) - { - uint16_t color = pgm_read_word(data + xp + yp * w); - if(!_iswapBytes) color = color<<8 | color>>8; - _img[x + ys * _iwidth] = color; - x++; + // Plot a 16 bpp image into a 16 bpp Sprite + if (_bpp == 16) { + for (uint32_t yp = yo; yp < yo + hs; yp++) { + x = xs; + for (uint32_t xp = xo; xp < xo + ws; xp++) { + uint16_t color = pgm_read_word(data + xp + yp * w); + if (!_iswapBytes) { + color = color<<8 | color >> 8; + } + _img[x + ys * _iwidth] = color; + x++; + } + ys++; } - ys++; } - } - - else if (_bpp == 8) // Plot a 16 bpp image into a 8 bpp Sprite - { - for (uint32_t yp = yo; yp < yo + hs; yp++) - { - x = xs; - for (uint32_t xp = xo; xp < xo + ws; xp++) - { - uint16_t color = pgm_read_word(data + xp + yp * w); - if(_iswapBytes) color = color<<8 | color>>8; - _img8[x + ys * _iwidth] = (uint8_t)((color & 0xE000)>>8 | (color & 0x0700)>>6 | (color & 0x0018)>>3); - x++; + // Plot a 16 bpp image into a 8 bpp Sprite + else if (_bpp == 8) { + for (uint32_t yp = yo; yp < yo + hs; yp++) { + x = xs; + for (uint32_t xp = xo; xp < xo + ws; xp++) { + uint16_t color = pgm_read_word(data + xp + yp * w); + if (_iswapBytes) { + color = color<<8 | color >> 8; + } + _img8[x + ys * _iwidth] = (uint8_t)((color & 0xE000) >> 8 | (color & 0x0700) >> 6 | (color & 0x0018) >> 3); + x++; + } + ys++; } - ys++; - } - } - - else // 1bpp - { - // Move coordinate rotation to support fn - if (_rotation == 1) - { - int32_t tx = x; - x = _dwidth - y - 1; - y = tx; - } - else if (_rotation == 2) - { - x = _dwidth - x - 1; - y = _dheight - y - 1; - } - else if (_rotation == 3) - { - int32_t tx = x; - x = y; - y = _dheight - tx - 1; - } - // Plot a 1bpp image into a 1bpp Sprite - const uint8_t* pdata = (const uint8_t* ) data; - uint32_t ww = (w+7) & 0xFFF8; - for (int32_t yp = 0; yp x1) swap_coord(x0, x1); - if (y0 > y1) swap_coord(y0, y1); + if (x0 > x1) { + swap_coord(x0, x1); + } + if (y0 > y1) { + swap_coord(y0, y1); + } - if (x0 < 0) x0 = 0; - if (x0 >= _iwidth) duff_coord = true; - if (x1 < 0) x1 = 0; - if (x1 >= _iwidth) x1 = _iwidth - 1; + if (x0 < 0) { + x0 = 0; + } + if (x0 >= _iwidth) { + duff_coord = true; + } + if (x1 < 0) { + x1 = 0; + } + if (x1 >= _iwidth) { + x1 = _iwidth - 1; + } - if (y0 < 0) y0 = 0; - if (y0 >= _iheight) duff_coord = true; - if (y1 < 0) y1 = 0; - if (y1 >= _iheight) y1 = _iheight - 1; + if (y0 < 0) { + y0 = 0; + } + if (y0 >= _iheight) { + duff_coord = true; + } + if (y1 < 0) { + y1 = 0; + } + if (y1 >= _iheight) { + y1 = _iheight - 1; + } - if (duff_coord) - { // Point to that extra "off screen" pixel + // Point to that extra "off screen" pixel + if (duff_coord) { _xs = 0; _ys = _iheight; _xe = 0; _ye = _iheight; - } - else - { + } else { _xs = x0; _ys = y0; _xe = x1; @@ -795,28 +858,28 @@ void TFT_eSprite::setWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1) ** Function name: pushColor ** Description: Send a new pixel to the set window *************************************************************************************x*/ -void TFT_eSprite::pushColor(uint32_t color) -{ +void TFT_eSprite::pushColor(uint32_t color) { if (!_created ) return; // Write the colour to RAM in set window - if (_bpp == 16) + if (_bpp == 16) { _img [_xptr + _yptr * _iwidth] = (uint16_t) (color >> 8) | (color << 8); - - else if (_bpp == 8) - _img8[_xptr + _yptr * _iwidth] = (uint8_t )((color & 0xE000)>>8 | (color & 0x0700)>>6 | (color & 0x0018)>>3); - - else drawPixel(_xptr, _yptr, color); + } else if (_bpp == 8) { + _img8[_xptr + _yptr * _iwidth] = (uint8_t )((color & 0xE000) >> 8 | (color & 0x0700) >> 6 | (color & 0x0018) >> 3); + } else { + drawPixel(_xptr, _yptr, color); + } // Increment x _xptr++; // Wrap on x and y to start, increment y if needed - if (_xptr > _xe) - { + if (_xptr > _xe) { _xptr = _xs; _yptr++; - if (_yptr > _ye) _yptr = _ys; + if (_yptr > _ye) { + _yptr = _ys; + } } } @@ -826,21 +889,22 @@ void TFT_eSprite::pushColor(uint32_t color) ** Function name: pushColor ** Description: Send a "len" new pixels to the set window *************************************************************************************x*/ -void TFT_eSprite::pushColor(uint32_t color, uint16_t len) -{ - if (!_created ) return; - +void TFT_eSprite::pushColor(uint32_t color, uint16_t len) { + if (!_created) { + return; + } uint16_t pixelColor; - if (_bpp == 16) + if (_bpp == 16) { pixelColor = (uint16_t) (color >> 8) | (color << 8); - - else if (_bpp == 8) - pixelColor = (color & 0xE000)>>8 | (color & 0x0700)>>6 | (color & 0x0018)>>3; - - else pixelColor = (uint16_t) color; // for 1bpp - - while(len--) writeColor(pixelColor); + } else if (_bpp == 8) { + pixelColor = (color & 0xE000) >> 8 | (color & 0x0700) >> 6 | (color & 0x0018) >> 3; + } else { + pixelColor = (uint16_t) color; // for 1bpp + } + while (len--) { + writeColor(pixelColor); + } } @@ -848,27 +912,30 @@ void TFT_eSprite::pushColor(uint32_t color, uint16_t len) ** Function name: writeColor ** Description: Write a pixel with pre-formatted colour to the set window *************************************************************************************x*/ -void TFT_eSprite::writeColor(uint16_t color) -{ - if (!_created ) return; +void TFT_eSprite::writeColor(uint16_t color) { + if (!_created) { + return; + } // Write 16 bit RGB 565 encoded colour to RAM - if (_bpp == 16) _img [_xptr + _yptr * _iwidth] = color; - - // Write 8 bit RGB 332 encoded colour to RAM - else if (_bpp == 8) _img8[_xptr + _yptr * _iwidth] = (uint8_t) color; - - else drawPixel(_xptr, _yptr, color); - + if (_bpp == 16) { + _img [_xptr + _yptr * _iwidth] = color; + } else if (_bpp == 8) { + // Write 8 bit RGB 332 encoded colour to RAM + _img8[_xptr + _yptr * _iwidth] = (uint8_t)color; + } else { + drawPixel(_xptr, _yptr, color); + } // Increment x _xptr++; // Wrap on x and y to start, increment y if needed - if (_xptr > _xe) - { + if (_xptr > _xe) { _xptr = _xs; _yptr++; - if (_yptr > _ye) _yptr = _ys; + if (_yptr > _ye) { + _yptr = _ys; + } } } @@ -877,18 +944,25 @@ void TFT_eSprite::writeColor(uint16_t color) ** Function name: setScrollRect ** Description: Set scroll area within the sprite and the gap fill colour *************************************************************************************x*/ -void TFT_eSprite::setScrollRect(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t color) -{ - if ((x >= _iwidth) || (y >= _iheight) || !_created ) return; - - if (x < 0) x = 0; - if (y < 0) y = 0; - - if ((x + w) > _iwidth ) w = _iwidth - x; - if ((y + h) > _iheight) h = _iheight - y; - - if ( w < 1 || h < 1) return; - +void TFT_eSprite::setScrollRect(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t color) { + if ((x >= _iwidth) || (y >= _iheight) || !_created) { + return; + } + if (x < 0) { + x = 0; + } + if (y < 0) { + y = 0; + } + if ((x + w) > _iwidth) { + w = _iwidth - x; + } + if ((y + h) > _iheight) { + h = _iheight - y; + } + if ( w < 1 || h < 1) { + return; + } _sx = x; _sy = y; _sw = w; @@ -902,10 +976,8 @@ void TFT_eSprite::setScrollRect(int32_t x, int32_t y, int32_t w, int32_t h, uint ** Function name: scroll ** Description: Scroll dx,dy pixels, positive right,down, negative left,up *************************************************************************************x*/ -void TFT_eSprite::scroll(int16_t dx, int16_t dy) -{ - if (abs(dx) >= _sw || abs(dy) >= _sh) - { +void TFT_eSprite::scroll(int16_t dx, int16_t dy) { + if (abs(dx) >= _sw || abs(dy) >= _sh) { fillRect (_sx, _sy, _sw, _sh, _scolor); return; } @@ -922,13 +994,16 @@ void TFT_eSprite::scroll(int16_t dx, int16_t dy) uint32_t fy = _sy; // from y // Adjust for x delta - if (dx <= 0) fx -= dx; - else tx += dx; + if (dx <= 0) { + fx -= dx; + } else { + tx += dx; + } // Adjust for y delta - if (dy <= 0) fy -= dy; - else - { // Scrolling down so start copy from bottom + if (dy <= 0) { + fy -= dy; + } else { // Scrolling down so start copy from bottom ty = ty + _sh - 1; // "To" pointer iw = -iw; // Pointer moves backwards fy = ty - dy; // "From" pointer @@ -939,45 +1014,56 @@ void TFT_eSprite::scroll(int16_t dx, int16_t dy) uint32_t typ = tx + ty * _iwidth; // Now move the pixels in RAM - if (_bpp == 16) - { - while (h--) - { // move pixel lines (to, from, byte count) + if (_bpp == 16) { + while (h--) { + // move pixel lines (to, from, byte count) memmove( _img + typ, _img + fyp, w<<1); typ += iw; fyp += iw; } - } - else if (_bpp == 8) - { - while (h--) - { // move pixel lines (to, from, byte count) + } else if (_bpp == 8) { + while (h--) { // move pixel lines (to, from, byte count) memmove( _img8 + typ, _img8 + fyp, w); typ += iw; fyp += iw; } - } - else if (_bpp == 1) - { + } else if (_bpp == 1) { if (dx > 0) { tx += w; fx += w; } // Start from right edge while (h--) { // move pixels one by one - for (uint16_t xp = 0; xp < w; xp++) - { - if (dx <= 0) drawPixel(tx + xp, ty, readPixel(fx + xp, fy)); - if (dx > 0) drawPixel(tx - xp, ty, readPixel(fx - xp, fy)); + for (uint16_t xp = 0; xp < w; xp++) { + if (dx <= 0) { + drawPixel(tx + xp, ty, readPixel(fx + xp, fy)); + } + if (dx > 0) { + drawPixel(tx - xp, ty, readPixel(fx - xp, fy)); + } + } + if (dy <= 0) { + ty++; + fy++; + } else { + ty--; + fy--; } - if (dy <= 0) { ty++; fy++; } - else { ty--; fy--; } } + } else { + return; // Not 1, 8 or 16 bpp } - else return; // Not 1, 8 or 16 bpp // Fill the gap left by the scrolling - if (dx > 0) fillRect(_sx, _sy, dx, _sh, _scolor); - if (dx < 0) fillRect(_sx + _sw + dx, _sy, -dx, _sh, _scolor); - if (dy > 0) fillRect(_sx, _sy, _sw, dy, _scolor); - if (dy < 0) fillRect(_sx, _sy + _sh + dy, _sw, -dy, _scolor); + if (dx > 0) { + fillRect(_sx, _sy, dx, _sh, _scolor); + } + if (dx < 0) { + fillRect(_sx + _sw + dx, _sy, -dx, _sh, _scolor); + } + if (dy > 0) { + fillRect(_sx, _sy, _sw, dy, _scolor); + } + if (dy < 0) { + fillRect(_sx, _sy + _sh + dy, _sw, -dy, _scolor); + } } @@ -985,25 +1071,25 @@ void TFT_eSprite::scroll(int16_t dx, int16_t dy) ** Function name: fillSprite ** Description: Fill the whole sprite with defined colour *************************************************************************************x*/ -void TFT_eSprite::fillSprite(uint32_t color) -{ - if (!_created ) return; - +void TFT_eSprite::fillSprite(uint32_t color) { + if (!_created) { + return; + } // Use memset if possible as it is super fast - if(( (uint8_t)color == (uint8_t)(color>>8) ) && _bpp == 16) - memset(_img, (uint8_t)color, _iwidth * _iheight * 2); - else if (_bpp == 8) - { - color = (color & 0xE000)>>8 | (color & 0x0700)>>6 | (color & 0x0018)>>3; + if (( (uint8_t)color == (uint8_t)(color >> 8) ) && _bpp == 16) { + memset(_img, (uint8_t)color, _iwidth * _iheight * 2); + } else if (_bpp == 8) { + color = (color & 0xE000) >> 8 | (color & 0x0700) >> 6 | (color & 0x0018) >> 3; memset(_img8, (uint8_t)color, _iwidth * _iheight); + } else if (_bpp == 1) { + if (color) { + memset(_img8, 0xFF, (_iwidth >> 3) * _iheight + 1); + } else { + memset(_img8, 0x00, (_iwidth >> 3) * _iheight + 1); + } + } else { + fillRect(0, 0, _iwidth, _iheight, color); } - else if (_bpp == 1) - { - if(color) memset(_img8, 0xFF, (_iwidth>>3) * _iheight + 1); - else memset(_img8, 0x00, (_iwidth>>3) * _iheight + 1); - } - - else fillRect(0, 0, _iwidth, _iheight, color); } @@ -1012,11 +1098,11 @@ void TFT_eSprite::fillSprite(uint32_t color) ** Description: Set the sprite text cursor x,y position *************************************************************************************x*/ // Not needed - using TFT_eSPI class function and this->cursor_x/y -//void TFT_eSprite::setCursor(int16_t x, int16_t y) -//{ -// this->cursor_x = x; -// this->cursor_y = y; -//} +// void TFT_eSprite::setCursor(int16_t x, int16_t y) +// { +// this->cursor_x = x; +// this->cursor_y = y; +// } /*************************************************************************************** @@ -1024,14 +1110,16 @@ void TFT_eSprite::fillSprite(uint32_t color) ** Description: Return the width of sprite *************************************************************************************x*/ // Return the size of the display -int16_t TFT_eSprite::width(void) -{ - if (!_created ) return 0; - - if (_bpp > 1) return _iwidth; - - if (_rotation == 1 || _rotation == 3) return _dheight; - +int16_t TFT_eSprite::width(void) { + if (!_created) { + return 0; + } + if (_bpp > 1) { + return _iwidth; + } + if (_rotation == 1 || _rotation == 3) { + return _dheight; + } return _dwidth; } @@ -1040,14 +1128,16 @@ int16_t TFT_eSprite::width(void) ** Function name: height ** Description: Return the height of sprite *************************************************************************************x*/ -int16_t TFT_eSprite::height(void) -{ - if (!_created ) return 0; - - if (_bpp > 1) return _iheight; - - if (_rotation == 1 || _rotation == 3) return _dwidth; - +int16_t TFT_eSprite::height(void) { + if (!_created) { + return 0; + } + if (_bpp > 1) { + return _iheight; + } + if (_rotation == 1 || _rotation == 3) { + return _dwidth; + } return _dheight; } @@ -1057,13 +1147,20 @@ int16_t TFT_eSprite::height(void) ** Description: Rotate coordinate frame for 1bpp sprite *************************************************************************************x*/ // Does nothing for 8 and 16 bpp sprites. TODO allow rotation of these sprites -void TFT_eSprite::setRotation(uint8_t rotation) -{ +void TFT_eSprite::setRotation(uint8_t rotation) { _rotation = rotation; - if (rotation == 0 && _iwidth > _iheight) swap_coord(_iwidth, _iheight); - if (rotation == 1 && _iwidth < _iheight) swap_coord(_iwidth, _iheight); - if (rotation == 2 && _iwidth > _iheight) swap_coord(_iwidth, _iheight); - if (rotation == 3 && _iwidth < _iheight) swap_coord(_iwidth, _iheight); + if (rotation == 0 && _iwidth > _iheight) { + swap_coord(_iwidth, _iheight); + } + if (rotation == 1 && _iwidth < _iheight) { + swap_coord(_iwidth, _iheight); + } + if (rotation == 2 && _iwidth > _iheight) { + swap_coord(_iwidth, _iheight); + } + if (rotation == 3 && _iwidth < _iheight) { + swap_coord(_iwidth, _iheight); + } } @@ -1071,9 +1168,7 @@ void TFT_eSprite::setRotation(uint8_t rotation) ** Function name: getRotation ** Description: Get rotation for 1bpp sprite *************************************************************************************x*/ - -uint8_t TFT_eSprite::getRotation(void) -{ +uint8_t TFT_eSprite::getRotation(void) { return _rotation; } @@ -1082,42 +1177,36 @@ uint8_t TFT_eSprite::getRotation(void) ** Function name: drawPixel ** Description: push a single pixel at an arbitrary position *************************************************************************************x*/ -void TFT_eSprite::drawPixel(int32_t x, int32_t y, uint32_t color) -{ +void TFT_eSprite::drawPixel(int32_t x, int32_t y, uint32_t color) { // Range checking - if ((x < 0) || (y < 0) ||(x >= _width) || (y >= _height) || !_created) return; - - if (_bpp == 16) - { + if ((x < 0) || (y < 0) ||(x >= _width) || (y >= _height) || !_created) { + return; + } + if (_bpp == 16) { color = (color >> 8) | (color << 8); _img[x+y*_iwidth] = (uint16_t) color; - } - else if (_bpp == 8) - { - _img8[x+y*_iwidth] = (uint8_t)((color & 0xE000)>>8 | (color & 0x0700)>>6 | (color & 0x0018)>>3); - } - else // 1 bpp - { - if (_rotation == 1) - { + } else if (_bpp == 8) { + _img8[x+y*_iwidth] = (uint8_t)((color & 0xE000) >> 8 | (color & 0x0700) >> 6 | (color & 0x0018) >> 3); + } else { + // 1 bpp + if (_rotation == 1) { uint16_t tx = x; x = _dwidth - y - 1; y = tx; - } - else if (_rotation == 2) - { + } else if (_rotation == 2) { x = _dwidth - x - 1; y = _dheight - y - 1; - } - else if (_rotation == 3) - { + } else if (_rotation == 3) { uint16_t tx = x; x = y; y = _dheight - tx - 1; } - if (color) _img8[(x + y * _bitwidth)>>3] |= (0x80 >> (x & 0x7)); - else _img8[(x + y * _bitwidth)>>3] &= ~(0x80 >> (x & 0x7)); + if (color) { + _img8[(x + y * _bitwidth) >> 3] |= (0x80 >> (x & 0x7)); + } else { + _img8[(x + y * _bitwidth) >> 3] &= ~(0x80 >> (x & 0x7)); + } } } @@ -1126,10 +1215,10 @@ void TFT_eSprite::drawPixel(int32_t x, int32_t y, uint32_t color) ** Function name: drawLine ** Description: draw a line between 2 arbitrary points *************************************************************************************x*/ -void TFT_eSprite::drawLine(int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint32_t color) -{ - if (!_created ) return; - +void TFT_eSprite::drawLine(int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint32_t color) { + if (!_created) { + return; + } boolean steep = abs(y1 - y0) > abs(x1 - x0); if (steep) { swap_coord(x0, y0); @@ -1154,26 +1243,34 @@ void TFT_eSprite::drawLine(int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint3 err -= dy; if (err < 0) { err += dx; - if (dlen == 1) drawPixel(y0, xs, color); - else drawFastVLine(y0, xs, dlen, color); + if (dlen == 1) { + drawPixel(y0, xs, color); + } else { + drawFastVLine(y0, xs, dlen, color); + } dlen = 0; y0 += ystep; xs = x0 + 1; } } - if (dlen) drawFastVLine(y0, xs, dlen, color); - } - else - { + if (dlen) { + drawFastVLine(y0, xs, dlen, color); + } + } else { for (; x0 <= x1; x0++) { dlen++; err -= dy; if (err < 0) { err += dx; - if (dlen == 1) drawPixel(xs, y0, color); - else drawFastHLine(xs, y0, dlen, color); + if (dlen == 1) { + drawPixel(xs, y0, color); + } else { + drawFastHLine(xs, y0, dlen, color); + } dlen = 0; y0 += ystep; xs = x0 + 1; } } - if (dlen) drawFastHLine(xs, y0, dlen, color); + if (dlen) { + drawFastHLine(xs, y0, dlen, color); + } } } @@ -1182,32 +1279,36 @@ void TFT_eSprite::drawLine(int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint3 ** Function name: drawFastVLine ** Description: draw a vertical line *************************************************************************************x*/ -void TFT_eSprite::drawFastVLine(int32_t x, int32_t y, int32_t h, uint32_t color) -{ +void TFT_eSprite::drawFastVLine(int32_t x, int32_t y, int32_t h, uint32_t color) { - if ((x < 0) || (x >= _iwidth) || (y >= _iheight) || !_created) return; + if ((x < 0) || (x >= _iwidth) || (y >= _iheight) || !_created) { + return; + } + if (y < 0) { + h += y; + y = 0; + } - if (y < 0) { h += y; y = 0; } + if ((y + h) > _iheight) { + h = _iheight - y; + } + if (h < 1) { + return; + } - if ((y + h) > _iheight) h = _iheight - y; - - if (h < 1) return; - - if (_bpp == 16) - { + if (_bpp == 16) { color = (color >> 8) | (color << 8); int32_t yp = x + _iwidth * y; - while (h--) {_img[yp] = (uint16_t) color; yp += _iwidth;} - } - else if (_bpp == 8) - { - color = (color & 0xE000)>>8 | (color & 0x0700)>>6 | (color & 0x0018)>>3; - while (h--) _img8[x + _iwidth * y++] = (uint8_t) color; - } - else - { - while (h--) - { + while (h--) { + _img[yp] = (uint16_t) color; yp += _iwidth; + } + } else if (_bpp == 8) { + color = (color & 0xE000) >> 8 | (color & 0x0700) >> 6 | (color & 0x0018) >> 3; + while (h--) { + _img8[x + _iwidth * y++] = (uint8_t) color; + } + } else{ + while (h--) { drawPixel(x, y, color); y++; } @@ -1219,31 +1320,32 @@ void TFT_eSprite::drawFastVLine(int32_t x, int32_t y, int32_t h, uint32_t color) ** Function name: drawFastHLine ** Description: draw a horizontal line *************************************************************************************x*/ -void TFT_eSprite::drawFastHLine(int32_t x, int32_t y, int32_t w, uint32_t color) -{ +void TFT_eSprite::drawFastHLine(int32_t x, int32_t y, int32_t w, uint32_t color) { - if ((y < 0) || (x >= _iwidth) || (y >= _iheight) || !_created) return; + if ((y < 0) || (x >= _iwidth) || (y >= _iheight) || !_created) { + return; + } + if (x < 0) { + w += x; + x = 0; + } - if (x < 0) { w += x; x = 0; } - - if ((x + w) > _iwidth) w = _iwidth - x; - - if (w < 1) return; - - if (_bpp == 16) - { + if ((x + w) > _iwidth) { + w = _iwidth - x; + } + if (w < 1) { + return; + } + if (_bpp == 16) { color = (color >> 8) | (color << 8); - while (w--) _img[_iwidth * y + x++] = (uint16_t) color; - } - else if (_bpp == 8) - { - color = (color & 0xE000)>>8 | (color & 0x0700)>>6 | (color & 0x0018)>>3; + while (w--) { + _img[_iwidth * y + x++] = (uint16_t) color; + } + } else if (_bpp == 8) { + color = (color & 0xE000) >> 8 | (color & 0x0700) >> 6 | (color & 0x0018) >> 3; memset(_img8+_iwidth * y + x, (uint8_t)color, w); - } - else - { - while (w--) - { + } else{ + while (w--) { drawPixel(x, y, color); x++; } @@ -1255,51 +1357,62 @@ void TFT_eSprite::drawFastHLine(int32_t x, int32_t y, int32_t w, uint32_t color) ** Function name: fillRect ** Description: draw a filled rectangle *************************************************************************************x*/ -void TFT_eSprite::fillRect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t color) -{ - if (!_created ) return; +void TFT_eSprite::fillRect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t color) { + if (!_created) { + return; + } - if ((x >= _iwidth) || (y >= _iheight)) return; + if ((x >= _iwidth) || (y >= _iheight)) { + return; + } + if (x < 0) { + w += x; + x = 0; + } - if (x < 0) { w += x; x = 0; } - if (y < 0) { h += y; y = 0; } - - if ((x + w) > _iwidth) w = _iwidth - x; - if ((y + h) > _iheight) h = _iheight - y; - - if ((w < 1) || (h < 1)) return; + if (y < 0) { + h += y; + y = 0; + } + if ((x + w) > _iwidth) { + w = _iwidth - x; + } + if ((y + h) > _iheight) { + h = _iheight - y; + } + if ((w < 1) || (h < 1)) { + return; + } int32_t yp = _iwidth * y + x; - if (_bpp == 16) - { + if (_bpp == 16) { color = (color >> 8) | (color << 8); uint32_t iw = w; int32_t ys = yp; - if(h--) {while (iw--) _img[yp++] = (uint16_t) color;} + if (h--) { + while (iw--) { + _img[yp++] = (uint16_t) color; + } + } yp = ys; - while (h--) - { + while (h--) { yp += _iwidth; memcpy( _img+yp, _img+ys, w<<1); } - } - else if (_bpp == 8) - { - color = (color & 0xE000)>>8 | (color & 0x0700)>>6 | (color & 0x0018)>>3; - while (h--) - { + } else if (_bpp == 8) { + color = (color & 0xE000) >> 8 | (color & 0x0700) >> 6 | (color & 0x0018) >> 3; + while (h--) { memset(_img8 + yp, (uint8_t)color, w); yp += _iwidth; } - } - else - { - while (h--) - { + } else { + while (h--) { int32_t ww = w; int32_t xx = x; - while (ww--) drawPixel(xx++, y, color); + while (ww--) { + drawPixel(xx++, y, color); + } y++; } } @@ -1310,144 +1423,150 @@ void TFT_eSprite::fillRect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t ** Function name: write ** Description: draw characters piped through serial stream *************************************************************************************x*/ -size_t TFT_eSprite::write(uint8_t utf8) -{ - if (utf8 == '\r') return 1; - -#ifdef SMOOTH_FONT - if(this->fontLoaded) - { - uint16_t unicode = decodeUTF8(utf8); - if (unicode < 32 && utf8 != '\n') return 1; - - //fontFile = SPIFFS.open( _gFontFilename, "r" ); - //fontFile = SPIFFS.open( this->_gFontFilename, "r" ); - - //if(!fontFile) - //{ - // fontLoaded = false; - // return 1; - //} - //Serial.print("Decoded Unicode = 0x");Serial.println(unicode,HEX); - - drawGlyph(unicode); - //fontFile.close(); +size_t TFT_eSprite::write(uint8_t utf8) { + if (utf8 == '\r') { return 1; } -#endif + #ifdef SMOOTH_FONT + if (this->fontLoaded) { + uint16_t unicode = decodeUTF8(utf8); + if (unicode < 32 && utf8 != '\n') { + return 1; + } + // fontFile = SPIFFS.open( _gFontFilename, "r" ); + // fontFile = SPIFFS.open( this->_gFontFilename, "r" ); - if (!_created ) return 1; + // if (!fontFile) + // { + // fontLoaded = false; + // return 1; + // } + // Serial.print("Decoded Unicode = 0x");Serial.println(unicode,HEX); + drawGlyph(unicode); + // fontFile.close(); + return 1; + } + #endif + + if (!_created) { + return 1; + } uint8_t uniCode = utf8; // Work with a copy - if (utf8 == '\n') uniCode+=22; // Make it a valid space character to stop errors - else if (utf8 < 32) return 1; - + if (utf8 == '\n') { + uniCode+=22; // Make it a valid space character to stop errors + } else if (utf8 < 32) { + return 1; + } uint16_t width = 0; uint16_t height = 0; -//vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv DEBUG vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv - //Serial.print((uint8_t) uniCode); // Debug line sends all printed TFT text to serial port - //Serial.println(uniCode, HEX); // Debug line sends all printed TFT text to serial port - //delay(5); // Debug optional wait for serial port to flush through -//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ DEBUG ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + //vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv DEBUG vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv + // Serial.print((uint8_t) uniCode); // Debug line sends all printed TFT text to serial port + // Serial.println(uniCode, HEX); // Debug line sends all printed TFT text to serial port + // delay(5); // Debug optional wait for serial port to flush through + //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ DEBUG ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< -#ifdef LOAD_GFXFF - if(!gfxFont) { -#endif -//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< - -#ifdef LOAD_FONT2 - if (textfont == 2) - { - if (utf8 > 127) return 1; - // This is 20us faster than using the fontdata structure (0.443ms per character instead of 0.465ms) - width = pgm_read_byte(widtbl_f16 + uniCode-32); - height = chr_hgt_f16; - // Font 2 is rendered in whole byte widths so we must allow for this - width = (width + 6) / 8; // Width in whole bytes for font 2, should be + 7 but must allow for font width change - width = width * 8; // Width converted back to pixles - } - #ifdef LOAD_RLE - else + //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< + #ifdef LOAD_GFXFF + if (!gfxFont) { #endif -#endif + //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< -#ifdef LOAD_RLE - { - if ((textfont>2) && (textfont<9)) - { - if (utf8 > 127) return 1; - // Uses the fontinfo struct array to avoid lots of 'if' or 'switch' statements - // A tad slower than above but this is not significant and is more convenient for the RLE fonts - width = pgm_read_byte( (uint8_t *)pgm_read_dword( &(fontdata[textfont].widthtbl ) ) + uniCode-32 ); - height= pgm_read_byte( &fontdata[textfont].height ); + #ifdef LOAD_FONT2 + if (textfont == 2) { + if (utf8 > 127) { + return 1; + } + // This is 20us faster than using the fontdata structure (0.443ms per character instead of 0.465ms) + width = pgm_read_byte(widtbl_f16 + uniCode-32); + height = chr_hgt_f16; + // Font 2 is rendered in whole byte widths so we must allow for this + width = (width + 6) / 8; // Width in whole bytes for font 2, should be + 7 but must allow for font width change + width = width * 8; // Width converted back to pixles } - } -#endif + #ifdef LOAD_RLE + else + #endif + #endif -#ifdef LOAD_GLCD - if (textfont==1) - { + #ifdef LOAD_RLE + { + if ((textfont>2) && (textfont<9)) { + if (utf8 > 127) { + return 1; + } + // Uses the fontinfo struct array to avoid lots of 'if' or 'switch' statements + // A tad slower than above but this is not significant and is more convenient for the RLE fonts + width = pgm_read_byte( (uint8_t *)pgm_read_dword( &(fontdata[textfont].widthtbl ) ) + uniCode-32 ); + height= pgm_read_byte( &fontdata[textfont].height ); + } + } + #endif + + #ifdef LOAD_GLCD + if (textfont==1) { width = 6; height = 8; - } -#else - if (textfont==1) return 1; -#endif + } + #else + if (textfont==1) { + return 1; + } + #endif height = height * textsize; - if (utf8 == '\n') - { + if (utf8 == '\n') { this->cursor_y += height; this->cursor_x = 0; - } - else - { - if (textwrapX && (this->cursor_x + width * textsize > _iwidth)) - { + } else { + if (textwrapX && (this->cursor_x + width * textsize > _iwidth)) { this->cursor_y += height; this->cursor_x = 0; } - if (textwrapY && (this->cursor_y >= _iheight)) this->cursor_y = 0; + if (textwrapY && (this->cursor_y >= _iheight)) { + this->cursor_y = 0; + } this->cursor_x += drawChar(uniCode, this->cursor_x, this->cursor_y, textfont); } -//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< -#ifdef LOAD_GFXFF - } // Custom GFX font - else - { + //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< + #ifdef LOAD_GFXFF + } else { // Custom GFX font - if(utf8 == '\n') { - this->cursor_x = 0; - this->cursor_y += (int16_t)textsize * (uint8_t)pgm_read_byte(&gfxFont->yAdvance); - } else { - if (uniCode > (uint8_t)pgm_read_byte(&gfxFont->last )) return 1; - if (uniCode < (uint8_t)pgm_read_byte(&gfxFont->first)) return 1; - - uint8_t c2 = uniCode - pgm_read_byte(&gfxFont->first); - GFXglyph *glyph = &(((GFXglyph *)pgm_read_dword(&gfxFont->glyph))[c2]); - uint8_t w = pgm_read_byte(&glyph->width), - h = pgm_read_byte(&glyph->height); - if((w > 0) && (h > 0)) { // Is there an associated bitmap? - int16_t xo = (int8_t)pgm_read_byte(&glyph->xOffset); - if(textwrapX && ((this->cursor_x + textsize * (xo + w)) > _iwidth)) { - // Drawing character would go off right edge; wrap to new line - this->cursor_x = 0; - this->cursor_y += (int16_t)textsize * (uint8_t)pgm_read_byte(&gfxFont->yAdvance); + if (utf8 == '\n') { + this->cursor_x = 0; + this->cursor_y += (int16_t)textsize * (uint8_t)pgm_read_byte(&gfxFont->yAdvance); + } else { + if (uniCode > (uint8_t)pgm_read_byte(&gfxFont->last )) { + return 1; } - if (textwrapY && (this->cursor_y >= _iheight)) this->cursor_y = 0; - drawChar(this->cursor_x, this->cursor_y, uniCode, textcolor, textbgcolor, textsize); + if (uniCode < (uint8_t)pgm_read_byte(&gfxFont->first)) { + return 1; + } + uint8_t c2 = uniCode - pgm_read_byte(&gfxFont->first); + GFXglyph *glyph = &(((GFXglyph *)pgm_read_dword(&gfxFont->glyph))[c2]); + uint8_t w = pgm_read_byte(&glyph->width), + h = pgm_read_byte(&glyph->height); + if ((w > 0) && (h > 0)) { // Is there an associated bitmap? + int16_t xo = (int8_t)pgm_read_byte(&glyph->xOffset); + if (textwrapX && ((this->cursor_x + textsize * (xo + w)) > _iwidth)) { + // Drawing character would go off right edge; wrap to new line + this->cursor_x = 0; + this->cursor_y += (int16_t)textsize * (uint8_t)pgm_read_byte(&gfxFont->yAdvance); + } + if (textwrapY && (this->cursor_y >= _iheight)) { + this->cursor_y = 0; + } + drawChar(this->cursor_x, this->cursor_y, uniCode, textcolor, textbgcolor, textsize); + } + this->cursor_x += pgm_read_byte(&glyph->xAdvance) * (int16_t)textsize; } - this->cursor_x += pgm_read_byte(&glyph->xAdvance) * (int16_t)textsize; } - } -#endif // LOAD_GFXFF -//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< - + #endif // LOAD_GFXFF + //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< return 1; } @@ -1456,87 +1575,82 @@ size_t TFT_eSprite::write(uint8_t utf8) ** Function name: drawChar ** Description: draw a single character in the Adafruit GLCD or freefont *************************************************************************************x*/ -void TFT_eSprite::drawChar(int32_t x, int32_t y, unsigned char c, uint32_t color, uint32_t bg, uint8_t size) -{ - if (!_created ) return; - +void TFT_eSprite::drawChar(int32_t x, int32_t y, unsigned char c, uint32_t color, uint32_t bg, uint8_t size) { + if (!_created) { + return; + } if ((x >= _iwidth) || // Clip right (y >= _iheight) || // Clip bottom - ((x + 6 * size - 1) < 0) || // Clip left - ((y + 8 * size - 1) < 0)) // Clip top + ((x + 6 * size - 1) < 0) || // Clip left + ((y + 8 * size - 1) < 0)) { // Clip top return; - -#ifdef LOAD_GLCD -//>>>>>>>>>>>>>>>>>> -#ifdef LOAD_GFXFF - if(!gfxFont) { // 'Classic' built-in font -#endif -//>>>>>>>>>>>>>>>>>> - - boolean fillbg = (bg != color); - - if ((size==1) && fillbg) - { - uint8_t column[6]; - uint8_t mask = 0x1; - - for (int8_t i = 0; i < 5; i++ ) column[i] = pgm_read_byte(font + (c * 5) + i); - column[5] = 0; - - int8_t j, k; - for (j = 0; j < 8; j++) { - for (k = 0; k < 5; k++ ) { - if (column[k] & mask) { - drawPixel(x + k, y + j, color); - } - else { - drawPixel(x + k, y + j, bg); - } - } - - mask <<= 1; - - drawPixel(x + k, y + j, bg); - } } - else - { - for (int8_t i = 0; i < 6; i++ ) { - uint8_t line; - if (i == 5) - line = 0x0; - else - line = pgm_read_byte(font + (c * 5) + i); + #ifdef LOAD_GLCD + //>>>>>>>>>>>>>>>>>> + #ifdef LOAD_GFXFF + if (!gfxFont) { // 'Classic' built-in font + #endif + //>>>>>>>>>>>>>>>>>> - if (size == 1) // default size - { - for (int8_t j = 0; j < 8; j++) { - if (line & 0x1) drawPixel(x + i, y + j, color); - line >>= 1; - } + boolean fillbg = (bg != color); + + if ((size==1) && fillbg) { + uint8_t column[6]; + uint8_t mask = 0x1; + + for (int8_t i = 0; i < 5; i++) { + column[i] = pgm_read_byte(font + (c * 5) + i); } - else { // big size - for (int8_t j = 0; j < 8; j++) { - if (line & 0x1) fillRect(x + (i * size), y + (j * size), size, size, color); - else if (fillbg) fillRect(x + i * size, y + j * size, size, size, bg); - line >>= 1; + column[5] = 0; + + int8_t j, k; + for (j = 0; j < 8; j++) { + for (k = 0; k < 5; k++) { + if (column[k] & mask) { + drawPixel(x + k, y + j, color); + } else { + drawPixel(x + k, y + j, bg); + } + } + mask <<= 1; + drawPixel(x + k, y + j, bg); + } + } else { + for (int8_t i = 0; i < 6; i++) { + uint8_t line; + if (i == 5) { + line = 0x0; + } else { + line = pgm_read_byte(font + (c * 5) + i); + } + if (size == 1) { // default size + for (int8_t j = 0; j < 8; j++) { + if (line & 0x1) drawPixel(x + i, y + j, color); + line >>= 1; + } + } else { // big size + for (int8_t j = 0; j < 8; j++) { + if (line & 0x1) { + fillRect(x + (i * size), y + (j * size), size, size, color); + } else if (fillbg) { + fillRect(x + i * size, y + j * size, size, size, bg); + } + line >>= 1; + } } } } - } -//>>>>>>>>>>>>>>>>>>>>>>>>>>> -#ifdef LOAD_GFXFF - } else { // Custom font -#endif -//>>>>>>>>>>>>>>>>>>>>>>>>>>> -#endif // LOAD_GLCD + //>>>>>>>>>>>>>>>>>>>>>>>>>>> + #ifdef LOAD_GFXFF + } else { // Custom font + #endif + //>>>>>>>>>>>>>>>>>>>>>>>>>>> + #endif // LOAD_GLCD -#ifdef LOAD_GFXFF + #ifdef LOAD_GFXFF // Filter out bad characters not present in font - if ((c >= (uint8_t)pgm_read_byte(&gfxFont->first)) && (c <= (uint8_t)pgm_read_byte(&gfxFont->last ))) - { -//>>>>>>>>>>>>>>>>>>>>>>>>>>> + if ((c >= (uint8_t)pgm_read_byte(&gfxFont->first)) && (c <= (uint8_t)pgm_read_byte(&gfxFont->last ))) { c -= pgm_read_byte(&gfxFont->first); GFXglyph *glyph = &(((GFXglyph *)pgm_read_dword(&gfxFont->glyph))[c]); @@ -1545,51 +1659,56 @@ void TFT_eSprite::drawChar(int32_t x, int32_t y, unsigned char c, uint32_t color uint16_t bo = pgm_read_word(&glyph->bitmapOffset); uint8_t w = pgm_read_byte(&glyph->width), h = pgm_read_byte(&glyph->height); - //xa = pgm_read_byte(&glyph->xAdvance); + // xa = pgm_read_byte(&glyph->xAdvance); int8_t xo = pgm_read_byte(&glyph->xOffset), yo = pgm_read_byte(&glyph->yOffset); uint8_t xx, yy, bits=0, bit=0; int16_t xo16 = 0, yo16 = 0; - if(size > 1) { + if (size > 1) { xo16 = xo; yo16 = yo; } uint16_t hpc = 0; // Horizontal foreground pixel count - for(yy=0; yy>= 1; } // Draw pixels for this line as we are about to increment yy if (hpc) { - if(size == 1) drawFastHLine(x+xo+xx-hpc, y+yo+yy, hpc, color); - else fillRect(x+(xo16+xx-hpc)*size, y+(yo16+yy)*size, size*hpc, size, color); - hpc=0; + if (size == 1) { + drawFastHLine(x + xo + xx - hpc, y + yo + yy, hpc, color); + } else { + fillRect(x + (xo16 + xx - hpc) * size, y + (yo16 + yy) * size, size * hpc, size, color); + } + hpc = 0; } } } -#endif - - -#ifdef LOAD_GLCD - #ifdef LOAD_GFXFF - } // End classic vs custom font #endif -#endif + #ifdef LOAD_GLCD + #ifdef LOAD_GFXFF + } // End classic vs custom font + #endif + #endif } @@ -1597,397 +1716,400 @@ void TFT_eSprite::drawChar(int32_t x, int32_t y, unsigned char c, uint32_t color ** Function name: drawChar ** Description: draw a unicode onto the screen *************************************************************************************x*/ -int16_t TFT_eSprite::drawChar(uint16_t uniCode, int32_t x, int32_t y) -{ +int16_t TFT_eSprite::drawChar(uint16_t uniCode, int32_t x, int32_t y) { return drawChar(uniCode, x, y, textfont); } -int16_t TFT_eSprite::drawChar(uint16_t uniCode, int32_t x, int32_t y, uint8_t font) -{ - if (!_created ) return 0; - - if (font==1) - { -#ifdef LOAD_GLCD - #ifndef LOAD_GFXFF - drawChar(x, y, uniCode, textcolor, textbgcolor, textsize); - return 6 * textsize; - #endif -#else - #ifndef LOAD_GFXFF +int16_t TFT_eSprite::drawChar(uint16_t uniCode, int32_t x, int32_t y, uint8_t font) { + if (!_created) { return 0; - #endif -#endif - -#ifdef LOAD_GFXFF - drawChar(x, y, uniCode, textcolor, textbgcolor, textsize); - if(!gfxFont) { // 'Classic' built-in font + } + if (font==1) { #ifdef LOAD_GLCD - return 6 * textsize; + #ifndef LOAD_GFXFF + drawChar(x, y, uniCode, textcolor, textbgcolor, textsize); + return 6 * textsize; + #endif #else - return 0; - #endif - } - else - { - if((uniCode >= pgm_read_byte(&gfxFont->first)) && (uniCode <= pgm_read_byte(&gfxFont->last) )) - { - uint8_t c2 = uniCode - pgm_read_byte(&gfxFont->first); - GFXglyph *glyph = &(((GFXglyph *)pgm_read_dword(&gfxFont->glyph))[c2]); - return pgm_read_byte(&glyph->xAdvance) * textsize; - } - else - { + #ifndef LOAD_GFXFF return 0; + #endif + #endif + + #ifdef LOAD_GFXFF + drawChar(x, y, uniCode, textcolor, textbgcolor, textsize); + if (!gfxFont) { // 'Classic' built-in font + #ifdef LOAD_GLCD + return 6 * textsize; + #else + return 0; + #endif + } else { + if ((uniCode >= pgm_read_byte(&gfxFont->first)) && (uniCode <= pgm_read_byte(&gfxFont->last) )) { + uint8_t c2 = uniCode - pgm_read_byte(&gfxFont->first); + GFXglyph *glyph = &(((GFXglyph *)pgm_read_dword(&gfxFont->glyph))[c2]); + return pgm_read_byte(&glyph->xAdvance) * textsize; + } else { + return 0; + } } - } -#endif + #endif } - if ((font>1) && (font<9) && ((uniCode < 32) || (uniCode > 127))) return 0; + if ((font > 1) && (font < 9) && ((uniCode < 32) || (uniCode > 127))) { + return 0; + } int32_t width = 0; int32_t height = 0; uint32_t flash_address = 0; uniCode -= 32; -#ifdef LOAD_FONT2 - if (font == 2) - { - // This is faster than using the fontdata structure - flash_address = pgm_read_dword(&chrtbl_f16[uniCode]); - width = pgm_read_byte(widtbl_f16 + uniCode); - height = chr_hgt_f16; - } - #ifdef LOAD_RLE - else - #endif -#endif - -#ifdef LOAD_RLE - { - if ((font>2) && (font<9)) - { - // This is slower than above but is more convenient for the RLE fonts - flash_address = pgm_read_dword( pgm_read_dword( &(fontdata[font].chartbl ) ) + uniCode*sizeof(void *) ); - width = pgm_read_byte( (uint8_t *)pgm_read_dword( &(fontdata[font].widthtbl ) ) + uniCode ); - height= pgm_read_byte( &fontdata[font].height ); + #ifdef LOAD_FONT2 + if (font == 2) { + // This is faster than using the fontdata structure + flash_address = pgm_read_dword(&chrtbl_f16[uniCode]); + width = pgm_read_byte(widtbl_f16 + uniCode); + height = chr_hgt_f16; } - } -#endif + #ifdef LOAD_RLE + else + #endif + #endif + + #ifdef LOAD_RLE + { + if ((font > 2) && (font < 9)) { + // This is slower than above but is more convenient for the RLE fonts + flash_address = pgm_read_dword( pgm_read_dword( &(fontdata[font].chartbl ) ) + uniCode*sizeof(void *) ); + width = pgm_read_byte( (uint8_t *)pgm_read_dword( &(fontdata[font].widthtbl ) ) + uniCode ); + height= pgm_read_byte( &fontdata[font].height ); + } + } + #endif int32_t w = width; - int32_t pX = 0; - int32_t pY = y; + int32_t pX = 0; + int32_t pY = y; uint8_t line = 0; -#ifdef LOAD_FONT2 // chop out code if we do not need it - if (font == 2) { - w = w + 6; // Should be + 7 but we need to compensate for width increment - w = w / 8; - if (x + width * textsize >= _iwidth) return width * textsize ; - - for (int32_t i = 0; i < height; i++) - { - if (textcolor != textbgcolor) fillRect(x, pY, width * textsize, textsize, textbgcolor); - - for (int32_t k = 0; k < w; k++) - { - line = pgm_read_byte((uint8_t *)flash_address + w * i + k); - if (line) { - if (textsize == 1) { - pX = x + k * 8; - if (line & 0x80) drawPixel(pX, pY, textcolor); - if (line & 0x40) drawPixel(pX + 1, pY, textcolor); - if (line & 0x20) drawPixel(pX + 2, pY, textcolor); - if (line & 0x10) drawPixel(pX + 3, pY, textcolor); - if (line & 0x08) drawPixel(pX + 4, pY, textcolor); - if (line & 0x04) drawPixel(pX + 5, pY, textcolor); - if (line & 0x02) drawPixel(pX + 6, pY, textcolor); - if (line & 0x01) drawPixel(pX + 7, pY, textcolor); - } - else { - pX = x + k * 8 * textsize; - if (line & 0x80) fillRect(pX, pY, textsize, textsize, textcolor); - if (line & 0x40) fillRect(pX + textsize, pY, textsize, textsize, textcolor); - if (line & 0x20) fillRect(pX + 2 * textsize, pY, textsize, textsize, textcolor); - if (line & 0x10) fillRect(pX + 3 * textsize, pY, textsize, textsize, textcolor); - if (line & 0x08) fillRect(pX + 4 * textsize, pY, textsize, textsize, textcolor); - if (line & 0x04) fillRect(pX + 5 * textsize, pY, textsize, textsize, textcolor); - if (line & 0x02) fillRect(pX + 6 * textsize, pY, textsize, textsize, textcolor); - if (line & 0x01) fillRect(pX + 7 * textsize, pY, textsize, textsize, textcolor); + #ifdef LOAD_FONT2 // chop out code if we do not need it + if (font == 2) { + w = w + 6; // Should be + 7 but we need to compensate for width increment + w = w / 8; + if (x + width * textsize >= _iwidth) { + return width * textsize ; + } + for (int32_t i = 0; i < height; i++) { + if (textcolor != textbgcolor) { + fillRect(x, pY, width * textsize, textsize, textbgcolor); + } + for (int32_t k = 0; k < w; k++) { + line = pgm_read_byte((uint8_t *)flash_address + w * i + k); + if (line) { + if (textsize == 1) { + pX = x + k * 8; + if (line & 0x80) drawPixel(pX, pY, textcolor); + if (line & 0x40) drawPixel(pX + 1, pY, textcolor); + if (line & 0x20) drawPixel(pX + 2, pY, textcolor); + if (line & 0x10) drawPixel(pX + 3, pY, textcolor); + if (line & 0x08) drawPixel(pX + 4, pY, textcolor); + if (line & 0x04) drawPixel(pX + 5, pY, textcolor); + if (line & 0x02) drawPixel(pX + 6, pY, textcolor); + if (line & 0x01) drawPixel(pX + 7, pY, textcolor); + } else { + pX = x + k * 8 * textsize; + if (line & 0x80) fillRect(pX, pY, textsize, textsize, textcolor); + if (line & 0x40) fillRect(pX + textsize, pY, textsize, textsize, textcolor); + if (line & 0x20) fillRect(pX + 2 * textsize, pY, textsize, textsize, textcolor); + if (line & 0x10) fillRect(pX + 3 * textsize, pY, textsize, textsize, textcolor); + if (line & 0x08) fillRect(pX + 4 * textsize, pY, textsize, textsize, textcolor); + if (line & 0x04) fillRect(pX + 5 * textsize, pY, textsize, textsize, textcolor); + if (line & 0x02) fillRect(pX + 6 * textsize, pY, textsize, textsize, textcolor); + if (line & 0x01) fillRect(pX + 7 * textsize, pY, textsize, textsize, textcolor); + } } } + pY += textsize; } - pY += textsize; } - } + #ifdef LOAD_RLE + else + #endif + #endif // FONT2 - #ifdef LOAD_RLE - else + #ifdef LOAD_RLE // 674 bytes of code + // Font is not 2 and hence is RLE encoded + { + w *= height; // Now w is total number of pixels in the character + + if (textcolor != textbgcolor) { + fillRect(x, pY, width * textsize, textsize * height, textbgcolor); + } + int16_t color = textcolor; + if (_bpp == 16) { + color = (textcolor >> 8) | (textcolor << 8); + } else if (_bpp == 8) { + color = ((textcolor & 0xE000) >> 8 | (textcolor & 0x0700) >> 6 | (textcolor & 0x0018) >> 3); + } + int32_t px = 0, py = pY; // To hold character block start and end column and row values + int32_t pc = 0; // Pixel count + uint8_t np = textsize * textsize; // Number of pixels in a drawn pixel + uint8_t tnp = 0; // Temporary copy of np for while loop + uint8_t ts = textsize - 1; // Temporary copy of textsize + // 16 bit pixel count so maximum font size is equivalent to 180x180 pixels in area + // w is total number of pixels to plot to fill character block + while (pc < w) { + line = pgm_read_byte((uint8_t *)flash_address); + flash_address++; // 20 bytes smaller by incrementing here + if (line & 0x80) { + line &= 0x7F; + line++; + if (ts) { + px = x + textsize * (pc % width); // Keep these px and py calculations outside the loop as they are slow + py = y + textsize * (pc / width); + } else { + px = x + pc % width; // Keep these px and py calculations outside the loop as they are slow + py = y + pc / width; + } + while (line--) { + pc++; + setWindow(px, py, px + ts, py + ts); + if (ts) { + tnp = np; + while (tnp--) { + writeColor(color); + } + } else { + writeColor(color); + } + + px += textsize; + + if (px >= (x + width * textsize)) { + px = x; + py += textsize; + } + } + } else { + line++; + pc += line; + } + } + } + // End of RLE font rendering #endif -#endif //FONT2 - -#ifdef LOAD_RLE //674 bytes of code - // Font is not 2 and hence is RLE encoded - { - w *= height; // Now w is total number of pixels in the character - - if (textcolor != textbgcolor) fillRect(x, pY, width * textsize, textsize * height, textbgcolor); - int16_t color = textcolor; - if (_bpp == 16) color = (textcolor >> 8) | (textcolor << 8); - else if (_bpp == 8) color = ((textcolor & 0xE000)>>8 | (textcolor & 0x0700)>>6 | (textcolor & 0x0018)>>3); - int32_t px = 0, py = pY; // To hold character block start and end column and row values - int32_t pc = 0; // Pixel count - uint8_t np = textsize * textsize; // Number of pixels in a drawn pixel - uint8_t tnp = 0; // Temporary copy of np for while loop - uint8_t ts = textsize - 1; // Temporary copy of textsize - // 16 bit pixel count so maximum font size is equivalent to 180x180 pixels in area - // w is total number of pixels to plot to fill character block - while (pc < w) - { - line = pgm_read_byte((uint8_t *)flash_address); - flash_address++; // 20 bytes smaller by incrementing here - if (line & 0x80) { - line &= 0x7F; - line++; - if (ts) { - px = x + textsize * (pc % width); // Keep these px and py calculations outside the loop as they are slow - py = y + textsize * (pc / width); - } - else { - px = x + pc % width; // Keep these px and py calculations outside the loop as they are slow - py = y + pc / width; - } - while (line--) { - pc++; - setWindow(px, py, px + ts, py + ts); - if (ts) { tnp = np; while (tnp--) writeColor(color); } - else writeColor(color); - - px += textsize; - - if (px >= (x + width * textsize)) - { - px = x; - py += textsize; - } - } - } - else { - line++; - pc += line; - } - } - } - // End of RLE font rendering -#endif return width * textsize; // x + } #ifdef SMOOTH_FONT -/*************************************************************************************** -** Function name: drawGlyph -** Description: Write a character to the sprite cursor position -*************************************************************************************x*/ -void TFT_eSprite::drawGlyph(uint16_t code) -{ - if (code < 0x21) - { - if (code == 0x20) { - if (_created) this->cursor_x += this->gFont.spaceWidth; - else this->cursor_x += this->gFont.spaceWidth; + /*************************************************************************************** + ** Function name: drawGlyph + ** Description: Write a character to the sprite cursor position + *************************************************************************************x*/ + void TFT_eSprite::drawGlyph(uint16_t code) { + if (code < 0x21) { + if (code == 0x20) { + if (_created) { + this->cursor_x += this->gFont.spaceWidth; + } else { + this->cursor_x += this->gFont.spaceWidth; + } + return; + } + + if (code == '\n') { + if (_created) { + this->cursor_x = 0; + this->cursor_y += this->gFont.yAdvance; + if (this->cursor_y >= _height) { + this->cursor_y = 0; + } + return; + } else { + cursor_x = 0; + cursor_y += gFont.yAdvance; + if (cursor_y >= _height) { + cursor_y = 0; + } + return; + } + } + } + uint16_t gNum = 0; + bool found = this->getUnicodeIndex(code, &gNum); + + uint16_t fg = this->textcolor; + uint16_t bg = this->textbgcolor; + + if (found) { + + bool newSprite = !_created; + + if (newSprite) { + createSprite(this->gWidth[gNum], this->gFont.yAdvance); + if (bg) { + fillSprite(bg); + } + this->cursor_x = -this->gdX[gNum]; + this->cursor_y = 0; + } + + this->fontFile.seek(this->gBitmap[gNum], fs::SeekSet); // This is slow for a significant position shift! + + uint8_t pbuffer[this->gWidth[gNum]]; + + int16_t xs = 0; + uint16_t dl = 0; + + for (int32_t y = 0; y < this->gHeight[gNum]; y++) { + this->fontFile.read(pbuffer, this->gWidth[gNum]); + for (int32_t x = 0; x < this->gWidth[gNum]; x++) { + uint8_t pixel = pbuffer[x]; + if (pixel) { + if (pixel != 0xFF) { + if (dl) { + drawFastHLine( xs, y + this->cursor_y + this->gFont.maxAscent - this->gdY[gNum], dl, fg); + dl = 0; + } + if (_bpp != 1) { + drawPixel(x + this->cursor_x + this->gdX[gNum], y + this->cursor_y + this->gFont.maxAscent - this->gdY[gNum], alphaBlend(pixel, fg, bg)); + } else if (pixel>127) { + drawPixel(x + this->cursor_x + this->gdX[gNum], y + this->cursor_y + this->gFont.maxAscent - this->gdY[gNum], fg); + } + } else { + if (dl == 0) { + xs = x + this->cursor_x + this->gdX[gNum]; + } + dl++; + } + } else { + if (dl) { + drawFastHLine( xs, y + this->cursor_y + this->gFont.maxAscent - this->gdY[gNum], dl, fg); + dl = 0; + } + } + } + if (dl) { + drawFastHLine( xs, y + this->cursor_y + this->gFont.maxAscent - this->gdY[gNum], dl, fg); + dl = 0; + } + } + + if (newSprite) { + pushSprite(this->cursor_x + this->gdX[gNum], this->cursor_y, bg); + deleteSprite(); + this->cursor_x += this->gxAdvance[gNum]; + } else { + this->cursor_x += this->gxAdvance[gNum]; + } + } else { + // Not a Unicode in font so draw a rectangle and move on cursor + drawRect(this->cursor_x, this->cursor_y + this->gFont.maxAscent - this->gFont.ascent, this->gFont.spaceWidth, this->gFont.ascent, fg); + this->cursor_x += this->gFont.spaceWidth + 1; + } + } + + + /*************************************************************************************** + ** Function name: printToSprite + ** Description: Write a string to the sprite cursor position + *************************************************************************************x*/ + void TFT_eSprite::printToSprite(String string) { + if (!this->fontLoaded) { + return; + } + uint16_t len = string.length(); + char cbuffer[len + 1]; // Add 1 for the null + string.toCharArray(cbuffer, len + 1); // Add 1 for the null, otherwise characters get dropped + printToSprite(cbuffer, len); + // printToSprite((char*)string.c_str(), string.length()); + } + + + /*************************************************************************************** + ** Function name: printToSprite + ** Description: Write a string to the sprite cursor position + *************************************************************************************x*/ + void TFT_eSprite::printToSprite(char *cbuffer, uint16_t len) { // String string) + if (!this->fontLoaded) { + return; + } + // fontFile = SPIFFS.open( this->_gFontFilename, "r" ); + + if (!this->fontFile) { + this->fontLoaded = false; return; } - if (code == '\n') { - if (_created) - { - this->cursor_x = 0; - this->cursor_y += this->gFont.yAdvance; - if (this->cursor_y >= _height) this->cursor_y = 0; - return; - } - else - { - cursor_x = 0; - cursor_y += gFont.yAdvance; - if (cursor_y >= _height) cursor_y = 0; - return; - } - } - } - - uint16_t gNum = 0; - bool found = this->getUnicodeIndex(code, &gNum); - - uint16_t fg = this->textcolor; - uint16_t bg = this->textbgcolor; - - if (found) - { - + uint16_t n = 0; bool newSprite = !_created; - if (newSprite) - { - createSprite(this->gWidth[gNum], this->gFont.yAdvance); - if(bg) fillSprite(bg); - this->cursor_x = -this->gdX[gNum]; - this->cursor_y = 0; - } + if (newSprite) { + int16_t sWidth = 0; + uint16_t index = 0; - this->fontFile.seek(this->gBitmap[gNum], fs::SeekSet); // This is slow for a significant position shift! - - uint8_t pbuffer[this->gWidth[gNum]]; - - int16_t xs = 0; - uint16_t dl = 0; - - for (int32_t y = 0; y < this->gHeight[gNum]; y++) - { - this->fontFile.read(pbuffer, this->gWidth[gNum]); - for (int32_t x = 0; x < this->gWidth[gNum]; x++) - { - uint8_t pixel = pbuffer[x]; - if (pixel) - { - if (pixel != 0xFF) - { - if (dl) { drawFastHLine( xs, y + this->cursor_y + this->gFont.maxAscent - this->gdY[gNum], dl, fg); dl = 0; } - if (_bpp != 1) drawPixel(x + this->cursor_x + this->gdX[gNum], y + this->cursor_y + this->gFont.maxAscent - this->gdY[gNum], alphaBlend(pixel, fg, bg)); - else if (pixel>127) drawPixel(x + this->cursor_x + this->gdX[gNum], y + this->cursor_y + this->gFont.maxAscent - this->gdY[gNum], fg); + while (n < len) { + uint16_t unicode = decodeUTF8((uint8_t*)cbuffer, &n, len - n); + if (this->getUnicodeIndex(unicode, &index)) { + if (n == 0) { + sWidth -= this->gdX[index]; } - else - { - if (dl==0) xs = x + this->cursor_x + this->gdX[gNum]; - dl++; + if (n == len-1) { + sWidth += ( this->gWidth[index] + this->gdX[index]); + } else { + sWidth += this->gxAdvance[index]; } - } - else - { - if (dl) { drawFastHLine( xs, y + this->cursor_y + this->gFont.maxAscent - this->gdY[gNum], dl, fg); dl = 0; } + } else { + sWidth += this->gFont.spaceWidth + 1; } } - if (dl) { drawFastHLine( xs, y + this->cursor_y + this->gFont.maxAscent - this->gdY[gNum], dl, fg); dl = 0; } + + createSprite(sWidth, this->gFont.yAdvance); + if (this->textbgcolor != TFT_BLACK) { + fillSprite(this->textbgcolor); + } } - if (newSprite) - { - pushSprite(this->cursor_x + this->gdX[gNum], this->cursor_y, bg); - deleteSprite(); - this->cursor_x += this->gxAdvance[gNum]; - } - else this->cursor_x += this->gxAdvance[gNum]; - } - else - { - // Not a Unicode in font so draw a rectangle and move on cursor - drawRect(this->cursor_x, this->cursor_y + this->gFont.maxAscent - this->gFont.ascent, this->gFont.spaceWidth, this->gFont.ascent, fg); - this->cursor_x += this->gFont.spaceWidth + 1; - } -} + n = 0; - -/*************************************************************************************** -** Function name: printToSprite -** Description: Write a string to the sprite cursor position -*************************************************************************************x*/ -void TFT_eSprite::printToSprite(String string) -{ - if(!this->fontLoaded) return; - uint16_t len = string.length(); - char cbuffer[len + 1]; // Add 1 for the null - string.toCharArray(cbuffer, len + 1); // Add 1 for the null, otherwise characters get dropped - printToSprite(cbuffer, len); - //printToSprite((char*)string.c_str(), string.length()); -} - - -/*************************************************************************************** -** Function name: printToSprite -** Description: Write a string to the sprite cursor position -*************************************************************************************x*/ -void TFT_eSprite::printToSprite(char *cbuffer, uint16_t len) //String string) -{ - if(!this->fontLoaded) return; - - //fontFile = SPIFFS.open( this->_gFontFilename, "r" ); - - if(!this->fontFile) - { - this->fontLoaded = false; - return; - } - - uint16_t n = 0; - bool newSprite = !_created; - - if (newSprite) - { - int16_t sWidth = 0; - uint16_t index = 0; - - while (n < len) - { + while (n < len) { uint16_t unicode = decodeUTF8((uint8_t*)cbuffer, &n, len - n); - if (this->getUnicodeIndex(unicode, &index)) - { - if (n == 0) sWidth -= this->gdX[index]; - if (n == len-1) sWidth += ( this->gWidth[index] + this->gdX[index]); - else sWidth += this->gxAdvance[index]; - } - else sWidth += this->gFont.spaceWidth + 1; + // Serial.print("Decoded Unicode = 0x");Serial.println(unicode,HEX); + // Serial.print("n = ");Serial.println(n); + drawGlyph(unicode); } - createSprite(sWidth, this->gFont.yAdvance); + if (newSprite) { // The sprite had to be created so place at TFT cursor + pushSprite(_tft->cursor_x, _tft->cursor_y); + deleteSprite(); + } - if (this->textbgcolor != TFT_BLACK) fillSprite(this->textbgcolor); + // fontFile.close(); } - n = 0; - while (n < len) - { - uint16_t unicode = decodeUTF8((uint8_t*)cbuffer, &n, len - n); - //Serial.print("Decoded Unicode = 0x");Serial.println(unicode,HEX); - //Serial.print("n = ");Serial.println(n); - drawGlyph(unicode); + /*************************************************************************************** + ** Function name: printToSprite + ** Description: Print character in a Sprite, create sprite if needed + *************************************************************************************x*/ + int16_t TFT_eSprite::printToSprite(int16_t x, int16_t y, uint16_t index) { + bool newSprite = !_created; + int16_t sWidth = this->gWidth[index]; + + if (newSprite) { + createSprite(sWidth, this->gFont.yAdvance); + + if (this->textbgcolor != TFT_BLACK) { + fillSprite(this->textbgcolor); + } + drawGlyph(this->gUnicode[index]); + + pushSprite(x + this->gdX[index], y, this->textbgcolor); + deleteSprite(); + } else { + drawGlyph(this->gUnicode[index]); + } + return this->gxAdvance[index]; } - - if (newSprite) - { // The sprite had to be created so place at TFT cursor - pushSprite(_tft->cursor_x, _tft->cursor_y); - deleteSprite(); - } - - //fontFile.close(); -} - - -/*************************************************************************************** -** Function name: printToSprite -** Description: Print character in a Sprite, create sprite if needed -*************************************************************************************x*/ -int16_t TFT_eSprite::printToSprite(int16_t x, int16_t y, uint16_t index) -{ - bool newSprite = !_created; - int16_t sWidth = this->gWidth[index]; - - if (newSprite) - { - createSprite(sWidth, this->gFont.yAdvance); - - if (this->textbgcolor != TFT_BLACK) fillSprite(this->textbgcolor); - - drawGlyph(this->gUnicode[index]); - - pushSprite(x + this->gdX[index], y, this->textbgcolor); - deleteSprite(); - } - - else drawGlyph(this->gUnicode[index]); - - return this->gxAdvance[index]; -} #endif diff --git a/src/utility/Sprite.h b/src/utility/Sprite.h index 6eccfaf..2cf93c0 100644 --- a/src/utility/Sprite.h +++ b/src/utility/Sprite.h @@ -7,141 +7,139 @@ #include "In_eSPI.h" class TFT_eSprite : public TFT_eSPI { + public: - public: + TFT_eSprite(TFT_eSPI *tft); - TFT_eSprite(TFT_eSPI *tft); + // Create a sprite of width x height pixels, return a pointer to the RAM area + // Sketch can cast returned value to (uint16_t*) for 16 bit depth if needed + // RAM required is 1 byte per pixel for 8 bit colour depth, 2 bytes for 16 bit + void* createSprite(int16_t width, int16_t height, uint8_t frames = 1); - // Create a sprite of width x height pixels, return a pointer to the RAM area - // Sketch can cast returned value to (uint16_t*) for 16 bit depth if needed - // RAM required is 1 byte per pixel for 8 bit colour depth, 2 bytes for 16 bit - void* createSprite(int16_t width, int16_t height, uint8_t frames = 1); + // Delete the sprite to free up the RAM + void deleteSprite(void); - // Delete the sprite to free up the RAM - void deleteSprite(void); + // Select the frame buffer for graphics + void* frameBuffer(int8_t f); - // Select the frame buffer for graphics - void* frameBuffer(int8_t f); + // Set or get the colour depth to 8 or 16 bits. Can be used to change depth an existing + // sprite, but clears it to black, returns a new pointer if sprite is re-created. + void* setColorDepth(int8_t b); + int8_t getColorDepth(void); - // Set or get the colour depth to 8 or 16 bits. Can be used to change depth an existing - // sprite, but clears it to black, returns a new pointer if sprite is re-created. - void* setColorDepth(int8_t b); - int8_t getColorDepth(void); + void setBitmapColor(uint16_t c, uint16_t b); - void setBitmapColor(uint16_t c, uint16_t b); + void drawPixel(int32_t x, int32_t y, uint32_t color); - void drawPixel(int32_t x, int32_t y, uint32_t color); + void drawChar(int32_t x, int32_t y, unsigned char c, uint32_t color, uint32_t bg, uint8_t size), - void drawChar(int32_t x, int32_t y, unsigned char c, uint32_t color, uint32_t bg, uint8_t size), + fillSprite(uint32_t color), - fillSprite(uint32_t color), + // Define a window to push 16 bit colour pixels into in a raster order + // Colours are converted to 8 bit if depth is set to 8 + setWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1), + pushColor(uint32_t color), + pushColor(uint32_t color, uint16_t len), + // Push a pixel preformatted as a 8 or 16 bit colour (avoids conversion overhead) + writeColor(uint16_t color), - // Define a window to push 16 bit colour pixels into in a raster order - // Colours are converted to 8 bit if depth is set to 8 - setWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1), - pushColor(uint32_t color), - pushColor(uint32_t color, uint16_t len), - // Push a pixel preformatted as a 8 or 16 bit colour (avoids conversion overhead) - writeColor(uint16_t color), + // Set the scroll zone, top left corner at x,y with defined width and height + // The colour (optional, black is default) is used to fill the gap after the scroll + setScrollRect(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t color = TFT_BLACK), + // Scroll the defined zone dx,dy pixels. Negative values left,up, positive right,down + // dy is optional (default is then no up/down scroll). + // The sprite coordinate frame does not move because pixels are moved + scroll(int16_t dx, int16_t dy = 0), - // Set the scroll zone, top left corner at x,y with defined width and height - // The colour (optional, black is default) is used to fill the gap after the scroll - setScrollRect(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t color = TFT_BLACK), - // Scroll the defined zone dx,dy pixels. Negative values left,up, positive right,down - // dy is optional (default is then no up/down scroll). - // The sprite coordinate frame does not move because pixels are moved - scroll(int16_t dx, int16_t dy = 0), + drawLine(int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint32_t color), + drawFastVLine(int32_t x, int32_t y, int32_t h, uint32_t color), + drawFastHLine(int32_t x, int32_t y, int32_t w, uint32_t color), - drawLine(int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint32_t color), - drawFastVLine(int32_t x, int32_t y, int32_t h, uint32_t color), - drawFastHLine(int32_t x, int32_t y, int32_t w, uint32_t color), + fillRect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t color); - fillRect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t color); + // Set the sprite text cursor position for print class (does not change the TFT screen cursor) + //setCursor(int16_t x, int16_t y); - // Set the sprite text cursor position for print class (does not change the TFT screen cursor) - //setCursor(int16_t x, int16_t y); + // Set the rotation of the Sprite (for 1bpp Sprites only) + void setRotation(uint8_t rotation); + uint8_t getRotation(void); - // Set the rotation of the Sprite (for 1bpp Sprites only) - void setRotation(uint8_t rotation); - uint8_t getRotation(void); + // Push a rotated copy of Sprite to TFT with optional transparent colour + bool pushRotated(int16_t angle, int32_t transp = -1); + // Push a rotated copy of Sprite to another different Sprite with optional transparent colour + bool pushRotated(TFT_eSprite *spr, int16_t angle, int32_t transp = -1); + // Set and get the pivot point for this Sprite + void setPivot(int16_t x, int16_t y); + int16_t getPivotX(void), + getPivotY(void); - // Push a rotated copy of Sprite to TFT with optional transparent colour - bool pushRotated(int16_t angle, int32_t transp = -1); - // Push a rotated copy of Sprite to another different Sprite with optional transparent colour - bool pushRotated(TFT_eSprite *spr, int16_t angle, int32_t transp = -1); - // Set and get the pivot point for this Sprite - void setPivot(int16_t x, int16_t y); - int16_t getPivotX(void), - getPivotY(void); + // Get the bounding box for a rotated copy of this Sprite + void getRotatedBounds(float sina, float cosa, int16_t w, int16_t h, int16_t xp, int16_t yp, + int16_t *min_x, int16_t *min_y, int16_t *max_x, int16_t *max_y); - // Get the bounding box for a rotated copy of this Sprite - void getRotatedBounds(float sina, float cosa, int16_t w, int16_t h, int16_t xp, int16_t yp, - int16_t *min_x, int16_t *min_y, int16_t *max_x, int16_t *max_y); + // Read the colour of a pixel at x,y and return value in 565 format + uint16_t readPixel(int32_t x0, int32_t y0); - // Read the colour of a pixel at x,y and return value in 565 format - uint16_t readPixel(int32_t x0, int32_t y0); + // Write an image (colour bitmap) to the sprite + void pushImage(int32_t x0, int32_t y0, int32_t w, int32_t h, uint16_t *data); + void pushImage(int32_t x0, int32_t y0, int32_t w, int32_t h, const uint16_t *data); - // Write an image (colour bitmap) to the sprite - void pushImage(int32_t x0, int32_t y0, int32_t w, int32_t h, uint16_t *data); - void pushImage(int32_t x0, int32_t y0, int32_t w, int32_t h, const uint16_t *data); + // Swap the byte order for pushImage() - corrects different image endianness + void setSwapBytes(bool swap); + bool getSwapBytes(void); - // Swap the byte order for pushImage() - corrects different image endianness - void setSwapBytes(bool swap); - bool getSwapBytes(void); + // Push the sprite to the TFT screen, this fn calls pushImage() in the TFT class. + // Optionally a "transparent" colour can be defined, pixels of that colour will not be rendered + void pushSprite(int32_t x, int32_t y); + void pushSprite(int32_t x, int32_t y, uint16_t transparent); - // Push the sprite to the TFT screen, this fn calls pushImage() in the TFT class. - // Optionally a "transparent" colour can be defined, pixels of that colour will not be rendered - void pushSprite(int32_t x, int32_t y); - void pushSprite(int32_t x, int32_t y, uint16_t transparent); + int16_t drawChar(uint16_t uniCode, int32_t x, int32_t y, uint8_t font), + drawChar(uint16_t uniCode, int32_t x, int32_t y); - int16_t drawChar(uint16_t uniCode, int32_t x, int32_t y, uint8_t font), - drawChar(uint16_t uniCode, int32_t x, int32_t y); + // Return the width and height of the sprite + int16_t width(void), + height(void); - // Return the width and height of the sprite - int16_t width(void), - height(void); + // Used by print class to print text to cursor position + size_t write(uint8_t); - // Used by print class to print text to cursor position - size_t write(uint8_t); + // Functions associated with anti-aliased fonts + void drawGlyph(uint16_t code); + void printToSprite(String string); + void printToSprite(char *cbuffer, uint16_t len); + int16_t printToSprite(int16_t x, int16_t y, uint16_t index); - // Functions associated with anti-aliased fonts - void drawGlyph(uint16_t code); - void printToSprite(String string); - void printToSprite(char *cbuffer, uint16_t len); - int16_t printToSprite(int16_t x, int16_t y, uint16_t index); + private: - private: + TFT_eSPI *_tft; - TFT_eSPI *_tft; + // Reserve memory for the Sprite and return a pointer + void* callocSprite(int16_t width, int16_t height, uint8_t frames = 1); - // Reserve memory for the Sprite and return a pointer - void* callocSprite(int16_t width, int16_t height, uint8_t frames = 1); + protected: - protected: + uint8_t _bpp; // bits per pixel (1, 8 or 16) + uint16_t *_img; // pointer to 16 bit sprite + uint8_t *_img8; // pointer to 8 bit sprite + uint8_t *_img8_1; // pointer to frame 1 + uint8_t *_img8_2; // pointer to frame 2 - uint8_t _bpp; // bits per pixel (1, 8 or 16) - uint16_t *_img; // pointer to 16 bit sprite - uint8_t *_img8; // pointer to 8 bit sprite - uint8_t *_img8_1; // pointer to frame 1 - uint8_t *_img8_2; // pointer to frame 2 + int16_t _xpivot; // x pivot point coordinate + int16_t _ypivot; // y pivot point coordinate - int16_t _xpivot; // x pivot point coordinate - int16_t _ypivot; // y pivot point coordinate + bool _created; // A Sprite has been created and memory reserved + bool _gFont = false; - bool _created; // A Sprite has been created and memory reserved - bool _gFont = false; + // int32_t _icursor_x, _icursor_y; + uint8_t _rotation = 0; + int32_t _xs, _ys, _xe, _ye, _xptr, _yptr; // for setWindow + int32_t _sx, _sy; // x,y for scroll zone + uint32_t _sw, _sh; // w,h for scroll zone + uint32_t _scolor; // gap fill colour for scroll zone -// int32_t _icursor_x, _icursor_y; - uint8_t _rotation = 0; - int32_t _xs, _ys, _xe, _ye, _xptr, _yptr; // for setWindow - int32_t _sx, _sy; // x,y for scroll zone - uint32_t _sw, _sh; // w,h for scroll zone - uint32_t _scolor; // gap fill colour for scroll zone - - boolean _iswapBytes; // Swap the byte order for Sprite pushImage() - - int32_t _iwidth, _iheight; // Sprite memory image bit width and height (swapped during rotations) - int32_t _dwidth, _dheight; // Real display width and height (for <8bpp Sprites) - int32_t _bitwidth; // Sprite image bit width for drawPixel (for <8bpp Sprites, not swapped) + boolean _iswapBytes; // Swap the byte order for Sprite pushImage() + int32_t _iwidth, _iheight; // Sprite memory image bit width and height (swapped during rotations) + int32_t _dwidth, _dheight; // Real display width and height (for <8bpp Sprites) + int32_t _bitwidth; // Sprite image bit width for drawPixel (for <8bpp Sprites, not swapped) }; diff --git a/src/utility/qrcode.c b/src/utility/qrcode.c index 92e606e..d45ff99 100755 --- a/src/utility/qrcode.c +++ b/src/utility/qrcode.c @@ -38,61 +38,58 @@ #if LOCK_VERSION == 0 -static const uint16_t NUM_ERROR_CORRECTION_CODEWORDS[4][40] = { + static const uint16_t NUM_ERROR_CORRECTION_CODEWORDS[4][40] = { // 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40 Error correction level { 10, 16, 26, 36, 48, 64, 72, 88, 110, 130, 150, 176, 198, 216, 240, 280, 308, 338, 364, 416, 442, 476, 504, 560, 588, 644, 700, 728, 784, 812, 868, 924, 980, 1036, 1064, 1120, 1204, 1260, 1316, 1372}, // Medium { 7, 10, 15, 20, 26, 36, 40, 48, 60, 72, 80, 96, 104, 120, 132, 144, 168, 180, 196, 224, 224, 252, 270, 300, 312, 336, 360, 390, 420, 450, 480, 510, 540, 570, 570, 600, 630, 660, 720, 750}, // Low { 17, 28, 44, 64, 88, 112, 130, 156, 192, 224, 264, 308, 352, 384, 432, 480, 532, 588, 650, 700, 750, 816, 900, 960, 1050, 1110, 1200, 1260, 1350, 1440, 1530, 1620, 1710, 1800, 1890, 1980, 2100, 2220, 2310, 2430}, // High { 13, 22, 36, 52, 72, 96, 108, 132, 160, 192, 224, 260, 288, 320, 360, 408, 448, 504, 546, 600, 644, 690, 750, 810, 870, 952, 1020, 1050, 1140, 1200, 1290, 1350, 1440, 1530, 1590, 1680, 1770, 1860, 1950, 2040}, // Quartile -}; + }; -static const uint8_t NUM_ERROR_CORRECTION_BLOCKS[4][40] = { + static const uint8_t NUM_ERROR_CORRECTION_BLOCKS[4][40] = { // Version: (note that index 0 is for padding, and is set to an illegal value) // 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40 Error correction level { 1, 1, 1, 2, 2, 4, 4, 4, 5, 5, 5, 8, 9, 9, 10, 10, 11, 13, 14, 16, 17, 17, 18, 20, 21, 23, 25, 26, 28, 29, 31, 33, 35, 37, 38, 40, 43, 45, 47, 49}, // Medium { 1, 1, 1, 1, 1, 2, 2, 2, 2, 4, 4, 4, 4, 4, 6, 6, 6, 6, 7, 8, 8, 9, 9, 10, 12, 12, 12, 13, 14, 15, 16, 17, 18, 19, 19, 20, 21, 22, 24, 25}, // Low { 1, 1, 2, 4, 4, 4, 5, 6, 8, 8, 11, 11, 16, 16, 18, 16, 19, 21, 25, 25, 25, 34, 30, 32, 35, 37, 40, 42, 45, 48, 51, 54, 57, 60, 63, 66, 70, 74, 77, 81}, // High { 1, 1, 2, 2, 4, 4, 6, 6, 8, 8, 8, 10, 12, 16, 12, 17, 16, 18, 21, 20, 23, 23, 25, 27, 29, 34, 34, 35, 38, 40, 43, 45, 48, 51, 53, 56, 59, 62, 65, 68}, // Quartile -}; + }; -static const uint16_t NUM_RAW_DATA_MODULES[40] = { + static const uint16_t NUM_RAW_DATA_MODULES[40] = { // 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, - 208, 359, 567, 807, 1079, 1383, 1568, 1936, 2336, 2768, 3232, 3728, 4256, 4651, 5243, 5867, 6523, + 208, 359, 567, 807, 1079, 1383, 1568, 1936, 2336, 2768, 3232, 3728, 4256, 4651, 5243, 5867, 6523, // 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - 7211, 7931, 8683, 9252, 10068, 10916, 11796, 12708, 13652, 14628, 15371, 16411, 17483, 18587, + 7211, 7931, 8683, 9252, 10068, 10916, 11796, 12708, 13652, 14628, 15371, 16411, 17483, 18587, // 32, 33, 34, 35, 36, 37, 38, 39, 40 - 19723, 20891, 22091, 23008, 24272, 25568, 26896, 28256, 29648 -}; + 19723, 20891, 22091, 23008, 24272, 25568, 26896, 28256, 29648 + }; // @TODO: Put other LOCK_VERSIONS here #elif LOCK_VERSION == 3 -static const int16_t NUM_ERROR_CORRECTION_CODEWORDS[4] = { + static const int16_t NUM_ERROR_CORRECTION_CODEWORDS[4] = { 26, 15, 44, 36 -}; + }; -static const int8_t NUM_ERROR_CORRECTION_BLOCKS[4] = { + static const int8_t NUM_ERROR_CORRECTION_BLOCKS[4] = { 1, 1, 2, 2 -}; - -static const uint16_t NUM_RAW_DATA_MODULES = 567; + }; + static const uint16_t NUM_RAW_DATA_MODULES = 567; #else - -#error Unsupported LOCK_VERSION (add it...) - + #error Unsupported LOCK_VERSION (add it...) #endif static int max(int a, int b) { - if (a > b) { return a; } - return b; + if (a > b) { return a; } + return b; } /* static int abs(int value) { - if (value < 0) { return -value; } - return value; + if (value < 0) { return -value; } + return value; } */ @@ -100,39 +97,38 @@ static int abs(int value) { //#pragma mark - Mode testing and conversion static int8_t getAlphanumeric(char c) { - - if (c >= '0' && c <= '9') { return (c - '0'); } - if (c >= 'A' && c <= 'Z') { return (c - 'A' + 10); } - - switch (c) { - case ' ': return 36; - case '$': return 37; - case '%': return 38; - case '*': return 39; - case '+': return 40; - case '-': return 41; - case '.': return 42; - case '/': return 43; - case ':': return 44; - } - - return -1; + + if (c >= '0' && c <= '9') { return (c - '0'); } + if (c >= 'A' && c <= 'Z') { return (c - 'A' + 10); } + + switch (c) { + case ' ': return 36; + case '$': return 37; + case '%': return 38; + case '*': return 39; + case '+': return 40; + case '-': return 41; + case '.': return 42; + case '/': return 43; + case ':': return 44; + } + return -1; } static bool isAlphanumeric(const char *text, uint16_t length) { - while (length != 0) { - if (getAlphanumeric(text[--length]) == -1) { return false; } - } - return true; + while (length != 0) { + if (getAlphanumeric(text[--length]) == -1) { return false; } + } + return true; } static bool isNumeric(const char *text, uint16_t length) { - while (length != 0) { - char c = text[--length]; - if (c < '0' || c > '9') { return false; } - } - return true; + while (length != 0) { + char c = text[--length]; + if (c < '0' || c > '9') { return false; } + } + return true; } @@ -144,106 +140,103 @@ static bool isNumeric(const char *text, uint16_t length) { // ALPHANUMERIC ( 9, 11, 13); // BYTE ( 8, 16, 16); static char getModeBits(uint8_t version, uint8_t mode) { - // Note: We use 15 instead of 16; since 15 doesn't exist and we cannot store 16 (8 + 8) in 3 bits - // hex(int("".join(reversed([('00' + bin(x - 8)[2:])[-3:] for x in [10, 9, 8, 12, 11, 15, 14, 13, 15]])), 2)) - unsigned int modeInfo = 0x7bbb80a; - -#if LOCK_VERSION == 0 || LOCK_VERSION > 9 + // Note: We use 15 instead of 16; since 15 doesn't exist and we cannot store 16 (8 + 8) in 3 bits + // hex(int("".join(reversed([('00' + bin(x - 8)[2:])[-3:] for x in [10, 9, 8, 12, 11, 15, 14, 13, 15]])), 2)) + unsigned int modeInfo = 0x7bbb80a; + + #if LOCK_VERSION == 0 || LOCK_VERSION > 9 if (version > 9) { modeInfo >>= 9; } -#endif - -#if LOCK_VERSION == 0 || LOCK_VERSION > 26 + #endif + + #if LOCK_VERSION == 0 || LOCK_VERSION > 26 if (version > 26) { modeInfo >>= 9; } -#endif - - char result = 8 + ((modeInfo >> (3 * mode)) & 0x07); - if (result == 15) { result = 16; } - - return result; + #endif + + char result = 8 + ((modeInfo >> (3 * mode)) & 0x07); + if (result == 15) { result = 16; } + return result; } //#pragma mark - BitBucket - typedef struct BitBucket { - uint32_t bitOffsetOrWidth; - uint16_t capacityBytes; - uint8_t *data; + uint32_t bitOffsetOrWidth; + uint16_t capacityBytes; + uint8_t *data; } BitBucket; /* void bb_dump(BitBucket *bitBuffer) { - printf("Buffer: "); - for (uint32_t i = 0; i < bitBuffer->capacityBytes; i++) { - printf("%02x", bitBuffer->data[i]); - if ((i % 4) == 3) { printf(" "); } - } - printf("\n"); + printf("Buffer: "); + for (uint32_t i = 0; i < bitBuffer->capacityBytes; i++) { + printf("%02x", bitBuffer->data[i]); + if ((i % 4) == 3) { printf(" "); } + } + printf("\n"); } */ static uint16_t bb_getGridSizeBytes(uint8_t size) { - return (((size * size) + 7) / 8); + return (((size * size) + 7) / 8); } static uint16_t bb_getBufferSizeBytes(uint32_t bits) { - return ((bits + 7) / 8); + return ((bits + 7) / 8); } static void bb_initBuffer(BitBucket *bitBuffer, uint8_t *data, int32_t capacityBytes) { - bitBuffer->bitOffsetOrWidth = 0; - bitBuffer->capacityBytes = capacityBytes; - bitBuffer->data = data; - - memset(data, 0, bitBuffer->capacityBytes); + bitBuffer->bitOffsetOrWidth = 0; + bitBuffer->capacityBytes = capacityBytes; + bitBuffer->data = data; + + memset(data, 0, bitBuffer->capacityBytes); } static void bb_initGrid(BitBucket *bitGrid, uint8_t *data, uint8_t size) { - bitGrid->bitOffsetOrWidth = size; - bitGrid->capacityBytes = bb_getGridSizeBytes(size); - bitGrid->data = data; - - memset(data, 0, bitGrid->capacityBytes); + bitGrid->bitOffsetOrWidth = size; + bitGrid->capacityBytes = bb_getGridSizeBytes(size); + bitGrid->data = data; + memset(data, 0, bitGrid->capacityBytes); } static void bb_appendBits(BitBucket *bitBuffer, uint32_t val, uint8_t length) { - uint32_t offset = bitBuffer->bitOffsetOrWidth; - for (int8_t i = length - 1; i >= 0; i--, offset++) { - bitBuffer->data[offset >> 3] |= ((val >> i) & 1) << (7 - (offset & 7)); - } - bitBuffer->bitOffsetOrWidth = offset; + uint32_t offset = bitBuffer->bitOffsetOrWidth; + for (int8_t i = length - 1; i >= 0; i--, offset++) { + bitBuffer->data[offset >> 3] |= ((val >> i) & 1) << (7 - (offset & 7)); + } + bitBuffer->bitOffsetOrWidth = offset; } /* void bb_setBits(BitBucket *bitBuffer, uint32_t val, int offset, uint8_t length) { - for (int8_t i = length - 1; i >= 0; i--, offset++) { - bitBuffer->data[offset >> 3] |= ((val >> i) & 1) << (7 - (offset & 7)); - } + for (int8_t i = length - 1; i >= 0; i--, offset++) { + bitBuffer->data[offset >> 3] |= ((val >> i) & 1) << (7 - (offset & 7)); + } } */ static void bb_setBit(BitBucket *bitGrid, uint8_t x, uint8_t y, bool on) { - uint32_t offset = y * bitGrid->bitOffsetOrWidth + x; - uint8_t mask = 1 << (7 - (offset & 0x07)); - if (on) { - bitGrid->data[offset >> 3] |= mask; - } else { - bitGrid->data[offset >> 3] &= ~mask; - } + uint32_t offset = y * bitGrid->bitOffsetOrWidth + x; + uint8_t mask = 1 << (7 - (offset & 0x07)); + if (on) { + bitGrid->data[offset >> 3] |= mask; + } else { + bitGrid->data[offset >> 3] &= ~mask; + } } static void bb_invertBit(BitBucket *bitGrid, uint8_t x, uint8_t y, bool invert) { - uint32_t offset = y * bitGrid->bitOffsetOrWidth + x; - uint8_t mask = 1 << (7 - (offset & 0x07)); - bool on = ((bitGrid->data[offset >> 3] & (1 << (7 - (offset & 0x07)))) != 0); - if (on ^ invert) { - bitGrid->data[offset >> 3] |= mask; - } else { - bitGrid->data[offset >> 3] &= ~mask; - } + uint32_t offset = y * bitGrid->bitOffsetOrWidth + x; + uint8_t mask = 1 << (7 - (offset & 0x07)); + bool on = ((bitGrid->data[offset >> 3] & (1 << (7 - (offset & 0x07)))) != 0); + if (on ^ invert) { + bitGrid->data[offset >> 3] |= mask; + } else { + bitGrid->data[offset >> 3] &= ~mask; + } } static bool bb_getBit(BitBucket *bitGrid, uint8_t x, uint8_t y) { - uint32_t offset = y * bitGrid->bitOffsetOrWidth + x; - return (bitGrid->data[offset >> 3] & (1 << (7 - (offset & 0x07)))) != 0; + uint32_t offset = y * bitGrid->bitOffsetOrWidth + x; + return (bitGrid->data[offset >> 3] & (1 << (7 - (offset & 0x07)))) != 0; } @@ -254,119 +247,118 @@ static bool bb_getBit(BitBucket *bitGrid, uint8_t x, uint8_t y) { // This means it is possible to apply a mask, undo it, and try another mask. Note that a final // well-formed QR Code symbol needs exactly one mask applied (not zero, not two, etc.). static void applyMask(BitBucket *modules, BitBucket *isFunction, uint8_t mask) { - uint8_t size = modules->bitOffsetOrWidth; - - for (uint8_t y = 0; y < size; y++) { - for (uint8_t x = 0; x < size; x++) { - if (bb_getBit(isFunction, x, y)) { continue; } - - bool invert = 0; - switch (mask) { - case 0: invert = (x + y) % 2 == 0; break; - case 1: invert = y % 2 == 0; break; - case 2: invert = x % 3 == 0; break; - case 3: invert = (x + y) % 3 == 0; break; - case 4: invert = (x / 3 + y / 2) % 2 == 0; break; - case 5: invert = x * y % 2 + x * y % 3 == 0; break; - case 6: invert = (x * y % 2 + x * y % 3) % 2 == 0; break; - case 7: invert = ((x + y) % 2 + x * y % 3) % 2 == 0; break; - } - bb_invertBit(modules, x, y, invert); - } + uint8_t size = modules->bitOffsetOrWidth; + + for (uint8_t y = 0; y < size; y++) { + for (uint8_t x = 0; x < size; x++) { + if (bb_getBit(isFunction, x, y)) { continue; } + + bool invert = 0; + switch (mask) { + case 0: invert = (x + y) % 2 == 0; break; + case 1: invert = y % 2 == 0; break; + case 2: invert = x % 3 == 0; break; + case 3: invert = (x + y) % 3 == 0; break; + case 4: invert = (x / 3 + y / 2) % 2 == 0; break; + case 5: invert = x * y % 2 + x * y % 3 == 0; break; + case 6: invert = (x * y % 2 + x * y % 3) % 2 == 0; break; + case 7: invert = ((x + y) % 2 + x * y % 3) % 2 == 0; break; + } + bb_invertBit(modules, x, y, invert); } + } } static void setFunctionModule(BitBucket *modules, BitBucket *isFunction, uint8_t x, uint8_t y, bool on) { - bb_setBit(modules, x, y, on); - bb_setBit(isFunction, x, y, true); + bb_setBit(modules, x, y, on); + bb_setBit(isFunction, x, y, true); } // Draws a 9*9 finder pattern including the border separator, with the center module at (x, y). static void drawFinderPattern(BitBucket *modules, BitBucket *isFunction, uint8_t x, uint8_t y) { - uint8_t size = modules->bitOffsetOrWidth; + uint8_t size = modules->bitOffsetOrWidth; - for (int8_t i = -4; i <= 4; i++) { - for (int8_t j = -4; j <= 4; j++) { - uint8_t dist = max(abs(i), abs(j)); // Chebyshev/infinity norm - int16_t xx = x + j, yy = y + i; - if (0 <= xx && xx < size && 0 <= yy && yy < size) { - setFunctionModule(modules, isFunction, xx, yy, dist != 2 && dist != 4); - } - } + for (int8_t i = -4; i <= 4; i++) { + for (int8_t j = -4; j <= 4; j++) { + uint8_t dist = max(abs(i), abs(j)); // Chebyshev/infinity norm + int16_t xx = x + j, yy = y + i; + if (0 <= xx && xx < size && 0 <= yy && yy < size) { + setFunctionModule(modules, isFunction, xx, yy, dist != 2 && dist != 4); + } } + } } // Draws a 5*5 alignment pattern, with the center module at (x, y). static void drawAlignmentPattern(BitBucket *modules, BitBucket *isFunction, uint8_t x, uint8_t y) { - for (int8_t i = -2; i <= 2; i++) { - for (int8_t j = -2; j <= 2; j++) { - setFunctionModule(modules, isFunction, x + j, y + i, max(abs(i), abs(j)) != 1); - } + for (int8_t i = -2; i <= 2; i++) { + for (int8_t j = -2; j <= 2; j++) { + setFunctionModule(modules, isFunction, x + j, y + i, max(abs(i), abs(j)) != 1); } + } } // Draws two copies of the format bits (with its own error correction code) // based on the given mask and this object's error correction level field. static void drawFormatBits(BitBucket *modules, BitBucket *isFunction, uint8_t ecc, uint8_t mask) { - - uint8_t size = modules->bitOffsetOrWidth; - // Calculate error correction code and pack bits - uint32_t data = ecc << 3 | mask; // errCorrLvl is uint2, mask is uint3 - uint32_t rem = data; - for (int i = 0; i < 10; i++) { - rem = (rem << 1) ^ ((rem >> 9) * 0x537); - } - - data = data << 10 | rem; - data ^= 0x5412; // uint15 - - // Draw first copy - for (uint8_t i = 0; i <= 5; i++) { - setFunctionModule(modules, isFunction, 8, i, ((data >> i) & 1) != 0); - } - - setFunctionModule(modules, isFunction, 8, 7, ((data >> 6) & 1) != 0); - setFunctionModule(modules, isFunction, 8, 8, ((data >> 7) & 1) != 0); - setFunctionModule(modules, isFunction, 7, 8, ((data >> 8) & 1) != 0); - - for (int8_t i = 9; i < 15; i++) { - setFunctionModule(modules, isFunction, 14 - i, 8, ((data >> i) & 1) != 0); - } - - // Draw second copy - for (int8_t i = 0; i <= 7; i++) { - setFunctionModule(modules, isFunction, size - 1 - i, 8, ((data >> i) & 1) != 0); - } - - for (int8_t i = 8; i < 15; i++) { - setFunctionModule(modules, isFunction, 8, size - 15 + i, ((data >> i) & 1) != 0); - } - - setFunctionModule(modules, isFunction, 8, size - 8, true); + uint8_t size = modules->bitOffsetOrWidth; + + // Calculate error correction code and pack bits + uint32_t data = ecc << 3 | mask; // errCorrLvl is uint2, mask is uint3 + uint32_t rem = data; + for (int i = 0; i < 10; i++) { + rem = (rem << 1) ^ ((rem >> 9) * 0x537); + } + + data = data << 10 | rem; + data ^= 0x5412; // uint15 + + // Draw first copy + for (uint8_t i = 0; i <= 5; i++) { + setFunctionModule(modules, isFunction, 8, i, ((data >> i) & 1) != 0); + } + + setFunctionModule(modules, isFunction, 8, 7, ((data >> 6) & 1) != 0); + setFunctionModule(modules, isFunction, 8, 8, ((data >> 7) & 1) != 0); + setFunctionModule(modules, isFunction, 7, 8, ((data >> 8) & 1) != 0); + + for (int8_t i = 9; i < 15; i++) { + setFunctionModule(modules, isFunction, 14 - i, 8, ((data >> i) & 1) != 0); + } + + // Draw second copy + for (int8_t i = 0; i <= 7; i++) { + setFunctionModule(modules, isFunction, size - 1 - i, 8, ((data >> i) & 1) != 0); + } + + for (int8_t i = 8; i < 15; i++) { + setFunctionModule(modules, isFunction, 8, size - 15 + i, ((data >> i) & 1) != 0); + } + + setFunctionModule(modules, isFunction, 8, size - 8, true); } // Draws two copies of the version bits (with its own error correction code), // based on this object's version field (which only has an effect for 7 <= version <= 40). static void drawVersion(BitBucket *modules, BitBucket *isFunction, uint8_t version) { - - int8_t size = modules->bitOffsetOrWidth; -#if LOCK_VERSION != 0 && LOCK_VERSION < 7 + int8_t size = modules->bitOffsetOrWidth; + + #if LOCK_VERSION != 0 && LOCK_VERSION < 7 return; - -#else + #else if (version < 7) { return; } - + // Calculate error correction code and pack bits uint32_t rem = version; // version is uint6, in the range [7, 40] for (uint8_t i = 0; i < 12; i++) { rem = (rem << 1) ^ ((rem >> 11) * 0x1F25); } - + uint32_t data = version << 12 | rem; // uint18 - + // Draw two copies for (uint8_t i = 0; i < 18; i++) { bool bit = ((data >> i) & 1) != 0; @@ -374,98 +366,98 @@ static void drawVersion(BitBucket *modules, BitBucket *isFunction, uint8_t versi setFunctionModule(modules, isFunction, a, b, bit); setFunctionModule(modules, isFunction, b, a, bit); } - -#endif + #endif } static void drawFunctionPatterns(BitBucket *modules, BitBucket *isFunction, uint8_t version, uint8_t ecc) { - - uint8_t size = modules->bitOffsetOrWidth; - // Draw the horizontal and vertical timing patterns - for (uint8_t i = 0; i < size; i++) { - setFunctionModule(modules, isFunction, 6, i, i % 2 == 0); - setFunctionModule(modules, isFunction, i, 6, i % 2 == 0); - } - - // Draw 3 finder patterns (all corners except bottom right; overwrites some timing modules) - drawFinderPattern(modules, isFunction, 3, 3); - drawFinderPattern(modules, isFunction, size - 4, 3); - drawFinderPattern(modules, isFunction, 3, size - 4); - -#if LOCK_VERSION == 0 || LOCK_VERSION > 1 + uint8_t size = modules->bitOffsetOrWidth; + + // Draw the horizontal and vertical timing patterns + for (uint8_t i = 0; i < size; i++) { + setFunctionModule(modules, isFunction, 6, i, i % 2 == 0); + setFunctionModule(modules, isFunction, i, 6, i % 2 == 0); + } + + // Draw 3 finder patterns (all corners except bottom right; overwrites some timing modules) + drawFinderPattern(modules, isFunction, 3, 3); + drawFinderPattern(modules, isFunction, size - 4, 3); + drawFinderPattern(modules, isFunction, 3, size - 4); + + #if LOCK_VERSION == 0 || LOCK_VERSION > 1 if (version > 1) { - // Draw the numerous alignment patterns - - uint8_t alignCount = version / 7 + 2; - uint8_t step; - if (version != 32) { - step = (version * 4 + alignCount * 2 + 1) / (2 * alignCount - 2) * 2; // ceil((size - 13) / (2*numAlign - 2)) * 2 - } else { // C-C-C-Combo breaker! - step = 26; - } - - uint8_t alignPositionIndex = alignCount - 1; - uint8_t alignPosition[alignCount]; - - alignPosition[0] = 6; - - uint8_t size = version * 4 + 17; - for (uint8_t i = 0, pos = size - 7; i < alignCount - 1; i++, pos -= step) { - alignPosition[alignPositionIndex--] = pos; - } - - for (uint8_t i = 0; i < alignCount; i++) { - for (uint8_t j = 0; j < alignCount; j++) { - if ((i == 0 && j == 0) || (i == 0 && j == alignCount - 1) || (i == alignCount - 1 && j == 0)) { - continue; // Skip the three finder corners - } else { - drawAlignmentPattern(modules, isFunction, alignPosition[i], alignPosition[j]); - } - } + // Draw the numerous alignment patterns + + uint8_t alignCount = version / 7 + 2; + uint8_t step; + if (version != 32) { + step = (version * 4 + alignCount * 2 + 1) / (2 * alignCount - 2) * 2; // ceil((size - 13) / (2*numAlign - 2)) * 2 + } else { // C-C-C-Combo breaker! + step = 26; + } + + uint8_t alignPositionIndex = alignCount - 1; + uint8_t alignPosition[alignCount]; + + alignPosition[0] = 6; + + uint8_t size = version * 4 + 17; + for (uint8_t i = 0, pos = size - 7; i < alignCount - 1; i++, pos -= step) { + alignPosition[alignPositionIndex--] = pos; + } + + for (uint8_t i = 0; i < alignCount; i++) { + for (uint8_t j = 0; j < alignCount; j++) { + if ((i == 0 && j == 0) || (i == 0 && j == alignCount - 1) || (i == alignCount - 1 && j == 0)) { + continue; // Skip the three finder corners + } else { + drawAlignmentPattern(modules, isFunction, alignPosition[i], alignPosition[j]); + } } + } } - -#endif - - // Draw configuration data - drawFormatBits(modules, isFunction, ecc, 0); // Dummy mask value; overwritten later in the constructor - drawVersion(modules, isFunction, version); + #endif + + // Draw configuration data + drawFormatBits(modules, isFunction, ecc, 0); // Dummy mask value; overwritten later in the constructor + drawVersion(modules, isFunction, version); } // Draws the given sequence of 8-bit codewords (data and error correction) onto the entire // data area of this QR Code symbol. Function modules need to be marked off before this is called. static void drawCodewords(BitBucket *modules, BitBucket *isFunction, BitBucket *codewords) { - - uint32_t bitLength = codewords->bitOffsetOrWidth; - uint8_t *data = codewords->data; - - uint8_t size = modules->bitOffsetOrWidth; - - // Bit index into the data - uint32_t i = 0; - - // Do the funny zigzag scan - for (int16_t right = size - 1; right >= 1; right -= 2) { // Index of right column in each column pair - if (right == 6) { right = 5; } - - for (uint8_t vert = 0; vert < size; vert++) { // Vertical counter - for (int j = 0; j < 2; j++) { - uint8_t x = right - j; // Actual x coordinate - bool upwards = ((right & 2) == 0) ^ (x < 6); - uint8_t y = upwards ? size - 1 - vert : vert; // Actual y coordinate - if (!bb_getBit(isFunction, x, y) && i < bitLength) { - bb_setBit(modules, x, y, ((data[i >> 3] >> (7 - (i & 7))) & 1) != 0); - i++; - } - // If there are any remainder bits (0 to 7), they are already - // set to 0/false/white when the grid of modules was initialized - } - } + + uint32_t bitLength = codewords->bitOffsetOrWidth; + uint8_t *data = codewords->data; + + uint8_t size = modules->bitOffsetOrWidth; + + // Bit index into the data + uint32_t i = 0; + + // Do the funny zigzag scan + for (int16_t right = size - 1; right >= 1; right -= 2) { // Index of right column in each column pair + if (right == 6) { + right = 5; } + + for (uint8_t vert = 0; vert < size; vert++) { // Vertical counter + for (int j = 0; j < 2; j++) { + uint8_t x = right - j; // Actual x coordinate + bool upwards = ((right & 2) == 0) ^ (x < 6); + uint8_t y = upwards ? size - 1 - vert : vert; // Actual y coordinate + if (!bb_getBit(isFunction, x, y) && i < bitLength) { + bb_setBit(modules, x, y, ((data[i >> 3] >> (7 - (i & 7))) & 1) != 0); + i++; + } + // If there are any remainder bits (0 to 7), they are already + // set to 0/false/white when the grid of modules was initialized + } + } + } } @@ -481,145 +473,145 @@ static void drawCodewords(BitBucket *modules, BitBucket *isFunction, BitBucket * // This is used by the automatic mask choice algorithm to find the mask pattern that yields the lowest score. // @TODO: This can be optimized by working with the bytes instead of bits. static uint32_t getPenaltyScore(BitBucket *modules) { - uint32_t result = 0; - - uint8_t size = modules->bitOffsetOrWidth; - - // Adjacent modules in row having same color - for (uint8_t y = 0; y < size; y++) { - - bool colorX = bb_getBit(modules, 0, y); - for (uint8_t x = 1, runX = 1; x < size; x++) { - bool cx = bb_getBit(modules, x, y); - if (cx != colorX) { - colorX = cx; - runX = 1; - - } else { - runX++; - if (runX == 5) { - result += PENALTY_N1; - } else if (runX > 5) { - result++; - } - } + uint32_t result = 0; + + uint8_t size = modules->bitOffsetOrWidth; + + // Adjacent modules in row having same color + for (uint8_t y = 0; y < size; y++) { + + bool colorX = bb_getBit(modules, 0, y); + for (uint8_t x = 1, runX = 1; x < size; x++) { + bool cx = bb_getBit(modules, x, y); + if (cx != colorX) { + colorX = cx; + runX = 1; + } else { + runX++; + if (runX == 5) { + result += PENALTY_N1; + } else if (runX > 5) { + result++; } + } } - - // Adjacent modules in column having same color + } + + // Adjacent modules in column having same color + for (uint8_t x = 0; x < size; x++) { + bool colorY = bb_getBit(modules, x, 0); + for (uint8_t y = 1, runY = 1; y < size; y++) { + bool cy = bb_getBit(modules, x, y); + if (cy != colorY) { + colorY = cy; + runY = 1; + } else { + runY++; + if (runY == 5) { + result += PENALTY_N1; + } else if (runY > 5) { + result++; + } + } + } + } + + uint16_t black = 0; + for (uint8_t y = 0; y < size; y++) { + uint16_t bitsRow = 0, bitsCol = 0; for (uint8_t x = 0; x < size; x++) { - bool colorY = bb_getBit(modules, x, 0); - for (uint8_t y = 1, runY = 1; y < size; y++) { - bool cy = bb_getBit(modules, x, y); - if (cy != colorY) { - colorY = cy; - runY = 1; - } else { - runY++; - if (runY == 5) { - result += PENALTY_N1; - } else if (runY > 5) { - result++; - } - } + bool color = bb_getBit(modules, x, y); + + // 2*2 blocks of modules having same color + if (x > 0 && y > 0) { + bool colorUL = bb_getBit(modules, x - 1, y - 1); + bool colorUR = bb_getBit(modules, x, y - 1); + bool colorL = bb_getBit(modules, x - 1, y); + if (color == colorUL && color == colorUR && color == colorL) { + result += PENALTY_N2; } - } - - uint16_t black = 0; - for (uint8_t y = 0; y < size; y++) { - uint16_t bitsRow = 0, bitsCol = 0; - for (uint8_t x = 0; x < size; x++) { - bool color = bb_getBit(modules, x, y); + } - // 2*2 blocks of modules having same color - if (x > 0 && y > 0) { - bool colorUL = bb_getBit(modules, x - 1, y - 1); - bool colorUR = bb_getBit(modules, x, y - 1); - bool colorL = bb_getBit(modules, x - 1, y); - if (color == colorUL && color == colorUR && color == colorL) { - result += PENALTY_N2; - } - } + // Finder-like pattern in rows and columns + bitsRow = ((bitsRow << 1) & 0x7FF) | color; + bitsCol = ((bitsCol << 1) & 0x7FF) | bb_getBit(modules, y, x); - // Finder-like pattern in rows and columns - bitsRow = ((bitsRow << 1) & 0x7FF) | color; - bitsCol = ((bitsCol << 1) & 0x7FF) | bb_getBit(modules, y, x); - - // Needs 11 bits accumulated - if (x >= 10) { - if (bitsRow == 0x05D || bitsRow == 0x5D0) { - result += PENALTY_N3; - } - if (bitsCol == 0x05D || bitsCol == 0x5D0) { - result += PENALTY_N3; - } - } - - // Balance of black and white modules - if (color) { black++; } + // Needs 11 bits accumulated + if (x >= 10) { + if (bitsRow == 0x05D || bitsRow == 0x5D0) { + result += PENALTY_N3; } - } + if (bitsCol == 0x05D || bitsCol == 0x5D0) { + result += PENALTY_N3; + } + } - // Find smallest k such that (45-5k)% <= dark/total <= (55+5k)% - uint16_t total = size * size; - for (uint16_t k = 0; black * 20 < (9 - k) * total || black * 20 > (11 + k) * total; k++) { - result += PENALTY_N4; + // Balance of black and white modules + if (color) { + black++; + } } - - return result; + } + + // Find smallest k such that (45-5k)% <= dark/total <= (55+5k)% + uint16_t total = size * size; + for (uint16_t k = 0; black * 20 < (9 - k) * total || black * 20 > (11 + k) * total; k++) { + result += PENALTY_N4; + } + return result; } //#pragma mark - Reed-Solomon Generator static uint8_t rs_multiply(uint8_t x, uint8_t y) { - // Russian peasant multiplication - // See: https://en.wikipedia.org/wiki/Ancient_Egyptian_multiplication - uint16_t z = 0; - for (int8_t i = 7; i >= 0; i--) { - z = (z << 1) ^ ((z >> 7) * 0x11D); - z ^= ((y >> i) & 1) * x; - } - return z; + // Russian peasant multiplication + // See: https://en.wikipedia.org/wiki/Ancient_Egyptian_multiplication + uint16_t z = 0; + for (int8_t i = 7; i >= 0; i--) { + z = (z << 1) ^ ((z >> 7) * 0x11D); + z ^= ((y >> i) & 1) * x; + } + return z; } static void rs_init(uint8_t degree, uint8_t *coeff) { - memset(coeff, 0, degree); - coeff[degree - 1] = 1; - - // Compute the product polynomial (x - r^0) * (x - r^1) * (x - r^2) * ... * (x - r^{degree-1}), - // drop the highest term, and store the rest of the coefficients in order of descending powers. - // Note that r = 0x02, which is a generator element of this field GF(2^8/0x11D). - uint16_t root = 1; - for (uint8_t i = 0; i < degree; i++) { - // Multiply the current product by (x - r^i) - for (uint8_t j = 0; j < degree; j++) { - coeff[j] = rs_multiply(coeff[j], root); - if (j + 1 < degree) { - coeff[j] ^= coeff[j + 1]; - } - } - root = (root << 1) ^ ((root >> 7) * 0x11D); // Multiply by 0x02 mod GF(2^8/0x11D) + memset(coeff, 0, degree); + coeff[degree - 1] = 1; + + // Compute the product polynomial (x - r^0) * (x - r^1) * (x - r^2) * ... * (x - r^{degree-1}), + // drop the highest term, and store the rest of the coefficients in order of descending powers. + // Note that r = 0x02, which is a generator element of this field GF(2^8/0x11D). + uint16_t root = 1; + for (uint8_t i = 0; i < degree; i++) { + // Multiply the current product by (x - r^i) + for (uint8_t j = 0; j < degree; j++) { + coeff[j] = rs_multiply(coeff[j], root); + if (j + 1 < degree) { + coeff[j] ^= coeff[j + 1]; + } } + root = (root << 1) ^ ((root >> 7) * 0x11D); // Multiply by 0x02 mod GF(2^8/0x11D) + } } static void rs_getRemainder(uint8_t degree, uint8_t *coeff, uint8_t *data, uint8_t length, uint8_t *result, uint8_t stride) { - // Compute the remainder by performing polynomial division - - //for (uint8_t i = 0; i < degree; i++) { result[] = 0; } - //memset(result, 0, degree); - - for (uint8_t i = 0; i < length; i++) { - uint8_t factor = data[i] ^ result[0]; - for (uint8_t j = 1; j < degree; j++) { - result[(j - 1) * stride] = result[j * stride]; - } - result[(degree - 1) * stride] = 0; - - for (uint8_t j = 0; j < degree; j++) { - result[j * stride] ^= rs_multiply(coeff[j], factor); - } + // Compute the remainder by performing polynomial division + + //for (uint8_t i = 0; i < degree; i++) { result[] = 0; } + //memset(result, 0, degree); + + for (uint8_t i = 0; i < length; i++) { + uint8_t factor = data[i] ^ result[0]; + for (uint8_t j = 1; j < degree; j++) { + result[(j - 1) * stride] = result[j * stride]; } + result[(degree - 1) * stride] = 0; + + for (uint8_t j = 0; j < degree; j++) { + result[j * stride] ^= rs_multiply(coeff[j], factor); + } + } } @@ -627,137 +619,138 @@ static void rs_getRemainder(uint8_t degree, uint8_t *coeff, uint8_t *data, uint8 //#pragma mark - QrCode static int8_t encodeDataCodewords(BitBucket *dataCodewords, const uint8_t *text, uint16_t length, uint8_t version) { - int8_t mode = MODE_BYTE; - - if (isNumeric((char*)text, length)) { - mode = MODE_NUMERIC; - bb_appendBits(dataCodewords, 1 << MODE_NUMERIC, 4); - bb_appendBits(dataCodewords, length, getModeBits(version, MODE_NUMERIC)); + int8_t mode = MODE_BYTE; - uint16_t accumData = 0; - uint8_t accumCount = 0; - for (uint16_t i = 0; i < length; i++) { - accumData = accumData * 10 + ((char)(text[i]) - '0'); - accumCount++; - if (accumCount == 3) { - bb_appendBits(dataCodewords, accumData, 10); - accumData = 0; - accumCount = 0; - } - } - - // 1 or 2 digits remaining - if (accumCount > 0) { - bb_appendBits(dataCodewords, accumData, accumCount * 3 + 1); - } - - } else if (isAlphanumeric((char*)text, length)) { - mode = MODE_ALPHANUMERIC; - bb_appendBits(dataCodewords, 1 << MODE_ALPHANUMERIC, 4); - bb_appendBits(dataCodewords, length, getModeBits(version, MODE_ALPHANUMERIC)); + if (isNumeric((char*)text, length)) { + mode = MODE_NUMERIC; + bb_appendBits(dataCodewords, 1 << MODE_NUMERIC, 4); + bb_appendBits(dataCodewords, length, getModeBits(version, MODE_NUMERIC)); - uint16_t accumData = 0; - uint8_t accumCount = 0; - for (uint16_t i = 0; i < length; i++) { - accumData = accumData * 45 + getAlphanumeric((char)(text[i])); - accumCount++; - if (accumCount == 2) { - bb_appendBits(dataCodewords, accumData, 11); - accumData = 0; - accumCount = 0; - } - } - - // 1 character remaining - if (accumCount > 0) { - bb_appendBits(dataCodewords, accumData, 6); - } - - } else { - bb_appendBits(dataCodewords, 1 << MODE_BYTE, 4); - bb_appendBits(dataCodewords, length, getModeBits(version, MODE_BYTE)); - for (uint16_t i = 0; i < length; i++) { - bb_appendBits(dataCodewords, (char)(text[i]), 8); - } + uint16_t accumData = 0; + uint8_t accumCount = 0; + for (uint16_t i = 0; i < length; i++) { + accumData = accumData * 10 + ((char)(text[i]) - '0'); + accumCount++; + if (accumCount == 3) { + bb_appendBits(dataCodewords, accumData, 10); + accumData = 0; + accumCount = 0; + } } - - //bb_setBits(dataCodewords, length, 4, getModeBits(version, mode)); - - return mode; + + // 1 or 2 digits remaining + if (accumCount > 0) { + bb_appendBits(dataCodewords, accumData, accumCount * 3 + 1); + } + + } else if (isAlphanumeric((char*)text, length)) { + mode = MODE_ALPHANUMERIC; + bb_appendBits(dataCodewords, 1 << MODE_ALPHANUMERIC, 4); + bb_appendBits(dataCodewords, length, getModeBits(version, MODE_ALPHANUMERIC)); + + uint16_t accumData = 0; + uint8_t accumCount = 0; + for (uint16_t i = 0; i < length; i++) { + accumData = accumData * 45 + getAlphanumeric((char)(text[i])); + accumCount++; + if (accumCount == 2) { + bb_appendBits(dataCodewords, accumData, 11); + accumData = 0; + accumCount = 0; + } + } + + // 1 character remaining + if (accumCount > 0) { + bb_appendBits(dataCodewords, accumData, 6); + } + + } else { + bb_appendBits(dataCodewords, 1 << MODE_BYTE, 4); + bb_appendBits(dataCodewords, length, getModeBits(version, MODE_BYTE)); + for (uint16_t i = 0; i < length; i++) { + bb_appendBits(dataCodewords, (char)(text[i]), 8); + } + } + //bb_setBits(dataCodewords, length, 4, getModeBits(version, mode)); + return mode; } static void performErrorCorrection(uint8_t version, uint8_t ecc, BitBucket *data) { - - // See: http://www.thonky.com/qr-code-tutorial/structure-final-message - -#if LOCK_VERSION == 0 + + // See: http://www.thonky.com/qr-code-tutorial/structure-final-message + + #if LOCK_VERSION == 0 uint8_t numBlocks = NUM_ERROR_CORRECTION_BLOCKS[ecc][version - 1]; uint16_t totalEcc = NUM_ERROR_CORRECTION_CODEWORDS[ecc][version - 1]; uint16_t moduleCount = NUM_RAW_DATA_MODULES[version - 1]; -#else + #else uint8_t numBlocks = NUM_ERROR_CORRECTION_BLOCKS[ecc]; uint16_t totalEcc = NUM_ERROR_CORRECTION_CODEWORDS[ecc]; uint16_t moduleCount = NUM_RAW_DATA_MODULES; -#endif - - uint8_t blockEccLen = totalEcc / numBlocks; - uint8_t numShortBlocks = numBlocks - moduleCount / 8 % numBlocks; - uint8_t shortBlockLen = moduleCount / 8 / numBlocks; - - uint8_t shortDataBlockLen = shortBlockLen - blockEccLen; - - uint8_t result[data->capacityBytes]; - memset(result, 0, sizeof(result)); - - uint8_t coeff[blockEccLen]; - rs_init(blockEccLen, coeff); - - uint16_t offset = 0; - uint8_t *dataBytes = data->data; - - - // Interleave all short blocks - for (uint8_t i = 0; i < shortDataBlockLen; i++) { - uint16_t index = i; - uint8_t stride = shortDataBlockLen; - for (uint8_t blockNum = 0; blockNum < numBlocks; blockNum++) { - result[offset++] = dataBytes[index]; - -#if LOCK_VERSION == 0 || LOCK_VERSION >= 5 - if (blockNum == numShortBlocks) { stride++; } -#endif - index += stride; - } - } - - // Version less than 5 only have short blocks -#if LOCK_VERSION == 0 || LOCK_VERSION >= 5 - { - // Interleave long blocks - uint16_t index = shortDataBlockLen * (numShortBlocks + 1); - uint8_t stride = shortDataBlockLen; - for (uint8_t blockNum = 0; blockNum < numBlocks - numShortBlocks; blockNum++) { - result[offset++] = dataBytes[index]; - - if (blockNum == 0) { stride++; } - index += stride; - } - } -#endif - - // Add all ecc blocks, interleaved - uint8_t blockSize = shortDataBlockLen; + #endif + + uint8_t blockEccLen = totalEcc / numBlocks; + uint8_t numShortBlocks = numBlocks - moduleCount / 8 % numBlocks; + uint8_t shortBlockLen = moduleCount / 8 / numBlocks; + + uint8_t shortDataBlockLen = shortBlockLen - blockEccLen; + + uint8_t result[data->capacityBytes]; + memset(result, 0, sizeof(result)); + + uint8_t coeff[blockEccLen]; + rs_init(blockEccLen, coeff); + + uint16_t offset = 0; + uint8_t *dataBytes = data->data; + + + // Interleave all short blocks + for (uint8_t i = 0; i < shortDataBlockLen; i++) { + uint16_t index = i; + uint8_t stride = shortDataBlockLen; for (uint8_t blockNum = 0; blockNum < numBlocks; blockNum++) { - -#if LOCK_VERSION == 0 || LOCK_VERSION >= 5 - if (blockNum == numShortBlocks) { blockSize++; } -#endif - rs_getRemainder(blockEccLen, coeff, dataBytes, blockSize, &result[offset + blockNum], numBlocks); - dataBytes += blockSize; + result[offset++] = dataBytes[index]; + + #if LOCK_VERSION == 0 || LOCK_VERSION >= 5 + if (blockNum == numShortBlocks) { stride++; } + #endif + index += stride; } - - memcpy(data->data, result, data->capacityBytes); - data->bitOffsetOrWidth = moduleCount; + } + // Version less than 5 only have short blocks + #if LOCK_VERSION == 0 || LOCK_VERSION >= 5 + { + // Interleave long blocks + uint16_t index = shortDataBlockLen * (numShortBlocks + 1); + uint8_t stride = shortDataBlockLen; + for (uint8_t blockNum = 0; blockNum < numBlocks - numShortBlocks; blockNum++) { + result[offset++] = dataBytes[index]; + + if (blockNum == 0) { + stride++; + } + index += stride; + } + } + #endif + + // Add all ecc blocks, interleaved + uint8_t blockSize = shortDataBlockLen; + for (uint8_t blockNum = 0; blockNum < numBlocks; blockNum++) { + + #if LOCK_VERSION == 0 || LOCK_VERSION >= 5 + if (blockNum == numShortBlocks) { + blockSize++; + } + #endif + rs_getRemainder(blockEccLen, coeff, dataBytes, blockSize, &result[offset + blockNum], numBlocks); + dataBytes += blockSize; + } + + memcpy(data->data, result, data->capacityBytes); + data->bitOffsetOrWidth = moduleCount; } // We store the Format bits tightly packed into a single byte (each of the 4 modes is 2 bits) @@ -768,105 +761,108 @@ static const uint8_t ECC_FORMAT_BITS = (0x02 << 6) | (0x03 << 4) | (0x00 << 2) | //#pragma mark - Public QRCode functions uint16_t qrcode_getBufferSize(uint8_t version) { - return bb_getGridSizeBytes(4 * version + 17); + return bb_getGridSizeBytes(4 * version + 17); } // @TODO: Return error if data is too big. int8_t qrcode_initBytes(QRCode *qrcode, uint8_t *modules, uint8_t version, uint8_t ecc, uint8_t *data, uint16_t length) { - uint8_t size = version * 4 + 17; - qrcode->version = version; - qrcode->size = size; - qrcode->ecc = ecc; - qrcode->modules = modules; - - uint8_t eccFormatBits = (ECC_FORMAT_BITS >> (2 * ecc)) & 0x03; - -#if LOCK_VERSION == 0 + uint8_t size = version * 4 + 17; + qrcode->version = version; + qrcode->size = size; + qrcode->ecc = ecc; + qrcode->modules = modules; + + uint8_t eccFormatBits = (ECC_FORMAT_BITS >> (2 * ecc)) & 0x03; + + #if LOCK_VERSION == 0 uint16_t moduleCount = NUM_RAW_DATA_MODULES[version - 1]; uint16_t dataCapacity = moduleCount / 8 - NUM_ERROR_CORRECTION_CODEWORDS[eccFormatBits][version - 1]; -#else + #else version = LOCK_VERSION; uint16_t moduleCount = NUM_RAW_DATA_MODULES; uint16_t dataCapacity = moduleCount / 8 - NUM_ERROR_CORRECTION_CODEWORDS[eccFormatBits]; -#endif - - struct BitBucket codewords; - uint8_t codewordBytes[bb_getBufferSizeBytes(moduleCount)]; - bb_initBuffer(&codewords, codewordBytes, (int32_t)sizeof(codewordBytes)); - - // Place the data code words into the buffer - int8_t mode = encodeDataCodewords(&codewords, data, length, version); - - if (mode < 0) { return -1; } - qrcode->mode = mode; - - // Add terminator and pad up to a byte if applicable - uint32_t padding = (dataCapacity * 8) - codewords.bitOffsetOrWidth; - if (padding > 4) { padding = 4; } - bb_appendBits(&codewords, 0, padding); - bb_appendBits(&codewords, 0, (8 - codewords.bitOffsetOrWidth % 8) % 8); + #endif - // Pad with alternate bytes until data capacity is reached - for (uint8_t padByte = 0xEC; codewords.bitOffsetOrWidth < (dataCapacity * 8); padByte ^= 0xEC ^ 0x11) { - bb_appendBits(&codewords, padByte, 8); + struct BitBucket codewords; + uint8_t codewordBytes[bb_getBufferSizeBytes(moduleCount)]; + bb_initBuffer(&codewords, codewordBytes, (int32_t)sizeof(codewordBytes)); + + // Place the data code words into the buffer + int8_t mode = encodeDataCodewords(&codewords, data, length, version); + + if (mode < 0) { + return -1; + } + qrcode->mode = mode; + + // Add terminator and pad up to a byte if applicable + uint32_t padding = (dataCapacity * 8) - codewords.bitOffsetOrWidth; + if (padding > 4) { + padding = 4; + } + bb_appendBits(&codewords, 0, padding); + bb_appendBits(&codewords, 0, (8 - codewords.bitOffsetOrWidth % 8) % 8); + + // Pad with alternate bytes until data capacity is reached + for (uint8_t padByte = 0xEC; codewords.bitOffsetOrWidth < (dataCapacity * 8); padByte ^= 0xEC ^ 0x11) { + bb_appendBits(&codewords, padByte, 8); + } + + BitBucket modulesGrid; + bb_initGrid(&modulesGrid, modules, size); + + BitBucket isFunctionGrid; + uint8_t isFunctionGridBytes[bb_getGridSizeBytes(size)]; + bb_initGrid(&isFunctionGrid, isFunctionGridBytes, size); + + // Draw function patterns, draw all codewords, do masking + drawFunctionPatterns(&modulesGrid, &isFunctionGrid, version, eccFormatBits); + performErrorCorrection(version, eccFormatBits, &codewords); + drawCodewords(&modulesGrid, &isFunctionGrid, &codewords); + + // Find the best (lowest penalty) mask + uint8_t mask = 0; + int32_t minPenalty = INT32_MAX; + for (uint8_t i = 0; i < 8; i++) { + drawFormatBits(&modulesGrid, &isFunctionGrid, eccFormatBits, i); + applyMask(&modulesGrid, &isFunctionGrid, i); + int penalty = getPenaltyScore(&modulesGrid); + if (penalty < minPenalty) { + mask = i; + minPenalty = penalty; } + applyMask(&modulesGrid, &isFunctionGrid, i); // Undoes the mask due to XOR + } - BitBucket modulesGrid; - bb_initGrid(&modulesGrid, modules, size); - - BitBucket isFunctionGrid; - uint8_t isFunctionGridBytes[bb_getGridSizeBytes(size)]; - bb_initGrid(&isFunctionGrid, isFunctionGridBytes, size); - - // Draw function patterns, draw all codewords, do masking - drawFunctionPatterns(&modulesGrid, &isFunctionGrid, version, eccFormatBits); - performErrorCorrection(version, eccFormatBits, &codewords); - drawCodewords(&modulesGrid, &isFunctionGrid, &codewords); - - // Find the best (lowest penalty) mask - uint8_t mask = 0; - int32_t minPenalty = INT32_MAX; - for (uint8_t i = 0; i < 8; i++) { - drawFormatBits(&modulesGrid, &isFunctionGrid, eccFormatBits, i); - applyMask(&modulesGrid, &isFunctionGrid, i); - int penalty = getPenaltyScore(&modulesGrid); - if (penalty < minPenalty) { - mask = i; - minPenalty = penalty; - } - applyMask(&modulesGrid, &isFunctionGrid, i); // Undoes the mask due to XOR - } - - qrcode->mask = mask; - - // Overwrite old format bits - drawFormatBits(&modulesGrid, &isFunctionGrid, eccFormatBits, mask); - - // Apply the final choice of mask - applyMask(&modulesGrid, &isFunctionGrid, mask); + qrcode->mask = mask; - return 0; + // Overwrite old format bits + drawFormatBits(&modulesGrid, &isFunctionGrid, eccFormatBits, mask); + + // Apply the final choice of mask + applyMask(&modulesGrid, &isFunctionGrid, mask); + + return 0; } int8_t qrcode_initText(QRCode *qrcode, uint8_t *modules, uint8_t version, uint8_t ecc, const char *data) { - return qrcode_initBytes(qrcode, modules, version, ecc, (uint8_t*)data, strlen(data)); + return qrcode_initBytes(qrcode, modules, version, ecc, (uint8_t*)data, strlen(data)); } bool qrcode_getModule(QRCode *qrcode, uint8_t x, uint8_t y) { - if (x < 0 || x >= qrcode->size || y < 0 || y >= qrcode->size) { - return false; - } - - uint32_t offset = y * qrcode->size + x; - return (qrcode->modules[offset >> 3] & (1 << (7 - (offset & 0x07)))) != 0; + if (x < 0 || x >= qrcode->size || y < 0 || y >= qrcode->size) { + return false; + } + uint32_t offset = y * qrcode->size + x; + return (qrcode->modules[offset >> 3] & (1 << (7 - (offset & 0x07)))) != 0; } /* uint8_t qrcode_getHexLength(QRCode *qrcode) { - return ((qrcode->size * qrcode->size) + 7) / 4; + return ((qrcode->size * qrcode->size) + 7) / 4; } void qrcode_getHex(QRCode *qrcode, char *result) { - + } */ diff --git a/src/utility/qrcode.h b/src/utility/qrcode.h index ef429d7..3af952a 100755 --- a/src/utility/qrcode.h +++ b/src/utility/qrcode.h @@ -31,65 +31,65 @@ #ifndef __QRCODE_H_ -#define __QRCODE_H_ + #define __QRCODE_H_ -#ifndef __cplusplus -typedef unsigned char bool; -static const bool false = 0; -static const bool true = 1; -#endif + #ifndef __cplusplus + typedef unsigned char bool; + static const bool false = 0; + static const bool true = 1; + #endif -#include + #include -// QR Code Format Encoding -#define MODE_NUMERIC 0 -#define MODE_ALPHANUMERIC 1 -#define MODE_BYTE 2 + // QR Code Format Encoding + #define MODE_NUMERIC 0 + #define MODE_ALPHANUMERIC 1 + #define MODE_BYTE 2 -// Error Correction Code Levels -#define ECC_LOW 0 -#define ECC_MEDIUM 1 -#define ECC_QUARTILE 2 -#define ECC_HIGH 3 + // Error Correction Code Levels + #define ECC_LOW 0 + #define ECC_MEDIUM 1 + #define ECC_QUARTILE 2 + #define ECC_HIGH 3 -// If set to non-zero, this library can ONLY produce QR codes at that version -// This saves a lot of dynamic memory, as the codeword tables are skipped -#ifndef LOCK_VERSION -#define LOCK_VERSION 0 -#endif + // If set to non-zero, this library can ONLY produce QR codes at that version + // This saves a lot of dynamic memory, as the codeword tables are skipped + #ifndef LOCK_VERSION + #define LOCK_VERSION 0 + #endif -typedef struct QRCode { + typedef struct QRCode { uint8_t version; uint8_t size; uint8_t ecc; uint8_t mode; uint8_t mask; uint8_t *modules; -} QRCode; + } QRCode; -#ifdef __cplusplus -extern "C"{ -#endif /* __cplusplus */ + #ifdef __cplusplus + extern "C"{ + #endif /* __cplusplus */ -uint16_t qrcode_getBufferSize(uint8_t version); + uint16_t qrcode_getBufferSize(uint8_t version); -int8_t qrcode_initText(QRCode *qrcode, uint8_t *modules, uint8_t version, uint8_t ecc, const char *data); -int8_t qrcode_initBytes(QRCode *qrcode, uint8_t *modules, uint8_t version, uint8_t ecc, uint8_t *data, uint16_t length); + int8_t qrcode_initText(QRCode *qrcode, uint8_t *modules, uint8_t version, uint8_t ecc, const char *data); + int8_t qrcode_initBytes(QRCode *qrcode, uint8_t *modules, uint8_t version, uint8_t ecc, uint8_t *data, uint16_t length); -bool qrcode_getModule(QRCode *qrcode, uint8_t x, uint8_t y); + bool qrcode_getModule(QRCode *qrcode, uint8_t x, uint8_t y); -#ifdef __cplusplus -} -#endif /* __cplusplus */ + #ifdef __cplusplus + } + #endif /* __cplusplus */ #endif /* __QRCODE_H_ */ diff --git a/src/utility/quaternionFilters.cpp b/src/utility/quaternionFilters.cpp index 87094fe..9eb8712 100644 --- a/src/utility/quaternionFilters.cpp +++ b/src/utility/quaternionFilters.cpp @@ -38,12 +38,11 @@ static float beta = sqrt(3.0f / 4.0f) * GyroMeasError; // Compute beta static float zeta = sqrt(3.0f / 4.0f) * GyroMeasDrift; // Vector to hold integral error for Mahony method -static float eInt[3] = {0.0f, 0.0f, 0.0f}; +static float eInt[3] = { 0.0f, 0.0f, 0.0f }; // Vector to hold quaternion -static float q[4] = {1.0f, 0.0f, 0.0f, 0.0f}; +static float q[4] = { 1.0f, 0.0f, 0.0f, 0.0f }; -void MadgwickQuaternionUpdate(float ax, float ay, float az, float gx, float gy, float gz, float mx, float my, float mz, float deltat) -{ +void MadgwickQuaternionUpdate(float ax, float ay, float az, float gx, float gy, float gz, float mx, float my, float mz, float deltat){ // short name local variable for readability float q1 = q[0], q2 = q[1], q3 = q[2], q4 = q[3]; float norm; @@ -77,16 +76,20 @@ void MadgwickQuaternionUpdate(float ax, float ay, float az, float gx, float gy, // Normalise accelerometer measurement norm = sqrt(ax * ax + ay * ay + az * az); - if (norm == 0.0f) return; // handle NaN - norm = 1.0f/norm; + if (norm == 0.0f) { + return; // handle NaN + } + norm = 1.0f / norm; ax *= norm; ay *= norm; az *= norm; // Normalise magnetometer measurement norm = sqrt(mx * mx + my * my + mz * mz); - if (norm == 0.0f) return; // handle NaN - norm = 1.0f/norm; + if (norm == 0.0f) { + return; // handle NaN + } + norm = 1.0f / norm; mx *= norm; my *= norm; mz *= norm; @@ -110,7 +113,7 @@ void MadgwickQuaternionUpdate(float ax, float ay, float az, float gx, float gy, s3 = -_2q1 * (2.0f * q2q4 - _2q1q3 - ax) + _2q4 * (2.0f * q1q2 + _2q3q4 - ay) - 4.0f * q3 * (1.0f - 2.0f * q2q2 - 2.0f * q3q3 - az) + (-_4bx * q3 - _2bz * q1) * (_2bx * (0.5f - q3q3 - q4q4) + _2bz * (q2q4 - q1q3) - mx) + (_2bx * q2 + _2bz * q4) * (_2bx * (q2q3 - q1q4) + _2bz * (q1q2 + q3q4) - my) + (_2bx * q1 - _4bz * q3) * (_2bx * (q1q3 + q2q4) + _2bz * (0.5f - q2q2 - q3q3) - mz); s4 = _2q2 * (2.0f * q2q4 - _2q1q3 - ax) + _2q3 * (2.0f * q1q2 + _2q3q4 - ay) + (-_4bx * q4 + _2bz * q2) * (_2bx * (0.5f - q3q3 - q4q4) + _2bz * (q2q4 - q1q3) - mx) + (-_2bx * q1 + _2bz * q3) * (_2bx * (q2q3 - q1q4) + _2bz * (q1q2 + q3q4) - my) + _2bx * q2 * (_2bx * (q1q3 + q2q4) + _2bz * (0.5f - q2q2 - q3q3) - mz); norm = sqrt(s1 * s1 + s2 * s2 + s3 * s3 + s4 * s4); // normalise step magnitude - norm = 1.0f/norm; + norm = 1.0f / norm; s1 *= norm; s2 *= norm; s3 *= norm; @@ -128,7 +131,7 @@ void MadgwickQuaternionUpdate(float ax, float ay, float az, float gx, float gy, q3 += qDot3 * deltat; q4 += qDot4 * deltat; norm = sqrt(q1 * q1 + q2 * q2 + q3 * q3 + q4 * q4); // normalise quaternion - norm = 1.0f/norm; + norm = 1.0f / norm; q[0] = q1 * norm; q[1] = q2 * norm; q[2] = q3 * norm; @@ -139,8 +142,7 @@ void MadgwickQuaternionUpdate(float ax, float ay, float az, float gx, float gy, // Similar to Madgwick scheme but uses proportional and integral filtering on // the error between estimated reference vectors and measured ones. -void MahonyQuaternionUpdate(float ax, float ay, float az, float gx, float gy, float gz, float mx, float my, float mz, float deltat) -{ +void MahonyQuaternionUpdate(float ax, float ay, float az, float gx, float gy, float gz, float mx, float my, float mz, float deltat){ // short name local variable for readability float q1 = q[0], q2 = q[1], q3 = q[2], q4 = q[3]; float norm; @@ -163,7 +165,9 @@ void MahonyQuaternionUpdate(float ax, float ay, float az, float gx, float gy, fl // Normalise accelerometer measurement norm = sqrt(ax * ax + ay * ay + az * az); - if (norm == 0.0f) return; // Handle NaN + if (norm == 0.0f) { + return; // Handle NaN + } norm = 1.0f / norm; // Use reciprocal for division ax *= norm; ay *= norm; @@ -171,7 +175,9 @@ void MahonyQuaternionUpdate(float ax, float ay, float az, float gx, float gy, fl // Normalise magnetometer measurement norm = sqrt(mx * mx + my * my + mz * mz); - if (norm == 0.0f) return; // Handle NaN + if (norm == 0.0f) { + return; // Handle NaN + } norm = 1.0f / norm; // Use reciprocal for division mx *= norm; my *= norm; @@ -195,14 +201,11 @@ void MahonyQuaternionUpdate(float ax, float ay, float az, float gx, float gy, fl ex = (ay * vz - az * vy) + (my * wz - mz * wy); ey = (az * vx - ax * vz) + (mz * wx - mx * wz); ez = (ax * vy - ay * vx) + (mx * wy - my * wx); - if (Ki > 0.0f) - { + if (Ki > 0.0f){ eInt[0] += ex; // accumulate integral error eInt[1] += ey; eInt[2] += ez; - } - else - { + }else{ eInt[0] = 0.0f; // prevent integral wind up eInt[1] = 0.0f; eInt[2] = 0.0f; @@ -212,7 +215,7 @@ void MahonyQuaternionUpdate(float ax, float ay, float az, float gx, float gy, fl gx = gx + Kp * ex + Ki * eInt[0]; gy = gy + Kp * ey + Ki * eInt[1]; gz = gz + Kp * ez + Ki * eInt[2]; - + // Integrate rate of change of quaternion pa = q2; pb = q3; @@ -231,4 +234,6 @@ void MahonyQuaternionUpdate(float ax, float ay, float az, float gx, float gy, fl q[3] = q4 * norm; } -const float * getQ () { return q; } +const float * getQ () { + return q; +} diff --git a/src/utility/quaternionFilters.h b/src/utility/quaternionFilters.h index 2b18a0f..b1c3d4f 100644 --- a/src/utility/quaternionFilters.h +++ b/src/utility/quaternionFilters.h @@ -1,14 +1,14 @@ #ifndef _QUATERNIONFILTERS_H_ -#define _QUATERNIONFILTERS_H_ + #define _QUATERNIONFILTERS_H_ -#include + #include -void MadgwickQuaternionUpdate(float ax, float ay, float az, float gx, float gy, + void MadgwickQuaternionUpdate(float ax, float ay, float az, float gx, float gy, + float gz, float mx, float my, float mz, + float deltat); + void MahonyQuaternionUpdate(float ax, float ay, float az, float gx, float gy, float gz, float mx, float my, float mz, float deltat); -void MahonyQuaternionUpdate(float ax, float ay, float az, float gx, float gy, - float gz, float mx, float my, float mz, - float deltat); -const float * getQ(); + const float * getQ(); #endif // _QUATERNIONFILTERS_H_