mirror of https://github.com/arendst/Tasmota.git
Merge branch 'development' into pre-release
This commit is contained in:
commit
a63d703a88
|
@ -66,13 +66,14 @@ RA8876::RA8876(int8_t cs,int8_t mosi,int8_t miso,int8_t sclk,int8_t bp) : Render
|
||||||
//#define RA8876_CS_LOW digitalWrite(m_csPin, LOW)
|
//#define RA8876_CS_LOW digitalWrite(m_csPin, LOW)
|
||||||
//#define RA8876_CS_HIGH digitalWrite(m_csPin, HIGH)
|
//#define RA8876_CS_HIGH digitalWrite(m_csPin, HIGH)
|
||||||
|
|
||||||
#ifdef ESP8266
|
#ifndef ESP32
|
||||||
#define RA8876_CS_LOW GPOC=(1<<m_csPin);
|
#define RA8876_CS_LOW GPOC=(1<<m_csPin);
|
||||||
#define RA8876_CS_HIGH GPOS=(1<<m_csPin);
|
#define RA8876_CS_HIGH GPOS=(1<<m_csPin);
|
||||||
#else
|
#else
|
||||||
#define RA8876_CS_LOW digitalWrite(1<<m_csPin,0);
|
#define RA8876_CS_LOW digitalWrite(m_csPin,0);
|
||||||
#define RA8876_CS_HIGH digitalWrite(1<<m_csPin,1);
|
#define RA8876_CS_HIGH digitalWrite(m_csPin,1);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
extern void ICACHE_RAM_ATTR RA8876_digitalWrite(uint8_t pin, uint8_t val) {
|
extern void ICACHE_RAM_ATTR RA8876_digitalWrite(uint8_t pin, uint8_t val) {
|
||||||
//stopWaveform(pin);
|
//stopWaveform(pin);
|
||||||
|
@ -173,10 +174,8 @@ void RA8876::DisplayOnff(int8_t on) {
|
||||||
uint8_t dpcr;
|
uint8_t dpcr;
|
||||||
SPI.beginTransaction(m_spiSettings);
|
SPI.beginTransaction(m_spiSettings);
|
||||||
dpcr = readReg(RA8876_REG_DPCR);
|
dpcr = readReg(RA8876_REG_DPCR);
|
||||||
|
|
||||||
if (on) {
|
if (on) {
|
||||||
dpcr |= 0x40; // Display on
|
dpcr |= 0x40; // Display on
|
||||||
dim(dimmer);
|
|
||||||
} else {
|
} else {
|
||||||
dpcr &= 0x40^0xff; // Display off
|
dpcr &= 0x40^0xff; // Display off
|
||||||
// backlight off
|
// backlight off
|
||||||
|
@ -185,12 +184,14 @@ void RA8876::DisplayOnff(int8_t on) {
|
||||||
}
|
}
|
||||||
writeReg(RA8876_REG_DPCR, dpcr);
|
writeReg(RA8876_REG_DPCR, dpcr);
|
||||||
SPI.endTransaction();
|
SPI.endTransaction();
|
||||||
|
if (on) {
|
||||||
|
dim(dimmer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 0-15
|
// 0-15
|
||||||
void RA8876::dim(uint8_t contrast) {
|
void RA8876::dim(uint8_t contrast) {
|
||||||
SPI.beginTransaction(m_spiSettings);
|
SPI.beginTransaction(m_spiSettings);
|
||||||
|
|
||||||
dimmer=contrast;
|
dimmer=contrast;
|
||||||
// pwm0 duty
|
// pwm0 duty
|
||||||
uint32_t duty=(contrast*1024)/15;
|
uint32_t duty=(contrast*1024)/15;
|
||||||
|
@ -671,10 +672,18 @@ bool RA8876::begin(void) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef ESP32
|
||||||
SPI.begin();
|
SPI.begin();
|
||||||
|
#else
|
||||||
|
SPI.begin(_sclk,_miso,_mosi , -1);
|
||||||
|
#endif
|
||||||
|
|
||||||
m_spiSettings = SPISettings(RA8876_SPI_SPEED, MSBFIRST, SPI_MODE3);
|
m_spiSettings = SPISettings(RA8876_SPI_SPEED, MSBFIRST, SPI_MODE3);
|
||||||
|
|
||||||
|
#ifdef RA8876_DEBUG
|
||||||
|
Serial.printf("RA8876 init\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
softReset();
|
softReset();
|
||||||
|
|
||||||
if (!initPLL()) {
|
if (!initPLL()) {
|
||||||
|
@ -682,24 +691,44 @@ bool RA8876::begin(void) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef RA8876_DEBUG
|
||||||
|
Serial.printf("RA8876 init pll OK\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!initMemory(m_sdramInfo)) {
|
if (!initMemory(m_sdramInfo)) {
|
||||||
//Serial.println("initMemory failed");
|
//Serial.println("initMemory failed");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef RA8876_DEBUG
|
||||||
|
Serial.printf("RA8876 init sdram OK\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!initDisplay()) {
|
if (!initDisplay()) {
|
||||||
//Serial.println("initDisplay failed");
|
//Serial.println("initDisplay failed");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef RA8876_DEBUG
|
||||||
|
Serial.printf("RA8876 init display OK\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
// Set default font
|
// Set default font
|
||||||
selectInternalFont(RA8876_FONT_SIZE_16);
|
selectInternalFont(RA8876_FONT_SIZE_16);
|
||||||
setTextScale(1);
|
setTextScale(1);
|
||||||
|
|
||||||
|
#ifdef RA8876_DEBUG
|
||||||
|
Serial.printf("RA8876 set scale OK\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
setRotation(0);
|
setRotation(0);
|
||||||
|
|
||||||
clearScreen(0);
|
clearScreen(0);
|
||||||
|
|
||||||
|
#ifdef RA8876_DEBUG
|
||||||
|
Serial.printf("RA8876 init complete\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -899,7 +928,8 @@ void RA8876::setAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) {
|
||||||
|
|
||||||
writeCmd(RA8876_REG_MRWDP); //04h();
|
writeCmd(RA8876_REG_MRWDP); //04h();
|
||||||
|
|
||||||
if (flag) SPI.endTransaction();
|
//if (flag) SPI.endTransaction();
|
||||||
|
SPI.endTransaction();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RA8876::pushColors(uint16_t *data, uint8_t len, boolean first) {
|
void RA8876::pushColors(uint16_t *data, uint8_t len, boolean first) {
|
||||||
|
@ -980,7 +1010,9 @@ void RA8876::waitWriteFifo(void) {
|
||||||
// timeout, soft reset
|
// timeout, soft reset
|
||||||
softReset();
|
softReset();
|
||||||
SPI.beginTransaction(m_spiSettings);
|
SPI.beginTransaction(m_spiSettings);
|
||||||
|
#ifdef RA8876_DEBUG
|
||||||
Serial.printf("iter timeout fifo\n");
|
Serial.printf("iter timeout fifo\n");
|
||||||
|
#endif
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1001,7 +1033,9 @@ void RA8876::wait_ready(void) {
|
||||||
// timeout, soft reset
|
// timeout, soft reset
|
||||||
softReset();
|
softReset();
|
||||||
SPI.beginTransaction(m_spiSettings);
|
SPI.beginTransaction(m_spiSettings);
|
||||||
|
#ifdef RA8876_DEBUG
|
||||||
Serial.printf("iter timeout cmd\n");
|
Serial.printf("iter timeout cmd\n");
|
||||||
|
#endif
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1188,11 +1222,13 @@ void RA8876::setTextMode(void) {
|
||||||
uint8_t icr = readReg(RA8876_REG_ICR);
|
uint8_t icr = readReg(RA8876_REG_ICR);
|
||||||
writeReg(RA8876_REG_ICR, icr | 0x04);
|
writeReg(RA8876_REG_ICR, icr | 0x04);
|
||||||
|
|
||||||
|
SPI.endTransaction();
|
||||||
if (textcolor==textbgcolor) {
|
if (textcolor==textbgcolor) {
|
||||||
setDrawMode_reg(1);
|
setDrawMode_reg(1);
|
||||||
} else {
|
} else {
|
||||||
setDrawMode_reg(0);
|
setDrawMode_reg(0);
|
||||||
}
|
}
|
||||||
|
SPI.beginTransaction(m_spiSettings);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1368,7 +1404,9 @@ size_t RA8876::xwrite(const uint8_t *buffer, size_t size) {
|
||||||
; // Ignored
|
; // Ignored
|
||||||
else if (c == '\n')
|
else if (c == '\n')
|
||||||
{
|
{
|
||||||
|
SPI.endTransaction();
|
||||||
setCursor(0, getCursorY() + getTextSizeY());
|
setCursor(0, getCursorY() + getTextSizeY());
|
||||||
|
SPI.beginTransaction(m_spiSettings);
|
||||||
writeCmd(RA8876_REG_MRWDP); // Reset current register for writing to memory
|
writeCmd(RA8876_REG_MRWDP); // Reset current register for writing to memory
|
||||||
}
|
}
|
||||||
else if ((m_fontFlags & RA8876_FONT_FLAG_XLAT_FULLWIDTH) && ((c >= 0x21) || (c <= 0x7F)))
|
else if ((m_fontFlags & RA8876_FONT_FLAG_XLAT_FULLWIDTH) && ((c >= 0x21) || (c <= 0x7F)))
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
#include <SPI.h>
|
#include <SPI.h>
|
||||||
#include <renderer.h>
|
#include <renderer.h>
|
||||||
|
|
||||||
|
#undef SPRINT
|
||||||
#define SPRINT(A) {char str[32];sprintf(str,"val: %d ",A);Serial.println((char*)str);}
|
#define SPRINT(A) {char str[32];sprintf(str,"val: %d ",A);Serial.println((char*)str);}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
* Use online command StateText to translate ON, OFF, HOLD and TOGGLE.
|
* Use online command StateText to translate ON, OFF, HOLD and TOGGLE.
|
||||||
* Use online command Prefix to translate cmnd, stat and tele.
|
* Use online command Prefix to translate cmnd, stat and tele.
|
||||||
*
|
*
|
||||||
* Updated until v8.1.0.1
|
* Updated until v8.3.0.2
|
||||||
\*********************************************************************/
|
\*********************************************************************/
|
||||||
|
|
||||||
#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English)
|
#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English)
|
||||||
|
@ -79,7 +79,7 @@
|
||||||
#define D_DATA "Datos"
|
#define D_DATA "Datos"
|
||||||
#define D_DARKLIGHT "Oscuro"
|
#define D_DARKLIGHT "Oscuro"
|
||||||
#define D_DEBUG "Debug"
|
#define D_DEBUG "Debug"
|
||||||
#define D_DEWPOINT "Dew point"
|
#define D_DEWPOINT "Punto de Rocío"
|
||||||
#define D_DISABLED "Deshabilitado"
|
#define D_DISABLED "Deshabilitado"
|
||||||
#define D_DISTANCE "Distancia"
|
#define D_DISTANCE "Distancia"
|
||||||
#define D_DNS_SERVER "Servidor DNS"
|
#define D_DNS_SERVER "Servidor DNS"
|
||||||
|
@ -98,8 +98,8 @@
|
||||||
#define D_FILE "Archivo"
|
#define D_FILE "Archivo"
|
||||||
#define D_FLOW_RATE "Caudal"
|
#define D_FLOW_RATE "Caudal"
|
||||||
#define D_FREE_MEMORY "Memoria Libre"
|
#define D_FREE_MEMORY "Memoria Libre"
|
||||||
#define D_PSR_MAX_MEMORY "PS-RAM Memory"
|
#define D_PSR_MAX_MEMORY "Memoria PS-RAM"
|
||||||
#define D_PSR_FREE_MEMORY "PS-RAM free Memory"
|
#define D_PSR_FREE_MEMORY "Memoria PS-RAM libre"
|
||||||
#define D_FREQUENCY "Frecuencia"
|
#define D_FREQUENCY "Frecuencia"
|
||||||
#define D_GAS "Gas"
|
#define D_GAS "Gas"
|
||||||
#define D_GATEWAY "Gateway"
|
#define D_GATEWAY "Gateway"
|
||||||
|
@ -140,7 +140,7 @@
|
||||||
#define D_PROGRAM_SIZE "Tamaño Programa"
|
#define D_PROGRAM_SIZE "Tamaño Programa"
|
||||||
#define D_PROJECT "Proyecto"
|
#define D_PROJECT "Proyecto"
|
||||||
#define D_RAIN "Lluvia"
|
#define D_RAIN "Lluvia"
|
||||||
#define D_RANGE "Range"
|
#define D_RANGE "Rango"
|
||||||
#define D_RECEIVED "Recibido"
|
#define D_RECEIVED "Recibido"
|
||||||
#define D_RESTART "Reiniciar"
|
#define D_RESTART "Reiniciar"
|
||||||
#define D_RESTARTING "Reiniciando"
|
#define D_RESTARTING "Reiniciando"
|
||||||
|
@ -302,7 +302,7 @@
|
||||||
#define D_OTHER_PARAMETERS "Otros parámetros"
|
#define D_OTHER_PARAMETERS "Otros parámetros"
|
||||||
#define D_TEMPLATE "Plantilla"
|
#define D_TEMPLATE "Plantilla"
|
||||||
#define D_ACTIVATE "Activar"
|
#define D_ACTIVATE "Activar"
|
||||||
#define D_DEVICE_NAME "Device Name"
|
#define D_DEVICE_NAME "Nombre de Dispositivo"
|
||||||
#define D_WEB_ADMIN_PASSWORD "Clave Administrador Web"
|
#define D_WEB_ADMIN_PASSWORD "Clave Administrador Web"
|
||||||
#define D_MQTT_ENABLE "Habilitar MQTT"
|
#define D_MQTT_ENABLE "Habilitar MQTT"
|
||||||
#define D_FRIENDLY_NAME "Nombre Amigable"
|
#define D_FRIENDLY_NAME "Nombre Amigable"
|
||||||
|
@ -780,27 +780,27 @@
|
||||||
#define D_SCRIPT_UPLOAD_FILES "Cargar Archivos"
|
#define D_SCRIPT_UPLOAD_FILES "Cargar Archivos"
|
||||||
|
|
||||||
//xsns_67_as3935.ino
|
//xsns_67_as3935.ino
|
||||||
#define D_AS3935_GAIN "gain:"
|
#define D_AS3935_GAIN "Ganancia:"
|
||||||
#define D_AS3935_ENERGY "energy:"
|
#define D_AS3935_ENERGY "Energía:"
|
||||||
#define D_AS3935_DISTANCE "distance:"
|
#define D_AS3935_DISTANCE "Distancia:"
|
||||||
#define D_AS3935_DISTURBER "disturber:"
|
#define D_AS3935_DISTURBER "Perturbancia:"
|
||||||
#define D_AS3935_VRMS "µVrms:"
|
#define D_AS3935_VRMS "µVrms:"
|
||||||
#define D_AS3935_APRX "aprx.:"
|
#define D_AS3935_APRX "aprox.:"
|
||||||
#define D_AS3935_AWAY "away"
|
#define D_AS3935_AWAY "lejos"
|
||||||
#define D_AS3935_LIGHT "lightning"
|
#define D_AS3935_LIGHT "Relámpagos"
|
||||||
#define D_AS3935_OUT "lightning out of range"
|
#define D_AS3935_OUT "Relámpagos fuera de rango"
|
||||||
#define D_AS3935_NOT "distance not determined"
|
#define D_AS3935_NOT "Distancia no determinada"
|
||||||
#define D_AS3935_ABOVE "lightning overhead"
|
#define D_AS3935_ABOVE "Relámpagos cercanos"
|
||||||
#define D_AS3935_NOISE "noise detected"
|
#define D_AS3935_NOISE "Ruido detectado"
|
||||||
#define D_AS3935_DISTDET "disturber detected"
|
#define D_AS3935_DISTDET "Perturbancia detectada"
|
||||||
#define D_AS3935_INTNOEV "Interrupt with no Event!"
|
#define D_AS3935_INTNOEV "Interrupción sin evento!"
|
||||||
#define D_AS3935_NOMESS "listening..."
|
#define D_AS3935_NOMESS "Escuchando..."
|
||||||
#define D_AS3935_ON "On"
|
#define D_AS3935_ON "Encendido"
|
||||||
#define D_AS3935_OFF "Off"
|
#define D_AS3935_OFF "Apagado"
|
||||||
#define D_AS3935_INDOORS "Indoors"
|
#define D_AS3935_INDOORS "Dentro de casa"
|
||||||
#define D_AS3935_OUTDOORS "Outdoors"
|
#define D_AS3935_OUTDOORS "Al aire libre"
|
||||||
#define D_AS3935_CAL_FAIL "calibration failed"
|
#define D_AS3935_CAL_FAIL "Falló calibración"
|
||||||
#define D_AS3935_CAL_OK "calibration set to:"
|
#define D_AS3935_CAL_OK "Calibración a:"
|
||||||
|
|
||||||
//xsns_68_opentherm.ino
|
//xsns_68_opentherm.ino
|
||||||
#define D_SENSOR_BOILER_OT_RX "OpenTherm RX"
|
#define D_SENSOR_BOILER_OT_RX "OpenTherm RX"
|
||||||
|
|
|
@ -0,0 +1,157 @@
|
||||||
|
/*
|
||||||
|
jpeg_utils.c - Version header file for Tasmota
|
||||||
|
|
||||||
|
Copyright (C) 2020 Theo Arends
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef ESP32
|
||||||
|
#ifdef JPEG_PICTS
|
||||||
|
|
||||||
|
#include "img_converters.h"
|
||||||
|
#include "esp_jpg_decode.h"
|
||||||
|
|
||||||
|
void rgb888_to_565(uint8_t *in, uint16_t *out, uint32_t len) {
|
||||||
|
uint8_t red, grn, blu;
|
||||||
|
uint16_t b , g, r;
|
||||||
|
|
||||||
|
for (uint32_t cnt=0; cnt<len; cnt++) {
|
||||||
|
red = *in++;
|
||||||
|
grn = *in++;
|
||||||
|
blu = *in++;
|
||||||
|
b = (blu >> 3) & 0x1f;
|
||||||
|
g = ((grn >> 2) & 0x3f) << 5;
|
||||||
|
r = ((red >> 3) & 0x1f) << 11;
|
||||||
|
*out++ = (r | g | b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint16_t width;
|
||||||
|
uint16_t height;
|
||||||
|
uint16_t data_offset;
|
||||||
|
const uint8_t *input;
|
||||||
|
uint8_t *output;
|
||||||
|
} rgb_jpg_decoder;
|
||||||
|
|
||||||
|
//input buffer
|
||||||
|
static uint32_t _jpg_read(void * arg, size_t index, uint8_t *buf, size_t len)
|
||||||
|
{
|
||||||
|
rgb_jpg_decoder * jpeg = (rgb_jpg_decoder *)arg;
|
||||||
|
if(buf) {
|
||||||
|
memcpy(buf, jpeg->input + index, len);
|
||||||
|
}
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
//output buffer and image width
|
||||||
|
static bool _rgb_write(void * arg, uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint8_t *data)
|
||||||
|
{
|
||||||
|
rgb_jpg_decoder * jpeg = (rgb_jpg_decoder *)arg;
|
||||||
|
if(!data){
|
||||||
|
if(x == 0 && y == 0){
|
||||||
|
//write start
|
||||||
|
jpeg->width = w;
|
||||||
|
jpeg->height = h;
|
||||||
|
//if output is null, this is BMP
|
||||||
|
if(!jpeg->output){
|
||||||
|
jpeg->output = (uint8_t *)malloc((w*h*3)+jpeg->data_offset);
|
||||||
|
if(!jpeg->output){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//write end
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t jw = jpeg->width*3;
|
||||||
|
size_t t = y * jw;
|
||||||
|
size_t b = t + (h * jw);
|
||||||
|
size_t l = x * 3;
|
||||||
|
uint8_t *out = jpeg->output+jpeg->data_offset;
|
||||||
|
uint8_t *o = out;
|
||||||
|
size_t iy, ix;
|
||||||
|
|
||||||
|
w = w * 3;
|
||||||
|
|
||||||
|
for(iy=t; iy<b; iy+=jw) {
|
||||||
|
o = out+iy+l;
|
||||||
|
for(ix=0; ix<w; ix+= 3) {
|
||||||
|
o[ix] = data[ix+2];
|
||||||
|
o[ix+1] = data[ix+1];
|
||||||
|
o[ix+2] = data[ix];
|
||||||
|
}
|
||||||
|
data+=w;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
esp_err_t esp_jpg_decode(size_t len, jpg_scale_t scale, jpg_reader_cb reader, jpg_writer_cb writer, void * arg);
|
||||||
|
|
||||||
|
|
||||||
|
bool jpg2rgb888(const uint8_t *src, size_t src_len, uint8_t * out, jpg_scale_t scale)
|
||||||
|
{
|
||||||
|
rgb_jpg_decoder jpeg;
|
||||||
|
jpeg.width = 0;
|
||||||
|
jpeg.height = 0;
|
||||||
|
jpeg.input = src;
|
||||||
|
jpeg.output = out;
|
||||||
|
jpeg.data_offset = 0;
|
||||||
|
|
||||||
|
if(esp_jpg_decode(src_len, scale, _jpg_read, _rgb_write, (void*)&jpeg) != ESP_OK){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://web.archive.org/web/20131016210645/http://www.64lines.com/jpeg-width-height
|
||||||
|
//Gets the JPEG size from the array of data passed to the function, file reference: http://www.obrador.com/essentialjpeg/headerinfo.htm
|
||||||
|
char get_jpeg_size(unsigned char* data, unsigned int data_size, unsigned short *width, unsigned short *height) {
|
||||||
|
//Check for valid JPEG image
|
||||||
|
int i=0; // Keeps track of the position within the file
|
||||||
|
if(data[i] == 0xFF && data[i+1] == 0xD8 && data[i+2] == 0xFF && data[i+3] == 0xE0) {
|
||||||
|
i += 4;
|
||||||
|
// Check for valid JPEG header (null terminated JFIF)
|
||||||
|
if(data[i+2] == 'J' && data[i+3] == 'F' && data[i+4] == 'I' && data[i+5] == 'F' && data[i+6] == 0x00) {
|
||||||
|
//Retrieve the block length of the first block since the first block will not contain the size of file
|
||||||
|
unsigned short block_length = data[i] * 256 + data[i+1];
|
||||||
|
while(i<data_size) {
|
||||||
|
i+=block_length; //Increase the file index to get to the next block
|
||||||
|
if(i >= data_size) return false; //Check to protect against segmentation faults
|
||||||
|
if(data[i] != 0xFF) return false; //Check that we are truly at the start of another block
|
||||||
|
if(data[i+1] == 0xC0) { //0xFFC0 is the "Start of frame" marker which contains the file size
|
||||||
|
//The structure of the 0xFFC0 block is quite simple [0xFFC0][ushort length][uchar precision][ushort x][ushort y]
|
||||||
|
*height = data[i+5]*256 + data[i+6];
|
||||||
|
*width = data[i+7]*256 + data[i+8];
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
i+=2; //Skip the block marker
|
||||||
|
block_length = data[i] * 256 + data[i+1]; //Go to the next block
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false; //If this point is reached then no size was found
|
||||||
|
}else{ return false; } //Not a valid JFIF string
|
||||||
|
|
||||||
|
}else{ return false; } //Not a valid SOI header
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // JPEG_PICTS
|
||||||
|
#endif //ESP32
|
|
@ -1500,47 +1500,109 @@ void CmndDisplayRows(void)
|
||||||
/*********************************************************************************************\
|
/*********************************************************************************************\
|
||||||
* optional drivers
|
* optional drivers
|
||||||
\*********************************************************************************************/
|
\*********************************************************************************************/
|
||||||
|
#ifdef ESP32
|
||||||
|
#ifdef JPEG_PICTS
|
||||||
|
#include "img_converters.h"
|
||||||
|
#include "esp_jpg_decode.h"
|
||||||
|
bool jpg2rgb888(const uint8_t *src, size_t src_len, uint8_t * out, jpg_scale_t scale);
|
||||||
|
char get_jpeg_size(unsigned char* data, unsigned int data_size, unsigned short *width, unsigned short *height);
|
||||||
|
void rgb888_to_565(uint8_t *in, uint16_t *out, uint32_t len);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#if defined(USE_SCRIPT_FATFS) && defined(USE_SCRIPT)
|
#if defined(USE_SCRIPT_FATFS) && defined(USE_SCRIPT)
|
||||||
|
#define XBUFF_LEN 128
|
||||||
void Draw_RGB_Bitmap(char *file,uint16_t xp, uint16_t yp) {
|
void Draw_RGB_Bitmap(char *file,uint16_t xp, uint16_t yp) {
|
||||||
if (!renderer) return;
|
if (!renderer) return;
|
||||||
|
|
||||||
//if (!strstr(file,".RGB")) return;
|
|
||||||
File fp;
|
File fp;
|
||||||
fp=SD.open(file,FILE_READ);
|
char *ending = strrchr(file,'.');
|
||||||
if (!fp) return;
|
if (!ending) return;
|
||||||
uint16_t xsize;
|
ending++;
|
||||||
fp.read((uint8_t*)&xsize,2);
|
char estr[8];
|
||||||
uint16_t ysize;
|
memset(estr,0,sizeof(estr));
|
||||||
fp.read((uint8_t*)&ysize,2);
|
for (uint32_t cnt=0; cnt<strlen(ending); cnt++) {
|
||||||
|
estr[cnt]=tolower(ending[cnt]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strcmp(estr,"rgb")) {
|
||||||
|
// special rgb format
|
||||||
|
fp=SD.open(file,FILE_READ);
|
||||||
|
if (!fp) return;
|
||||||
|
uint16_t xsize;
|
||||||
|
fp.read((uint8_t*)&xsize,2);
|
||||||
|
uint16_t ysize;
|
||||||
|
fp.read((uint8_t*)&ysize,2);
|
||||||
#if 1
|
#if 1
|
||||||
#define XBUFF 128
|
uint16_t xdiv=xsize/XBUFF_LEN;
|
||||||
uint16_t xdiv=xsize/XBUFF;
|
renderer->setAddrWindow(xp,yp,xp+xsize,yp+ysize);
|
||||||
renderer->setAddrWindow(xp,yp,xp+xsize,yp+ysize);
|
for(int16_t j=0; j<ysize; j++) {
|
||||||
for(int16_t j=0; j<ysize; j++) {
|
for(int16_t i=0; i<xsize; i+=XBUFF_LEN) {
|
||||||
for(int16_t i=0; i<xsize; i+=XBUFF) {
|
uint16_t rgb[XBUFF_LEN];
|
||||||
uint16_t rgb[XBUFF];
|
uint16_t len=fp.read((uint8_t*)rgb,XBUFF_LEN*2);
|
||||||
uint16_t len=fp.read((uint8_t*)rgb,XBUFF*2);
|
if (len>=2) renderer->pushColors(rgb,len/2,true);
|
||||||
if (len>=2) renderer->pushColors(rgb,len/2,true);
|
}
|
||||||
|
OsWatchLoop();
|
||||||
}
|
}
|
||||||
OsWatchLoop();
|
renderer->setAddrWindow(0,0,0,0);
|
||||||
}
|
|
||||||
renderer->setAddrWindow(0,0,0,0);
|
|
||||||
#else
|
#else
|
||||||
for(int16_t j=0; j<ysize; j++) {
|
for(int16_t j=0; j<ysize; j++) {
|
||||||
for(int16_t i=0; i<xsize; i++ ) {
|
for(int16_t i=0; i<xsize; i++ ) {
|
||||||
uint16_t rgb;
|
uint16_t rgb;
|
||||||
uint8_t res=fp.read((uint8_t*)&rgb,2);
|
uint8_t res=fp.read((uint8_t*)&rgb,2);
|
||||||
if (!res) break;
|
if (!res) break;
|
||||||
renderer->writePixel(xp+i,yp,rgb);
|
renderer->writePixel(xp+i,yp,rgb);
|
||||||
|
}
|
||||||
|
delay(0);
|
||||||
|
OsWatchLoop();
|
||||||
|
yp++;
|
||||||
}
|
}
|
||||||
delay(0);
|
|
||||||
OsWatchLoop();
|
|
||||||
yp++;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
fp.close();
|
fp.close();
|
||||||
|
} else if (!strcmp(estr,"jpg")) {
|
||||||
|
// jpeg files on ESP32 with more memory
|
||||||
|
#ifdef ESP32
|
||||||
|
#ifdef JPEG_PICTS
|
||||||
|
if (psramFound()) {
|
||||||
|
fp=SD.open(file,FILE_READ);
|
||||||
|
if (!fp) return;
|
||||||
|
uint32_t size = fp.size();
|
||||||
|
uint8_t *mem = (uint8_t *)heap_caps_malloc(size+4, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
|
||||||
|
if (mem) {
|
||||||
|
uint8_t res=fp.read(mem, size);
|
||||||
|
if (res) {
|
||||||
|
uint16_t xsize;
|
||||||
|
uint16_t ysize;
|
||||||
|
if (mem[0]==0xff && mem[1]==0xd8) {
|
||||||
|
get_jpeg_size(mem, size, &xsize, &ysize);
|
||||||
|
//Serial.printf(" x,y %d - %d\n",xsize, ysize );
|
||||||
|
if (xsize && ysize) {
|
||||||
|
uint8_t *out_buf = (uint8_t *)heap_caps_malloc((xsize*ysize*3)+4, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
|
||||||
|
if (out_buf) {
|
||||||
|
uint8_t *ob=out_buf;
|
||||||
|
jpg2rgb888(mem, size, out_buf, (jpg_scale_t)JPG_SCALE_NONE);
|
||||||
|
uint16_t pixels=xsize*ysize/XBUFF_LEN;
|
||||||
|
renderer->setAddrWindow(xp,yp,xp+xsize,yp+ysize);
|
||||||
|
for(int32_t j=0; j<pixels; j++) {
|
||||||
|
uint16_t rbuff[XBUFF_LEN*2];
|
||||||
|
rgb888_to_565(ob, rbuff, XBUFF_LEN);
|
||||||
|
ob+=XBUFF_LEN*3;
|
||||||
|
renderer->pushColors(rbuff,XBUFF_LEN,true);
|
||||||
|
OsWatchLoop();
|
||||||
|
}
|
||||||
|
renderer->setAddrWindow(0,0,0,0);
|
||||||
|
free(out_buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(mem);
|
||||||
|
}
|
||||||
|
fp.close();
|
||||||
|
}
|
||||||
|
#endif // JPEG_PICTS
|
||||||
|
#endif // ESP32
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -71,11 +71,24 @@ void RA8876_InitDriver()
|
||||||
fg_color = RA8876_WHITE;
|
fg_color = RA8876_WHITE;
|
||||||
bg_color = RA8876_BLACK;
|
bg_color = RA8876_BLACK;
|
||||||
|
|
||||||
|
#ifdef ESP32
|
||||||
|
#define HW_SPI_MOSI 23
|
||||||
|
#define HW_SPI_MISO 19
|
||||||
|
#define HW_SPI_CLK 18
|
||||||
|
#else
|
||||||
|
#undef HW_SPI_MOSI
|
||||||
|
#define HW_SPI_MOSI 13
|
||||||
|
#undef HW_SPI_MISO
|
||||||
|
#define HW_SPI_MISO 12
|
||||||
|
#undef HW_SPI_CLK
|
||||||
|
#define HW_SPI_CLK 14
|
||||||
|
#endif
|
||||||
|
|
||||||
// init renderer, must use hardware spi
|
// init renderer, must use hardware spi
|
||||||
if (PinUsed(GPIO_SSPI_CS) && (Pin(GPIO_SSPI_MOSI)==13) && (Pin(GPIO_SSPI_MISO)==12) && (Pin(GPIO_SSPI_SCLK)==14)) {
|
if (PinUsed(GPIO_SSPI_CS) && (Pin(GPIO_SSPI_MOSI)==HW_SPI_MOSI) && (Pin(GPIO_SSPI_MISO)==HW_SPI_MISO) && (Pin(GPIO_SSPI_SCLK)==HW_SPI_CLK)) {
|
||||||
ra8876 = new RA8876(Pin(GPIO_SSPI_CS),Pin(GPIO_SSPI_MOSI),Pin(GPIO_SSPI_MISO),Pin(GPIO_SSPI_SCLK),Pin(GPIO_BACKLIGHT));
|
ra8876 = new RA8876(Pin(GPIO_SSPI_CS),Pin(GPIO_SSPI_MOSI),Pin(GPIO_SSPI_MISO),Pin(GPIO_SSPI_SCLK),Pin(GPIO_BACKLIGHT));
|
||||||
} else {
|
} else {
|
||||||
if (PinUsed(GPIO_SPI_CS) && (Pin(GPIO_SPI_MOSI)==13) && (Pin(GPIO_SPI_MISO)==12) && (Pin(GPIO_SPI_CLK)==14)) {
|
if (PinUsed(GPIO_SPI_CS) && (Pin(GPIO_SPI_MOSI)==HW_SPI_MOSI) && (Pin(GPIO_SPI_MISO)==HW_SPI_MISO) && (Pin(GPIO_SPI_CLK)==HW_SPI_CLK)) {
|
||||||
ra8876 = new RA8876(Pin(GPIO_SPI_CS),Pin(GPIO_SPI_MOSI),Pin(GPIO_SPI_MISO),Pin(GPIO_SPI_CLK),Pin(GPIO_BACKLIGHT));
|
ra8876 = new RA8876(Pin(GPIO_SPI_CS),Pin(GPIO_SPI_MOSI),Pin(GPIO_SPI_MISO),Pin(GPIO_SPI_CLK),Pin(GPIO_BACKLIGHT));
|
||||||
} else {
|
} else {
|
||||||
return;
|
return;
|
||||||
|
|
Loading…
Reference in New Issue