This commit is contained in:
2026-02-12 01:27:25 -08:00
parent 0e91b56966
commit bf3aca0d38
322 changed files with 297928 additions and 93 deletions

View File

@@ -0,0 +1,268 @@
/*******************************************************************************
* Arduino VNC
* This is a simple VNC sample
*
* Dependent libraries:
* ArduinoVNC: https://github.com/moononournation/arduinoVNC.git
*
* Touch libraries:
* FT6X36: https://github.com/strange-v/FT6X36.git
* GT911: https://github.com/TAMCTec/gt911-arduino.git
* XPT2046: https://github.com/PaulStoffregen/XPT2046_Touchscreen.git
*
* Setup steps:
* 1. Fill your own SSID_NAME, SSID_PASSWORD, VNC_IP, VNC_PORT and VNC_PASSWORD
* 2. Change your LCD parameters in Arduino_GFX setting
******************************************************************************/
/* WiFi settings */
const char *SSID_NAME = "YourAP";
const char *SSID_PASSWORD = "PleaseInputYourPasswordHere";
const char *VNC_IP = "192.168.12.34";
const uint16_t VNC_PORT = 5901;
const char *VNC_PASSWORD = "PleaseInputYourPasswordHere";
/*******************************************************************************
* Please config the touch panel in touch.h
******************************************************************************/
#include "touch.h"
/*******************************************************************************
* Please config the optional keyboard in keyboard.h
******************************************************************************/
#include "keyboard.h"
/*******************************************************************************
* Start of Arduino_GFX setting
*
* Arduino_GFX try to find the settings depends on selected board in Arduino IDE
* Or you can define the display dev kit not in the board list
* Defalult pin list for non display dev kit:
* Arduino Nano, Micro and more: CS: 9, DC: 8, RST: 7, BL: 6, SCK: 13, MOSI: 11, MISO: 12
* ESP32 various dev board : CS: 5, DC: 27, RST: 33, BL: 22, SCK: 18, MOSI: 23, MISO: nil
* ESP32-C2/3 various dev board: CS: 7, DC: 2, RST: 1, BL: 3, SCK: 4, MOSI: 6, MISO: nil
* ESP32-C5 various dev board : CS: 23, DC: 24, RST: 25, BL: 26, SCK: 10, MOSI: 8, MISO: nil
* ESP32-C6 various dev board : CS: 18, DC: 22, RST: 23, BL: 15, SCK: 21, MOSI: 19, MISO: nil
* ESP32-H2 various dev board : CS: 0, DC: 12, RST: 8, BL: 22, SCK: 10, MOSI: 25, MISO: nil
* ESP32-P4 various dev board : CS: 26, DC: 27, RST: 25, BL: 24, SCK: 36, MOSI: 32, MISO: nil
* ESP32-S2 various dev board : CS: 34, DC: 38, RST: 33, BL: 21, SCK: 36, MOSI: 35, MISO: nil
* ESP32-S3 various dev board : CS: 40, DC: 41, RST: 42, BL: 48, SCK: 36, MOSI: 35, MISO: nil
* ESP8266 various dev board : CS: 15, DC: 4, RST: 2, BL: 5, SCK: 14, MOSI: 13, MISO: 12
* Raspberry Pi Pico dev board : CS: 17, DC: 27, RST: 26, BL: 28, SCK: 18, MOSI: 19, MISO: 16
* RTL8720 BW16 old patch core : CS: 18, DC: 17, RST: 2, BL: 23, SCK: 19, MOSI: 21, MISO: 20
* RTL8720_BW16 Official core : CS: 9, DC: 8, RST: 6, BL: 3, SCK: 10, MOSI: 12, MISO: 11
* RTL8722 dev board : CS: 18, DC: 17, RST: 22, BL: 23, SCK: 13, MOSI: 11, MISO: 12
* RTL8722_mini dev board : CS: 12, DC: 14, RST: 15, BL: 13, SCK: 11, MOSI: 9, MISO: 10
* Seeeduino XIAO dev board : CS: 3, DC: 2, RST: 1, BL: 0, SCK: 8, MOSI: 10, MISO: 9
* Teensy 4.1 dev board : CS: 39, DC: 41, RST: 40, BL: 22, SCK: 13, MOSI: 11, MISO: 12
******************************************************************************/
#include <Arduino_GFX_Library.h>
#define GFX_BL DF_GFX_BL // default backlight pin, you may replace DF_GFX_BL to actual backlight pin
/* More dev device declaration: https://github.com/moononournation/Arduino_GFX/wiki/Dev-Device-Declaration */
#if defined(DISPLAY_DEV_KIT)
Arduino_GFX *gfx = create_default_Arduino_GFX();
#else /* !defined(DISPLAY_DEV_KIT) */
/* More data bus class: https://github.com/moononournation/Arduino_GFX/wiki/Data-Bus-Class */
Arduino_DataBus *bus = create_default_Arduino_DataBus();
/* More display class: https://github.com/moononournation/Arduino_GFX/wiki/Display-Class */
Arduino_GFX *gfx = new Arduino_ILI9341(bus, DF_GFX_RST, 3 /* rotation */, false /* IPS */);
#endif /* !defined(DISPLAY_DEV_KIT) */
/*******************************************************************************
* End of Arduino_GFX setting
******************************************************************************/
#if defined(ESP32)
#include <WiFi.h>
#elif defined(ESP8266)
#include <ESP8266WiFi.h>
#elif defined(ARDUINO_RASPBERRY_PI_PICO_W)
#include <WiFi.h>
#elif defined(RTL8722DM)
#include <WiFi.h>
#endif
#include "VNC_GFX.h"
#include <VNC.h>
VNC_GFX *vnc_gfx = new VNC_GFX(gfx);
arduinoVNC vnc = arduinoVNC(vnc_gfx);
void TFTnoWifi(void)
{
gfx->fillScreen(RGB565_BLACK);
gfx->setCursor(0, ((gfx->height() / 2) - (5 * 8)));
gfx->setTextColor(RGB565_RED);
gfx->setTextSize(5);
gfx->println("NO WIFI!");
gfx->setTextSize(2);
gfx->println();
}
void TFTnoVNC(void)
{
gfx->fillScreen(RGB565_BLACK);
gfx->setCursor(0, ((gfx->height() / 2) - (4 * 8)));
gfx->setTextColor(RGB565_LIME);
gfx->setTextSize(4);
gfx->println("connect VNC");
gfx->setTextSize(2);
gfx->println();
gfx->print(VNC_IP);
gfx->print(":");
gfx->println(VNC_PORT);
}
void handle_touch()
{
if (touch_has_signal())
{
if (touch_touched())
{
vnc.mouseEvent(touch_last_x, touch_last_y, 0b001);
}
else if (touch_released())
{
vnc.mouseEvent(touch_last_x, touch_last_y, 0b000);
}
}
}
void handle_keyboard()
{
int key = keyboard_get_key();
if (key > 0)
{
// Serial.println(key);
switch (key)
{
case 8:
key = 0xff08; // BackSpace
break;
case 9:
key = 0xff09; // Tab
break;
case 13:
key = 0xff0d; // Return or Enter
break;
case 27:
key = 0xff1b; // Escape
break;
case 180:
key = 0xff51; // Left
break;
case 181:
key = 0xff52; // Up
break;
case 182:
key = 0xff54; // Down
break;
case 183:
key = 0xff53; // Right
break;
}
vnc.keyEvent(key, 0b001);
vnc.keyEvent(key, 0b000);
}
}
void setup(void)
{
#ifdef DEV_DEVICE_INIT
DEV_DEVICE_INIT();
#endif
Serial.begin(115200);
// Serial.setDebugOutput(true);
// while(!Serial);
Serial.println("Arduino_GFX VNC example");
// Init keyboard device
keyboard_init();
Serial.println("Init display");
if (!gfx->begin())
{
Serial.println("gfx->begin() failed!");
}
gfx->fillScreen(RGB565_BLACK);
#ifdef GFX_BL
pinMode(GFX_BL, OUTPUT);
digitalWrite(GFX_BL, HIGH);
#endif
// Init touch device
touch_init(gfx->width(), gfx->height(), gfx->getRotation());
TFTnoWifi();
Serial.println("Init WiFi");
gfx->println("Init WiFi");
#if defined(ESP32)
WiFi.mode(WIFI_STA);
WiFi.begin(SSID_NAME, SSID_PASSWORD);
#elif defined(ESP8266)
// disable sleep mode for better data rate
WiFi.setSleepMode(WIFI_NONE_SLEEP);
WiFi.mode(WIFI_STA);
WiFi.begin(SSID_NAME, SSID_PASSWORD);
#elif defined(ARDUINO_RASPBERRY_PI_PICO_W)
WiFi.mode(WIFI_STA);
WiFi.begin(SSID_NAME, SSID_PASSWORD);
#elif defined(RTL8722DM)
WiFi.begin((char *)SSID_NAME, (char *)SSID_PASSWORD);
#endif
while (WiFi.status() != WL_CONNECTED)
{
delay(500);
Serial.print(".");
gfx->print(".");
}
Serial.println(" CONNECTED");
gfx->println(" CONNECTED");
Serial.println("IP address: ");
gfx->println("IP address: ");
Serial.println(WiFi.localIP());
gfx->println(WiFi.localIP());
TFTnoVNC();
Serial.println(F("[SETUP] VNC..."));
#ifdef SEPARATE_DRAW_TASK
draw_task_setup();
#endif
vnc.begin(VNC_IP, VNC_PORT);
vnc.setPassword(VNC_PASSWORD); // optional
}
void loop()
{
if (WiFi.status() != WL_CONNECTED)
{
vnc.reconnect();
TFTnoWifi();
delay(100);
}
else
{
if (vnc.connected())
{
handle_touch();
handle_keyboard();
}
vnc.loop();
if (!vnc.connected())
{
TFTnoVNC();
// some delay to not flood the server
delay(5000);
}
}
}

View File

@@ -0,0 +1,185 @@
#ifndef _VNC_GFX_H_
#define _VNC_GFX_H_
#include "Arduino_GFX_Library.h"
#include "VNC.h"
#include "VNC_config.h"
#ifdef ESP32
// #define SEPARATE_DRAW_TASK
#endif
#ifdef SEPARATE_DRAW_TASK
#define NUMBER_OF_DRAW_BUFFER 64
typedef struct
{
xQueueHandle xqh;
Arduino_GFX *gfx;
} ParamDrawTask;
typedef struct
{
int16_t x;
int16_t y;
int16_t w;
int16_t h;
bool isBitmap;
uint16_t *buf;
} DrawData;
static xQueueHandle _xqh;
static ParamDrawTask _pDrawTask;
static TaskHandle_t _draw_task_handle;
static DrawData drawDatas[NUMBER_OF_DRAW_BUFFER];
static int draw_queue_cnt = 0;
static void queueDrawTask(uint32_t x, uint32_t y, uint32_t w, uint32_t h, bool isBitmap, uint16_t *d)
{
log_i("queueDrawTask start.");
DrawData *dd = &drawDatas[draw_queue_cnt % NUMBER_OF_DRAW_BUFFER];
dd->x = x;
dd->y = y;
dd->w = w;
dd->h = h;
dd->isBitmap = isBitmap;
log_i("copy data start.");
uint16_t *p = &dd->buf[0];
if (isBitmap)
{
log_i("copy bitmap.");
int i = w * h;
while (i--)
{
*p++ = *d++;
}
}
else
{
*p = *d;
}
log_i("copy data end.");
++draw_queue_cnt;
log_i("xQueueSend start.");
xQueueSend(_xqh, &dd, portMAX_DELAY);
log_i("xQueueSend end.");
log_i("queueDrawTask end.");
}
static void draw_task(void *arg)
{
DrawData *dd;
log_i("draw_task start.");
while (xQueueReceive(_xqh, &dd, portMAX_DELAY))
{
log_i("draw_task work start: x: %d, y: %d, w: %d, h: %d.", dd->x, dd->y, dd->w, dd->h);
if (dd->isBitmap)
{
gfx->draw16bitBeRGBBitmap(dd->x, dd->y, &dd->buf[0], dd->w, dd->h);
}
else
{
gfx->fillRect(dd->x, dd->y, dd->w, dd->h, dd->buf[0]);
}
log_i("draw_task work end.");
}
vQueueDelete(_xqh);
log_i("draw_task end.");
vTaskDelete(NULL);
}
void draw_task_setup()
{
_xqh = xQueueCreate(NUMBER_OF_DRAW_BUFFER, sizeof(DrawData));
_pDrawTask.xqh = _xqh;
_pDrawTask.gfx = gfx;
log_i("xTaskCreatePinnedToCore start");
xTaskCreatePinnedToCore(
(TaskFunction_t)draw_task,
(const char *const)"Draw Task",
(const uint32_t)1600,
(void *const)&_pDrawTask,
(UBaseType_t)configMAX_PRIORITIES - 1,
(TaskHandle_t *const)&_draw_task_handle,
(const BaseType_t)0);
log_i("xTaskCreatePinnedToCore end");
for (int i = 0; i < NUMBER_OF_DRAW_BUFFER; i++)
{
if (!drawDatas[i].buf)
{
drawDatas[i].buf = (uint16_t *)malloc(FB_SIZE * 2);
}
if (drawDatas[i].buf)
{
log_i("#%d draw buffer allocated.", i);
}
else
{
log_e("#%d draw buffer allocat failed.", i);
}
}
}
#endif
class VNC_GFX : public VNCdisplay
{
public:
VNC_GFX(Arduino_GFX *gfx)
{
_gfx = gfx;
}
bool hasCopyRect(void)
{
return false;
}
uint32_t getHeight(void)
{
return _gfx->height();
}
uint32_t getWidth(void)
{
return _gfx->width();
}
void draw_area(uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint8_t *data)
{
// DEBUG_VNC("draw_area(%d, %d, %d, %d, data)\n", x, y, w, h);
#ifdef SEPARATE_DRAW_TASK
queueDrawTask(x, y, w, h, true, (uint16_t *)data);
#else
// _gfx->draw16bitBeRGBBitmap(x, y, (uint16_t *)data, w, h);
_gfx->draw16bitRGBBitmap(x, y, (uint16_t *)data, w, h);
#endif
}
void draw_rect(uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint16_t color)
{
// DEBUG_VNC("draw_rect(%d, %d, %d, %d, color)\n", x, y, w, h);
// MSB_16_SET(color, color);
#ifdef SEPARATE_DRAW_TASK
queueDrawTask(x, y, w, h, false, &color);
#else
_gfx->fillRect(x, y, w, h, color);
#endif
}
void vnc_options_override(dfb_vnc_options *opt)
{
// opt->client.bigendian = 1;
}
private:
Arduino_GFX *_gfx;
};
#endif /* _VNC_GFX_H_ */

View File

@@ -0,0 +1,76 @@
/*******************************************************************************
* Keyboard libraries:
* M5Stack CardKB: no extra libraries required
https://github.com/solderparty/arduino_bbq10kbd
******************************************************************************/
/* uncomment for M5Stack CardKB */
// #define KEYBOARD_CARDKB
// #define KEYBOARD_CARDKB_SDA 19
// #define KEYBOARD_CARDKB_SCL 20
// #define KEYBOARD_CARDKB_I2C_ADDR 0x5f
/* uncomment for BBQKeyboard */
// #define KEYBOARD_BBQKB
// #define KEYBOARD_BBQKB_SDA 21
// #define KEYBOARD_BBQKB_SCL 22
#if defined(KEYBOARD_CARDKB)
#include <Wire.h>
#elif defined(KEYBOARD_BBQKB)
#include <Wire.h>
#include <BBQ10Keyboard.h>
BBQ10Keyboard keyboard;
#endif
void keyboard_init()
{
#if defined(KEYBOARD_CARDKB)
Wire1.begin(KEYBOARD_CARDKB_SDA, KEYBOARD_CARDKB_SCL);
#elif defined(KEYBOARD_BBQKB)
Wire1.begin(KEYBOARD_BBQKB_SDA, KEYBOARD_BBQKB_SCL);
keyboard.begin();
keyboard.setBacklight(0.5f);
#endif
}
char keyboard_get_key()
{
#if defined(KEYBOARD_CARDKB)
uint8_t bytesReceived = Wire1.requestFrom(KEYBOARD_CARDKB_I2C_ADDR, 1);
if ((bool)bytesReceived)
{ // If received more than zero bytes
return Wire1.read();
}
else
{
return 0;
}
#elif defined(KEYBOARD_BBQKB)
const int keyCount = keyboard.keyCount();
if (keyCount > 0)
{
const BBQ10Keyboard::KeyEvent key = keyboard.keyEvent();
String state = "pressed";
if (key.state == BBQ10Keyboard::StateLongPress)
state = "held down";
else if (key.state == BBQ10Keyboard::StateRelease)
state = "released";
Serial.printf("key: '%c' (dec %d, hex %02x) %s\r\n", key.key, key.key, key.key, state.c_str());
if ((key.key != 0) && (key.state != BBQ10Keyboard::StateRelease))
{
return key.key;
}
else
{
return 0;
}
}
else
{
return 0;
}
#endif
}

View File

@@ -0,0 +1,205 @@
/*******************************************************************************
* Touch libraries:
* XPT2046: https://github.com/PaulStoffregen/XPT2046_Touchscreen.git
*
* Capacitive touchscreen libraries
* TouchLib: https://github.com/mmMicky/TouchLib.git
*
* #define CTS328_SLAVE_ADDRESS (0x1A)
* #define L58_SLAVE_ADDRESS (0X5A)
* #define CTS826_SLAVE_ADDRESS (0X15)
* #define CTS820_SLAVE_ADDRESS (0X15)
* #define CTS816S_SLAVE_ADDRESS (0X15)
* #define FT3267_SLAVE_ADDRESS (0x38)
* #define FT5x06_ADDR (0x38)
* #define GT911_SLAVE_ADDRESS1 (0X5D)
* #define GT911_SLAVE_ADDRESS2 (0X14)
* #define ZTW622_SLAVE1_ADDRESS (0x20)
* #define ZTW622_SLAVE2_ADDRESS (0x46)
*
******************************************************************************/
/* uncomment for XPT2046 */
// #define TOUCH_XPT2046
// #define TOUCH_XPT2046_SCK 12
// #define TOUCH_XPT2046_MISO 13
// #define TOUCH_XPT2046_MOSI 11
// #define TOUCH_XPT2046_CS 10
// #define TOUCH_XPT2046_INT 18
// #define TOUCH_XPT2046_ROTATION 0
// #define TOUCH_XPT2046_SAMPLES 50
// uncomment for most capacitive touchscreen
// #define TOUCH_MODULES_FT5x06 // GT911 / CST_SELF / CST_MUTUAL / ZTW622 / L58 / FT3267 / FT5x06
// #define TOUCH_MODULE_ADDR FT5x06_ADDR // CTS328_SLAVE_ADDRESS / L58_SLAVE_ADDRESS / CTS826_SLAVE_ADDRESS / CTS820_SLAVE_ADDRESS / CTS816S_SLAVE_ADDRESS / FT3267_SLAVE_ADDRESS / FT5x06_ADDR / GT911_SLAVE_ADDRESS1 / GT911_SLAVE_ADDRESS2 / ZTW622_SLAVE1_ADDRESS / ZTW622_SLAVE2_ADDRESS
// #define TOUCH_SCL 5
// #define TOUCH_SDA 6
// #define TOUCH_RES -1
// #define TOUCH_INT -1
// Please fill below values from Arduino_GFX Example - TouchCalibration
bool touch_swap_xy = false;
int16_t touch_map_x1 = -1;
int16_t touch_map_x2 = -1;
int16_t touch_map_y1 = -1;
int16_t touch_map_y2 = -1;
int16_t touch_max_x = 0, touch_max_y = 0;
int16_t touch_raw_x = 0, touch_raw_y = 0;
int16_t touch_last_x = 0, touch_last_y = 0;
#if defined(TOUCH_XPT2046)
#include <XPT2046_Touchscreen.h>
#include <SPI.h>
XPT2046_Touchscreen ts(TOUCH_XPT2046_CS, TOUCH_XPT2046_INT);
#elif defined(TOUCH_MODULE_ADDR) // TouchLib
#include <Wire.h>
#include <TouchLib.h>
TouchLib touch(Wire, TOUCH_SDA, TOUCH_SCL, TOUCH_MODULE_ADDR);
#endif // TouchLib
void touch_init(int16_t w, int16_t h, uint8_t r)
{
touch_max_x = w - 1;
touch_max_y = h - 1;
if (touch_map_x1 == -1)
{
switch (r)
{
case 3:
touch_swap_xy = true;
touch_map_x1 = touch_max_x;
touch_map_x2 = 0;
touch_map_y1 = 0;
touch_map_y2 = touch_max_y;
break;
case 2:
touch_swap_xy = false;
touch_map_x1 = touch_max_x;
touch_map_x2 = 0;
touch_map_y1 = touch_max_y;
touch_map_y2 = 0;
break;
case 1:
touch_swap_xy = true;
touch_map_x1 = 0;
touch_map_x2 = touch_max_x;
touch_map_y1 = touch_max_y;
touch_map_y2 = 0;
break;
default: // case 0:
touch_swap_xy = false;
touch_map_x1 = 0;
touch_map_x2 = touch_max_x;
touch_map_y1 = 0;
touch_map_y2 = touch_max_y;
break;
}
}
#if defined(TOUCH_XPT2046)
SPI.begin(TOUCH_XPT2046_SCK, TOUCH_XPT2046_MISO, TOUCH_XPT2046_MOSI, TOUCH_XPT2046_CS);
ts.begin();
ts.setRotation(TOUCH_XPT2046_ROTATION);
#elif defined(TOUCH_MODULE_ADDR) // TouchLib
// Reset touchscreen
#if (TOUCH_RES > 0)
pinMode(TOUCH_RES, OUTPUT);
digitalWrite(TOUCH_RES, 0);
delay(200);
digitalWrite(TOUCH_RES, 1);
delay(200);
#endif
Wire.begin(TOUCH_SDA, TOUCH_SCL);
touch.init();
#endif // TouchLib
}
bool touch_has_signal()
{
#if defined(TOUCH_XPT2046)
return ts.tirqTouched();
#elif defined(TOUCH_MODULE_ADDR) // TouchLib
// TODO: implement TOUCH_INT
return true;
#endif // TouchLib
return false;
}
void translate_touch_raw()
{
if (touch_swap_xy)
{
touch_last_x = map(touch_raw_y, touch_map_x1, touch_map_x2, 0, touch_max_x);
touch_last_y = map(touch_raw_x, touch_map_y1, touch_map_y2, 0, touch_max_y);
}
else
{
touch_last_x = map(touch_raw_x, touch_map_x1, touch_map_x2, 0, touch_max_x);
touch_last_y = map(touch_raw_y, touch_map_y1, touch_map_y2, 0, touch_max_y);
}
// Serial.printf("touch_raw_x: %d, touch_raw_y: %d, touch_last_x: %d, touch_last_y: %d\n", touch_raw_x, touch_raw_y, touch_last_x, touch_last_y);
}
bool touch_touched()
{
#if defined(TOUCH_XPT2046)
if (ts.touched())
{
TS_Point p = ts.getPoint();
touch_raw_x = p.x;
touch_raw_y = p.y;
int max_z = p.z;
int count = 0;
while ((ts.touched()) && (count < TOUCH_XPT2046_SAMPLES))
{
count++;
TS_Point p = ts.getPoint();
if (p.z > max_z)
{
touch_raw_x = p.x;
touch_raw_y = p.y;
max_z = p.z;
}
// Serial.printf("touch_raw_x: %d, touch_raw_y: %d, p.z: %d\n", touch_raw_x, touch_raw_y, p.z);
}
translate_touch_raw();
return true;
}
#elif defined(TOUCH_MODULE_ADDR) // TouchLib
if (touch.read())
{
TP_Point t = touch.getPoint(0);
touch_raw_x = t.x;
touch_raw_y = t.y;
touch_last_x = touch_raw_x;
touch_last_y = touch_raw_y;
translate_touch_raw();
return true;
}
#endif // TouchLib
return false;
}
bool touch_released()
{
#if defined(TOUCH_XPT2046)
return true;
#elif defined(TOUCH_MODULE_ADDR) // TouchLib
return false;
#endif // TouchLib
return false;
}