mirror of https://github.com/arendst/Tasmota.git
udisplay parallel support
This commit is contained in:
parent
baace8c133
commit
43c6cf6e26
|
@ -639,6 +639,9 @@ void Renderer::ep_update_mode(uint8_t mode) {
|
|||
void Renderer::ep_update_area(uint16_t xp, uint16_t yp, uint16_t width, uint16_t height, uint8_t mode) {
|
||||
}
|
||||
|
||||
uint32_t Renderer::get_sr_touch(uint32_t xp, uint32_t xm, uint32_t yp, uint32_t ym) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// #ifndef USE_DISPLAY_LVGL_ONLY
|
||||
|
||||
|
|
|
@ -90,6 +90,7 @@ public:
|
|||
virtual LVGL_PARAMS *lvgl_pars(void);
|
||||
virtual void ep_update_mode(uint8_t mode);
|
||||
virtual void ep_update_area(uint16_t xp, uint16_t yp, uint16_t width, uint16_t height, uint8_t mode);
|
||||
virtual uint32_t get_sr_touch(uint32_t xp, uint32_t xm, uint32_t yp, uint32_t ym);
|
||||
|
||||
void setDrawMode(uint8_t mode);
|
||||
uint8_t drawmode;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -5,12 +5,38 @@
|
|||
#include <renderer.h>
|
||||
#include <Wire.h>
|
||||
#include <SPI.h>
|
||||
|
||||
|
||||
#ifdef ESP32
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32S3
|
||||
#define USE_ESP32_S3
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef ESP32
|
||||
#include "driver/spi_master.h"
|
||||
#endif
|
||||
|
||||
#ifdef USE_ESP32_S3
|
||||
#include <esp_lcd_panel_io.h>
|
||||
#include "esp_private/gdma.h"
|
||||
#include <hal/gpio_ll.h>
|
||||
#include <hal/lcd_hal.h>
|
||||
#include <soc/lcd_cam_reg.h>
|
||||
#include <soc/lcd_cam_struct.h>
|
||||
static inline volatile uint32_t* get_gpio_hi_reg(int_fast8_t pin) { return (pin & 32) ? &GPIO.out1_w1ts.val : &GPIO.out_w1ts; }
|
||||
//static inline volatile uint32_t* get_gpio_hi_reg(int_fast8_t pin) { return (volatile uint32_t*)((pin & 32) ? 0x60004014 : 0x60004008) ; } // workaround Eratta
|
||||
static inline volatile uint32_t* get_gpio_lo_reg(int_fast8_t pin) { return (pin & 32) ? &GPIO.out1_w1tc.val : &GPIO.out_w1tc; }
|
||||
//static inline volatile uint32_t* get_gpio_lo_reg(int_fast8_t pin) { return (volatile uint32_t*)((pin & 32) ? 0x60004018 : 0x6000400C) ; }
|
||||
static inline bool gpio_in(int_fast8_t pin) { return ((pin & 32) ? GPIO.in1.data : GPIO.in) & (1 << (pin & 31)); }
|
||||
static inline void gpio_hi(int_fast8_t pin) { if (pin >= 0) *get_gpio_hi_reg(pin) = 1 << (pin & 31); } // ESP_LOGI("LGFX", "gpio_hi: %d", pin); }
|
||||
static inline void gpio_lo(int_fast8_t pin) { if (pin >= 0) *get_gpio_lo_reg(pin) = 1 << (pin & 31); } // ESP_LOGI("LGFX", "gpio_lo: %d", pin); }
|
||||
#endif
|
||||
|
||||
#define _UDSP_I2C 1
|
||||
#define _UDSP_SPI 2
|
||||
#define _UDSP_PAR8 3
|
||||
#define _UDSP_PAR16 4
|
||||
|
||||
#define UDISP1_WHITE 1
|
||||
#define UDISP1_BLACK 0
|
||||
|
@ -76,6 +102,22 @@ enum uColorType { uCOLOR_BW, uCOLOR_COLOR };
|
|||
|
||||
#define LUTMAXSIZE 64
|
||||
|
||||
#ifdef USE_ESP32_S3
|
||||
struct esp_lcd_i80_bus_t {
|
||||
int bus_id; // Bus ID, index from 0
|
||||
portMUX_TYPE spinlock; // spinlock used to protect i80 bus members(hal, device_list, cur_trans)
|
||||
lcd_hal_context_t hal; // Hal object
|
||||
size_t bus_width; // Number of data lines
|
||||
intr_handle_t intr; // LCD peripheral interrupt handle
|
||||
void* pm_lock; // Power management lock
|
||||
size_t num_dma_nodes; // Number of DMA descriptors
|
||||
uint8_t *format_buffer; // The driver allocates an internal buffer for DMA to do data format transformer
|
||||
size_t resolution_hz; // LCD_CLK resolution, determined by selected clock source
|
||||
gdma_channel_handle_t dma_chan; // DMA channel handle
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
class uDisplay : public Renderer {
|
||||
public:
|
||||
uDisplay(char *);
|
||||
|
@ -110,11 +152,11 @@ class uDisplay : public Renderer {
|
|||
void drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color);
|
||||
uint32_t str2c(char **sp, char *vp, uint32_t len);
|
||||
void i2c_command(uint8_t val);
|
||||
void spi_command_one(uint8_t val);
|
||||
void spi_command(uint8_t val);
|
||||
void spi_data8(uint8_t val);
|
||||
void spi_data16(uint16_t val);
|
||||
void spi_data32(uint32_t val);
|
||||
void ulcd_command_one(uint8_t val);
|
||||
void ulcd_command(uint8_t val);
|
||||
void ulcd_data8(uint8_t val);
|
||||
void ulcd_data16(uint16_t val);
|
||||
void ulcd_data32(uint32_t val);
|
||||
void write8(uint8_t val);
|
||||
void write8_slow(uint8_t val);
|
||||
void write9(uint8_t val, uint8_t dc);
|
||||
|
@ -226,6 +268,44 @@ class uDisplay : public Renderer {
|
|||
int16_t rotmap_ymin;
|
||||
int16_t rotmap_ymax;
|
||||
void pushColorsMono(uint16_t *data, uint16_t len, bool rgb16_swap = false);
|
||||
|
||||
#ifdef USE_ESP32_S3
|
||||
int8_t par_cs;
|
||||
int8_t par_rs;
|
||||
int8_t par_wr;
|
||||
int8_t par_rd;
|
||||
|
||||
int8_t par_dbl[8];
|
||||
int8_t par_dbh[8];
|
||||
|
||||
esp_lcd_i80_bus_handle_t _i80_bus = nullptr;
|
||||
gdma_channel_handle_t _dma_chan;
|
||||
lldesc_t *_dmadesc = nullptr;
|
||||
uint32_t _dmadesc_size = 0;
|
||||
uint32_t _clock_reg_value;
|
||||
void calcClockDiv(uint32_t* div_a, uint32_t* div_b, uint32_t* div_n, uint32_t* clkcnt, uint32_t baseClock, uint32_t targetFreq);
|
||||
void _alloc_dmadesc(size_t len);
|
||||
void _setup_dma_desc_links(const uint8_t *data, int32_t len);
|
||||
void pb_beginTransaction(void);
|
||||
void pb_endTransaction(void);
|
||||
void pb_wait(void);
|
||||
bool pb_busy(void);
|
||||
void _pb_init_pin(bool);
|
||||
bool pb_writeCommand(uint32_t data, uint_fast8_t bit_length);
|
||||
void pb_writeData(uint32_t data, uint_fast8_t bit_length);
|
||||
void pb_pushPixels(uint16_t* data, uint32_t length, bool swap_bytes, bool use_dma);
|
||||
void pb_writeBytes(const uint8_t* data, uint32_t length, bool use_dma);
|
||||
void _send_align_data(void);
|
||||
volatile lcd_cam_dev_t* _dev;
|
||||
uint32_t* _cache_flip;
|
||||
static constexpr size_t CACHE_SIZE = 256;
|
||||
uint32_t _cache[2][CACHE_SIZE / sizeof(uint32_t)];
|
||||
bool _has_align_data;
|
||||
uint8_t _align_data;
|
||||
void cs_control(bool level);
|
||||
uint32_t get_sr_touch(uint32_t xp, uint32_t xm, uint32_t yp, uint32_t ym);
|
||||
#endif
|
||||
|
||||
#ifdef ESP32
|
||||
// dma section
|
||||
bool DMA_Enabled = false;
|
||||
|
|
|
@ -582,7 +582,6 @@ void DisplayText(void)
|
|||
// pad field with spaces fxx
|
||||
var = atoiv(cp, &fill);
|
||||
cp += var;
|
||||
linebuf[fill] = 0;
|
||||
break;
|
||||
#ifdef USE_UFILESYS
|
||||
case 'P':
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
xdrv_55_touch.ino - Touch contolers
|
||||
xdrv_55_touch.ino - Touch controllers
|
||||
|
||||
Copyright (C) 2021 Gerhard Mutz, Theo Arends & Stephan Hadinger
|
||||
|
||||
|
@ -19,24 +19,24 @@
|
|||
|
||||
/*******************************************************************************************\
|
||||
* Universal TouchScreen driver, extensible via Berry
|
||||
*
|
||||
*
|
||||
* API:
|
||||
* void Touch_Init() - TODO
|
||||
*
|
||||
*
|
||||
* uint32_t Touch_Status(int32_t sel)
|
||||
* 0: return 1 if TSGlobal.touched
|
||||
* 1: return x
|
||||
* 2: return y
|
||||
* -1: return raw x (before conersion for resistive)
|
||||
* -1: return raw x (before conversion for resistive)
|
||||
* -2: return raw y
|
||||
*
|
||||
*
|
||||
* void Touch_Check(void(*rotconvert)(int16_t *x, int16_t *y))
|
||||
*
|
||||
*
|
||||
* void TS_RotConvert(int16_t *x, int16_t *y) - calls the renderer's rotation converter
|
||||
\*******************************************************************************************/
|
||||
|
||||
|
||||
#if defined(USE_LVGL_TOUCHSCREEN) || defined(USE_FT5206) || defined(USE_XPT2046) || defined(USE_LILYGO47) || defined(USE_TOUCH_BUTTONS)
|
||||
#if defined(USE_LVGL_TOUCHSCREEN) || defined(USE_FT5206) || defined(USE_XPT2046) || defined(USE_LILYGO47) || defined(USE_TOUCH_BUTTONS) || defined(SIMPLE_RES_TOUCH)
|
||||
|
||||
#ifdef USE_DISPLAY_LVGL_ONLY
|
||||
#undef USE_TOUCH_BUTTONS
|
||||
|
@ -73,6 +73,7 @@ TSGlobal_t TSGlobal;
|
|||
|
||||
bool FT5206_found = false;
|
||||
bool XPT2046_found = false;
|
||||
bool SRES_found = false;
|
||||
|
||||
#ifndef MAX_TOUCH_BUTTONS
|
||||
#define MAX_TOUCH_BUTTONS 16
|
||||
|
@ -131,6 +132,58 @@ uint32_t Touch_Status(int32_t sel) {
|
|||
uint8_t tbstate[3];
|
||||
#endif // USE_M5STACK_CORE2
|
||||
|
||||
|
||||
// simple resistive touch pins
|
||||
// with dma it should check for active transfers
|
||||
// so currently dont use dma
|
||||
#ifdef SIMPLE_RES_TOUCH
|
||||
struct RES_TOUCH {
|
||||
int8_t xplus;
|
||||
int8_t xminus;
|
||||
int8_t yplus;
|
||||
int8_t yminus;
|
||||
uint16_t xp;
|
||||
uint16_t yp;
|
||||
} sres_touch;
|
||||
|
||||
void Simple_ResTouch_Init(int8_t xp, int8_t xm, int8_t yp, int8_t ym) {
|
||||
sres_touch.xplus = xp; // d1
|
||||
sres_touch.xminus = xm; // cs
|
||||
sres_touch.yplus = yp; // rs
|
||||
sres_touch.yminus = ym; // d0
|
||||
SRES_found = true;
|
||||
AddLog(LOG_LEVEL_INFO, PSTR("TS: simple resistive touch init"));
|
||||
}
|
||||
|
||||
#define SRES_THRESHOLD 500
|
||||
|
||||
bool SRES_touched() {
|
||||
uint32_t val = renderer->get_sr_touch(sres_touch.xplus, sres_touch.xminus, sres_touch.yplus, sres_touch.yminus);
|
||||
if (val == 0) {
|
||||
return false;
|
||||
}
|
||||
sres_touch.xp = val >> 16;
|
||||
sres_touch.yp = val & 0xffff;
|
||||
|
||||
int16_t xp = sres_touch.xp;
|
||||
int16_t yp = sres_touch.yp;
|
||||
|
||||
//AddLog(LOG_LEVEL_INFO, "TS x=%i y=%i)", xp, yp);
|
||||
|
||||
if (xp > SRES_THRESHOLD && yp > SRES_THRESHOLD) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int16_t SRES_x() {
|
||||
return sres_touch.xp;
|
||||
}
|
||||
int16_t SRES_y() {
|
||||
return sres_touch.yp;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef USE_FT5206
|
||||
#include <FT5206.h>
|
||||
// touch panel controller
|
||||
|
@ -189,11 +242,20 @@ int16_t XPT2046_y() {
|
|||
}
|
||||
#endif // USE_XPT2046
|
||||
|
||||
|
||||
|
||||
void Touch_Check(void(*rotconvert)(int16_t *x, int16_t *y)) {
|
||||
static bool was_touched = false; // flag used to log the data sent when the screen was just released
|
||||
|
||||
|
||||
#ifdef SIMPLE_RES_TOUCH
|
||||
if (SRES_found) {
|
||||
TSGlobal.touched = SRES_touched();
|
||||
if (TSGlobal.touched) {
|
||||
TSGlobal.raw_touch_xp = SRES_x();
|
||||
TSGlobal.raw_touch_yp = SRES_y();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef USE_FT5206
|
||||
if (FT5206_found) {
|
||||
TSGlobal.touched = FT5206_touched();
|
||||
|
@ -213,6 +275,7 @@ void Touch_Check(void(*rotconvert)(int16_t *x, int16_t *y)) {
|
|||
}
|
||||
}
|
||||
#endif // USE_XPT2046
|
||||
|
||||
TSGlobal.touch_xp = TSGlobal.raw_touch_xp;
|
||||
TSGlobal.touch_yp = TSGlobal.raw_touch_yp;
|
||||
|
||||
|
@ -270,6 +333,8 @@ void Touch_Check(void(*rotconvert)(int16_t *x, int16_t *y)) {
|
|||
}
|
||||
}
|
||||
|
||||
extern uint8_t GT911_found;
|
||||
|
||||
#ifdef USE_TOUCH_BUTTONS
|
||||
void Touch_MQTT(uint8_t index, const char *cp, uint32_t val) {
|
||||
#ifdef USE_FT5206
|
||||
|
@ -277,12 +342,20 @@ void Touch_MQTT(uint8_t index, const char *cp, uint32_t val) {
|
|||
#endif
|
||||
#ifdef USE_XPT2046
|
||||
if (XPT2046_found) ResponseTime_P(PSTR(",\"XPT2046\":{\"%s%d\":\"%d\"}}"), cp, index+1, val);
|
||||
#endif // USE_XPT2046
|
||||
#ifdef USE_GT911
|
||||
if (GT911_found) ResponseTime_P(PSTR(",\"GT911\":{\"%s%d\":\"%d\"}}"), cp, index+1, val);
|
||||
#endif // USE_XPT2046
|
||||
MqttPublishTeleSensor();
|
||||
}
|
||||
|
||||
void EP_Drawbutton(uint32_t count) {
|
||||
renderer->ep_update_area(buttons[count]->spars.xp, buttons[count]->spars.yp, buttons[count]->spars.xs, buttons[count]->spars.ys, 3);
|
||||
}
|
||||
|
||||
void Touch_RDW_BUTT(uint32_t count, uint32_t pwr) {
|
||||
buttons[count]->xdrawButton(pwr);
|
||||
EP_Drawbutton(count);
|
||||
if (pwr) buttons[count]->vpower.on_off = 1;
|
||||
else buttons[count]->vpower.on_off = 0;
|
||||
}
|
||||
|
@ -293,8 +366,8 @@ void CheckTouchButtons(bool touched, int16_t touch_x, int16_t touch_y) {
|
|||
uint8_t vbutt=0;
|
||||
|
||||
if (!renderer) return;
|
||||
if (TSGlobal.touched) {
|
||||
// AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("touch after convert %d - %d"), pLoc.x, pLoc.y);
|
||||
if (touched) {
|
||||
//AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("touch after convert %d - %d"), touch_x, touch_y);
|
||||
// now must compare with defined buttons
|
||||
for (uint8_t count = 0; count < MAX_TOUCH_BUTTONS; count++) {
|
||||
if (buttons[count]) {
|
||||
|
@ -307,8 +380,8 @@ void CheckTouchButtons(bool touched, int16_t touch_x, int16_t touch_y) {
|
|||
if (!buttons[count]->vpower.is_virtual) {
|
||||
uint8_t pwr=bitRead(TasmotaGlobal.power, rbutt);
|
||||
if (!SendKey(KEY_BUTTON, rbutt+1, POWER_TOGGLE)) {
|
||||
ExecuteCommandPower(rbutt+1, POWER_TOGGLE, SRC_BUTTON);
|
||||
Touch_RDW_BUTT(count, !pwr);
|
||||
ExecuteCommandPower(rbutt+1, POWER_TOGGLE, SRC_BUTTON);
|
||||
}
|
||||
} else {
|
||||
// virtual button
|
||||
|
@ -323,7 +396,9 @@ void CheckTouchButtons(bool touched, int16_t touch_x, int16_t touch_y) {
|
|||
cp="PBT";
|
||||
}
|
||||
buttons[count]->xdrawButton(buttons[count]->vpower.on_off);
|
||||
EP_Drawbutton(count);
|
||||
Touch_MQTT(count, cp, buttons[count]->vpower.on_off);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -337,6 +412,7 @@ void CheckTouchButtons(bool touched, int16_t touch_x, int16_t touch_y) {
|
|||
// slider
|
||||
if (buttons[count]->didhit(touch_x, touch_y)) {
|
||||
uint16_t value = buttons[count]->UpdateSlider(touch_x, touch_y);
|
||||
EP_Drawbutton(count);
|
||||
Touch_MQTT(count, "SLD", value);
|
||||
}
|
||||
}
|
||||
|
@ -356,6 +432,7 @@ void CheckTouchButtons(bool touched, int16_t touch_x, int16_t touch_y) {
|
|||
buttons[count]->vpower.on_off = 0;
|
||||
Touch_MQTT(count,"PBT", buttons[count]->vpower.on_off);
|
||||
buttons[count]->xdrawButton(buttons[count]->vpower.on_off);
|
||||
EP_Drawbutton(count);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -371,8 +448,6 @@ void CheckTouchButtons(bool touched, int16_t touch_x, int16_t touch_y) {
|
|||
}
|
||||
}
|
||||
}
|
||||
TSGlobal.raw_touch_xp = TSGlobal.touch_xp = 0;
|
||||
TSGlobal.raw_touch_yp = TSGlobal.touch_yp = 0;
|
||||
}
|
||||
}
|
||||
#endif // USE_TOUCH_BUTTONS
|
||||
|
@ -391,7 +466,7 @@ bool Xdrv55(uint8_t function) {
|
|||
case FUNC_INIT:
|
||||
break;
|
||||
case FUNC_EVERY_100_MSECOND:
|
||||
if (FT5206_found || XPT2046_found) {
|
||||
if (FT5206_found || XPT2046_found || SRES_found) {
|
||||
Touch_Check(TS_RotConvert);
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -33,6 +33,10 @@ uint8_t ctouch_counter;
|
|||
extern FS *ffsp;
|
||||
#endif
|
||||
|
||||
|
||||
enum {GPIO_DP_RES=GPIO_SENSOR_END-1,GPIO_DP_CS,GPIO_DP_RS,GPIO_DP_WR,GPIO_DP_RD,GPIO_DPAR0,GPIO_DPAR1,GPIO_DPAR2,GPIO_DPAR3,GPIO_DPAR4,GPIO_DPAR5,GPIO_DPAR6,GPIO_DPAR7,GPIO_DPAR8,GPIO_DPAR9,GPIO_DPAR10,GPIO_DPAR11,GPIO_DPAR12,GPIO_DPAR13,GPIO_DPAR14,GPIO_DPAR15};
|
||||
|
||||
|
||||
#ifndef USE_DISPLAY
|
||||
uint8_t color_type;
|
||||
uint16_t fg_color;
|
||||
|
@ -46,7 +50,6 @@ extern uint16_t bg_color;
|
|||
|
||||
#define DISPDESC_SIZE 1000
|
||||
|
||||
|
||||
void Core2DisplayPower(uint8_t on);
|
||||
void Core2DisplayDim(uint8_t dim);
|
||||
|
||||
|
@ -228,6 +231,44 @@ int8_t cs;
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32S3
|
||||
int8_t xp, xm, yp, ym;
|
||||
cp = strstr(ddesc, "PAR,");
|
||||
if (cp) {
|
||||
cp += 4;
|
||||
// 8 or 16 bus
|
||||
uint8_t mode = strtol(cp, &cp, 10);
|
||||
cp++;
|
||||
|
||||
replacepin(&cp, Pin(GPIO_DP_RES));
|
||||
xm = replacepin(&cp, Pin(GPIO_DP_CS));
|
||||
yp = replacepin(&cp, Pin(GPIO_DP_RS));
|
||||
replacepin(&cp, Pin(GPIO_DP_WR));
|
||||
replacepin(&cp, Pin(GPIO_DP_RD));
|
||||
replacepin(&cp, Pin(GPIO_BACKLIGHT));
|
||||
|
||||
ym = replacepin(&cp, Pin(GPIO_DPAR0));
|
||||
xp = replacepin(&cp, Pin(GPIO_DPAR1));
|
||||
|
||||
replacepin(&cp, Pin(GPIO_DPAR2));
|
||||
replacepin(&cp, Pin(GPIO_DPAR3));
|
||||
replacepin(&cp, Pin(GPIO_DPAR4));
|
||||
replacepin(&cp, Pin(GPIO_DPAR5));
|
||||
replacepin(&cp, Pin(GPIO_DPAR6));
|
||||
replacepin(&cp, Pin(GPIO_DPAR7));
|
||||
|
||||
if (mode == 16) {
|
||||
replacepin(&cp, Pin(GPIO_DPAR8));
|
||||
replacepin(&cp, Pin(GPIO_DPAR9));
|
||||
replacepin(&cp, Pin(GPIO_DPAR10));
|
||||
replacepin(&cp, Pin(GPIO_DPAR11));
|
||||
replacepin(&cp, Pin(GPIO_DPAR12));
|
||||
replacepin(&cp, Pin(GPIO_DPAR13));
|
||||
replacepin(&cp, Pin(GPIO_DPAR14));
|
||||
replacepin(&cp, Pin(GPIO_DPAR15));
|
||||
}
|
||||
}
|
||||
#endif // CONFIG_IDF_TARGET_ESP32S3
|
||||
/*
|
||||
File fp;
|
||||
fp = ffsp->open("/dump.txt", "w");
|
||||
|
@ -293,6 +334,16 @@ int8_t cs;
|
|||
}
|
||||
#endif // USE_XPT2046
|
||||
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32S3
|
||||
#ifdef SIMPLE_RES_TOUCH
|
||||
cp = strstr(ddesc, ":TR,");
|
||||
if (cp) {
|
||||
cp += 4;
|
||||
Simple_ResTouch_Init(xp, xm, yp, ym);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
uint8_t inirot = Settings->display_rotate;
|
||||
|
||||
cp = strstr(ddesc, ":r,");
|
||||
|
|
Loading…
Reference in New Issue