Ajout PacoMouse
86
PacoMouseCYD/README.md
Normal file
@@ -0,0 +1,86 @@
|
||||
# PacoMouseCYD
|
||||
|
||||
|
||||
Firmware for a WiFi throttle to control locomotives and accessories using a [Cheap Yellow Display](https://github.com/witnessmenow/ESP32-Cheap-Yellow-Display/) 2432S028R.
|
||||
|
||||

|
||||
|
||||
* Protocols: Z21, Xpressnet LAN, Loconet over TCP/IP (LBserver & Binary) and ECoS
|
||||
* Control of Locomotives
|
||||
* Rotary encoder for loco speed and direction
|
||||
* Function icons
|
||||
* Color image of the locomotive from the SD.
|
||||
* Extra: Locomotive editor in the SD from the web browser
|
||||
* Loconet: Command station detection for the correct control of functions F9 to F28.
|
||||
* Shunting mode for precise stopping.
|
||||
* Steam locomotive driving simulator
|
||||
* Control of accesories with 2, 3 or 4 aspects.
|
||||
* Multiple panels of accessories.
|
||||
* CV and LNCV programming
|
||||
* Identify the name of the most common manufacturers when reading the CV8.
|
||||
* Locking of some features for guest or club use.
|
||||
* Manually measurement of train speed
|
||||
* Station Run: Game for children
|
||||
* WiFi Analyzer
|
||||
* Menus in different languages:
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
|
||||
|
||||
|
||||
## Videos
|
||||
|
||||
[](https://www.youtube.com/watch?v=YSfBQpVUhg8)
|
||||
|
||||
[](https://www.youtube.com/watch?v=auRIvvbzx6Q)
|
||||
|
||||
|
||||
---
|
||||
|
||||
## Documentation
|
||||
- https://usuaris.tinet.cat/fmco/
|
||||
- https://fmcopaco.github.io/
|
||||
- Read the [manual](doc/PacoMouseCYD_manual_v0.9.pdf) in the doc directory
|
||||
- Step-by-step assembly of PacoMouseCYD by [Isaac](https://www.iguadix.es/content/pacomouse-cyd)
|
||||
|
||||
---
|
||||
|
||||
## Schematics
|
||||
|
||||

|
||||
|
||||
The CYD (Cheap Yellow Display) has the following features:
|
||||
|
||||
* ESP32 (With Wifi and Bluetooth)
|
||||
* 320 x 240 TFT Display (2.8" ILI9341)
|
||||
* Touch Screen (Resistive XPT2046)
|
||||
* USB for powering and programming
|
||||
* SD Card Slot (max. 32Gb FAT32), LED and some additional pins broken out in JST 1.25 connectors.
|
||||
|
||||
|
||||
Just add a rotary encoder type EC-11 or KY-040 with a pushbutton, a battery and its charger to have your **PacoMouseCYD** wireless throttle.
|
||||
|
||||
---
|
||||
|
||||
## Copyright
|
||||
Copyright (c) 2025-2026 Paco Cañada, [The Pows](https://usuaris.tinet.cat/fmco/)
|
||||
All rights reserved.
|
||||
|
||||
---
|
||||
|
||||
## License
|
||||
Proprietary.
|
||||
Sources are only provided to compile and upload to the device.
|
||||
Modifiyng source code or forking/publishing this project ist not allowed.
|
||||
Commercial use is forbidden.
|
||||
|
||||
---
|
||||
|
||||
## Used Libraries
|
||||
* TFT_eSPI (FreeBSD)
|
||||
|
||||
|
||||
|
||||
646
PacoMouseCYD/SD/LocoEditor.html
Normal file
18
PacoMouseCYD/SD/acc/panel.csv
Normal file
@@ -0,0 +1,18 @@
|
||||
Nombre
|
||||
Panel 0
|
||||
Panel 1
|
||||
Panel 2
|
||||
Panel 3
|
||||
Panel 4
|
||||
Panel 5
|
||||
Panel 6
|
||||
Panel 7
|
||||
Panel 8
|
||||
Panel 9
|
||||
Panel 10
|
||||
Panel 11
|
||||
Panel 12
|
||||
Panel 13
|
||||
Panel 14
|
||||
Panel 15
|
||||
|
||||
|
BIN
PacoMouseCYD/SD/image/0.bmp
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
PacoMouseCYD/SD/image/1.bmp
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
PacoMouseCYD/SD/image/1000.bmp
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
PacoMouseCYD/SD/image/1001.bmp
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
PacoMouseCYD/SD/image/1002.bmp
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
PacoMouseCYD/SD/image/1003.bmp
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
PacoMouseCYD/SD/image/1004.bmp
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
PacoMouseCYD/SD/image/1005.bmp
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
PacoMouseCYD/SD/image/1006.bmp
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
PacoMouseCYD/SD/image/1007.bmp
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
PacoMouseCYD/SD/image/1008.bmp
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
PacoMouseCYD/SD/image/1009.bmp
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
PacoMouseCYD/SD/image/1010.bmp
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
PacoMouseCYD/SD/image/1011.bmp
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
PacoMouseCYD/SD/image/1012.bmp
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
PacoMouseCYD/SD/image/1013.bmp
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
PacoMouseCYD/SD/image/1014.bmp
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
PacoMouseCYD/SD/image/1015.bmp
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
PacoMouseCYD/SD/image/1016.bmp
Normal file
|
After Width: | Height: | Size: 23 KiB |
BIN
PacoMouseCYD/SD/image/1017.bmp
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
PacoMouseCYD/SD/image/2.bmp
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
PacoMouseCYD/SD/image/3.bmp
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
PacoMouseCYD/SD/image/4.bmp
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
PacoMouseCYD/SD/image/5.bmp
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
PacoMouseCYD/SD/image/6.bmp
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
PacoMouseCYD/SD/image/7.bmp
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
PacoMouseCYD/SD/image/8.bmp
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
PacoMouseCYD/SD/image/9.bmp
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
PacoMouseCYD/SD/image/logo.bmp
Normal file
|
After Width: | Height: | Size: 98 KiB |
2
PacoMouseCYD/SD/loco/15.csv
Normal file
@@ -0,0 +1,2 @@
|
||||
Name;Image;Vmax;F0;F1;F2;F3;F4;F5;F6;F7;F8;F9;F10;F11;F12;F13;F14;F15;F16;F17;F18;F19;F20;F21;F22;F23;F24;F25;F26;F27;F28
|
||||
Ce 6/8 III;1012;75;3;6;16;2;2;2;2;2;2;2;2;2;2;2;2;2;2;2;2;2;2;2;2;2;2;2;2;2;2
|
||||
|
2
PacoMouseCYD/SD/loco/2000.csv
Normal file
@@ -0,0 +1,2 @@
|
||||
Name;Image;Vmax;F0;F1;F2;F3;F4;F5;F6;F7;F8;F9;F10;F11;F12;F13;F14;F15;F16;F17;F18;F19;F20;F21;F22;F23;F24;F25;F26;F27;F28
|
||||
Talgo;1006;160;3;6;17;9;10;14;2;2;2;2;2;2;2;2;2;2;2;2;2;2;2;2;2;2;2;2;2;2;2
|
||||
|
2
PacoMouseCYD/SD/loco/242.csv
Normal file
@@ -0,0 +1,2 @@
|
||||
Name;Image;Vmax;F0;F1;F2;F3;F4;F5;F6;F7;F8;F9;F10;F11;F12;F13;F14;F15;F16;F17;F18;F19;F20;F21;F22;F23;F24;F25;F26;F27;F28
|
||||
242F-2209;1008;100;3;6;17;9;10;15;7;8;20;2;2;2;2;2;2;2;2;2;2;2;2;2;2;2;2;2;2;2;2
|
||||
|
2
PacoMouseCYD/SD/loco/252.csv
Normal file
@@ -0,0 +1,2 @@
|
||||
Name;Image;Vmax;F0;F1;F2;F3;F4;F5;F6;F7;F8;F9;F10;F11;F12;F13;F14;F15;F16;F17;F18;F19;F20;F21;F22;F23;F24;F25;F26;F27;F28
|
||||
252 Altaria;1009;140;3;6;17;9;10;15;7;8;20;2;2;2;2;2;2;2;2;2;2;2;2;2;2;2;2;2;2;2;2
|
||||
|
2
PacoMouseCYD/SD/loco/3.csv
Normal file
@@ -0,0 +1,2 @@
|
||||
Name;Image;Vmax;F0;F1;F2;F3;F4;F5;F6;F7;F8;F9;F10;F11;F12;F13;F14;F15;F16;F17;F18;F19;F20;F21;F22;F23;F24;F25;F26;F27;F28
|
||||
Platanito;1004;120;3;2;2;2;2;2;2;2;2;2;2;2;2;2;2;2;2;2;2;2;2;2;2;2;2;2;2;2;2
|
||||
|
2
PacoMouseCYD/SD/loco/319.csv
Normal file
@@ -0,0 +1,2 @@
|
||||
Name;Image;Vmax;F0;F1;F2;F3;F4;F5;F6;F7;F8;F9;F10;F11;F12;F13;F14;F15;F16;F17;F18;F19;F20;F21;F22;F23;F24;F25;F26;F27;F28
|
||||
319-309 Taxi;1003;120;3;6;17;10;9;4;5;8;14;15;20;12;15;16;18;19;2;13;11;2;2;2;2;2;2;2;2;2;2
|
||||
|
2
PacoMouseCYD/SD/loco/321.csv
Normal file
@@ -0,0 +1,2 @@
|
||||
Name;Image;Vmax;F0;F1;F2;F3;F4;F5;F6;F7;F8;F9;F10;F11;F12;F13;F14;F15;F16;F17;F18;F19;F20;F21;F22;F23;F24;F25;F26;F27;F28
|
||||
321 025-9 Taxi;1017;120;3;6;16;17;14;5;33;32;30;6;16;36;26;26;23;28;29;6;6;9;19;2;2;2;2;2;2;2;2
|
||||
|
2
PacoMouseCYD/SD/loco/4.csv
Normal file
@@ -0,0 +1,2 @@
|
||||
Name;Image;Vmax;F0;F1;F2;F3;F4;F5;F6;F7;F8;F9;F10;F11;F12;F13;F14;F15;F16;F17;F18;F19;F20;F21;F22;F23;F24;F25;F26;F27;F28
|
||||
Vapor 003;1001;80;3;2;2;2;2;2;2;2;2;2;2;2;2;2;2;2;2;2;2;2;2;2;2;2;2;2;2;2;2
|
||||
|
2
PacoMouseCYD/SD/loco/5.csv
Normal file
@@ -0,0 +1,2 @@
|
||||
Name;Image;Vmax;F0;F1;F2;F3;F4;F5;F6;F7;F8;F9;F10;F11;F12;F13;F14;F15;F16;F17;F18;F19;F20;F21;F22;F23;F24;F25;F26;F27;F28
|
||||
269 Cercanias;1000;140;3;2;4;5;6;7;8;9;10;11;12;13;14;15;16;17;18;19;20;2;2;2;2;2;2;2;2;2;2
|
||||
|
2
PacoMouseCYD/SD/loco/6.csv
Normal file
@@ -0,0 +1,2 @@
|
||||
Name;Image;Vmax;F0;F1;F2;F3;F4;F5;F6;F7;F8;F9;F10;F11;F12;F13;F14;F15;F16;F17;F18;F19;F20;F21;F22;F23;F24;F25;F26;F27;F28
|
||||
Camello Cercan.;1005;140;3;4;2;2;2;2;2;2;2;2;2;2;2;2;2;2;2;2;2;2;2;2;2;2;2;2;2;2;2
|
||||
|
2
PacoMouseCYD/SD/loco/79.csv
Normal file
@@ -0,0 +1,2 @@
|
||||
Name;Image;Vmax;F0;F1;F2;F3;F4;F5;F6;F7;F8;F9;F10;F11;F12;F13;F14;F15;F16;F17;F18;F19;F20;F21;F22;F23;F24;F25;F26;F27;F28
|
||||
Mikado;1002;80;3;2;4;6;8;10;2;2;2;2;2;2;2;2;2;2;2;2;2;2;2;2;2;2;2;2;2;2;2
|
||||
|
2
PacoMouseCYD/SD/loco/99.csv
Normal file
@@ -0,0 +1,2 @@
|
||||
Name;Image;Vmax;F0;F1;F2;F3;F4;F5;F6;F7;F8;F9;F10;F11;F12;F13;F14;F15;F16;F17;F18;F19;F20;F21;F22;F23;F24;F25;F26;F27;F28
|
||||
Villacanas;1007;85;3;4;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1
|
||||
|
BIN
PacoMouseCYD/doc/PacoMouseCYD_manual_v0.9.pdf
Normal file
44
PacoMouseCYD/doc/User_Setup.h
Normal file
@@ -0,0 +1,44 @@
|
||||
// USER DEFINED SETTINGS
|
||||
|
||||
#define USER_SETUP_INFO "User_Setup CYD 2.8"
|
||||
|
||||
#define ILI9341_2_DRIVER // Alternative ILI9341 driver, see https://github.com/Bodmer/TFT_eSPI/issues/1172
|
||||
|
||||
#define TFT_WIDTH 240 // ST7789 240 x 240 and 240 x 320
|
||||
|
||||
#define TFT_HEIGHT 320 // ST7789 240 x 320
|
||||
|
||||
#define TFT_INVERSION_ON
|
||||
|
||||
#define TFT_BL 21 // LED back-light control pin
|
||||
#define TFT_BACKLIGHT_ON HIGH // Level to turn ON back-light (HIGH or LOW)
|
||||
|
||||
#define TFT_MISO 12
|
||||
#define TFT_MOSI 13
|
||||
#define TFT_SCLK 14
|
||||
#define TFT_CS 15 // Chip select control pin
|
||||
#define TFT_DC 2 // Data Command control pin
|
||||
#define TFT_RST -1 // Set TFT_RST to -1 if display RESET is connected to ESP32 board RST
|
||||
|
||||
#define TOUCH_CS 33 // Chip select pin (T_CS) of touch screen
|
||||
|
||||
#define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH
|
||||
#define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters
|
||||
#define LOAD_FONT4 // Font 4. Medium 26 pixel high font, needs ~5848 bytes in FLASH, 96 characters
|
||||
#define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm
|
||||
#define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:-.
|
||||
#define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-.
|
||||
#define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts
|
||||
|
||||
#define SMOOTH_FONT
|
||||
|
||||
|
||||
#define SPI_FREQUENCY 55000000 // STM32 SPI1 only (SPI2 maximum is 27MHz)
|
||||
|
||||
#define SPI_READ_FREQUENCY 20000000
|
||||
|
||||
#define SPI_TOUCH_FREQUENCY 2500000
|
||||
|
||||
#define USE_HSPI_PORT
|
||||
|
||||
|
||||
BIN
PacoMouseCYD/doc/options/TFT_eSPI_CYD2.4/ESP32-2432S024.jpg
Normal file
|
After Width: | Height: | Size: 168 KiB |
383
PacoMouseCYD/doc/options/TFT_eSPI_CYD2.4/User_Setup.h
Normal file
@@ -0,0 +1,383 @@
|
||||
// USER DEFINED SETTINGS
|
||||
// Set driver type, fonts to be loaded, pins used and SPI control method etc
|
||||
//
|
||||
// See the User_Setup_Select.h file if you wish to be able to define multiple
|
||||
// setups and then easily select which setup file is used by the compiler.
|
||||
//
|
||||
// If this file is edited correctly then all the library example sketches should
|
||||
// run without the need to make any more changes for a particular hardware setup!
|
||||
// Note that some sketches are designed for a particular TFT pixel width/height
|
||||
|
||||
// User defined information reported by "Read_User_Setup" test & diagnostics example
|
||||
#define USER_SETUP_INFO "User_Setup CYD 2.4"
|
||||
|
||||
// Define to disable all #warnings in library (can be put in User_Setup_Select.h)
|
||||
//#define DISABLE_ALL_LIBRARY_WARNINGS
|
||||
|
||||
// ##################################################################################
|
||||
//
|
||||
// Section 1. Call up the right driver file and any options for it
|
||||
//
|
||||
// ##################################################################################
|
||||
|
||||
// Define STM32 to invoke optimised processor support (only for STM32)
|
||||
//#define STM32
|
||||
|
||||
// Defining the STM32 board allows the library to optimise the performance
|
||||
// for UNO compatible "MCUfriend" style shields
|
||||
//#define NUCLEO_64_TFT
|
||||
//#define NUCLEO_144_TFT
|
||||
|
||||
// STM32 8 bit parallel only:
|
||||
// If STN32 Port A or B pins 0-7 are used for 8 bit parallel data bus bits 0-7
|
||||
// then this will improve rendering performance by a factor of ~8x
|
||||
//#define STM_PORTA_DATA_BUS
|
||||
//#define STM_PORTB_DATA_BUS
|
||||
|
||||
// Tell the library to use parallel mode (otherwise SPI is assumed)
|
||||
//#define TFT_PARALLEL_8_BIT
|
||||
//#defined TFT_PARALLEL_16_BIT // **** 16 bit parallel ONLY for RP2040 processor ****
|
||||
|
||||
// Display type - only define if RPi display
|
||||
//#define RPI_DISPLAY_TYPE // 20MHz maximum SPI
|
||||
|
||||
// Only define one driver, the other ones must be commented out
|
||||
//#define ILI9341_DRIVER // Generic driver for common displays
|
||||
#define ILI9341_2_DRIVER // Alternative ILI9341 driver, see https://github.com/Bodmer/TFT_eSPI/issues/1172
|
||||
//#define ST7735_DRIVER // Define additional parameters below for this display
|
||||
//#define ILI9163_DRIVER // Define additional parameters below for this display
|
||||
//#define S6D02A1_DRIVER
|
||||
//#define RPI_ILI9486_DRIVER // 20MHz maximum SPI
|
||||
//#define HX8357D_DRIVER
|
||||
//#define ILI9481_DRIVER
|
||||
//#define ILI9486_DRIVER
|
||||
//#define ILI9488_DRIVER // WARNING: Do not connect ILI9488 display SDO to MISO if other devices share the SPI bus (TFT SDO does NOT tristate when CS is high)
|
||||
//#define ST7789_DRIVER // Full configuration option, define additional parameters below for this display
|
||||
//#define ST7789_2_DRIVER // Minimal configuration option, define additional parameters below for this display
|
||||
//#define R61581_DRIVER
|
||||
//#define RM68140_DRIVER
|
||||
//#define ST7796_DRIVER
|
||||
//#define SSD1351_DRIVER
|
||||
//#define SSD1963_480_DRIVER
|
||||
//#define SSD1963_800_DRIVER
|
||||
//#define SSD1963_800ALT_DRIVER
|
||||
//#define ILI9225_DRIVER
|
||||
//#define GC9A01_DRIVER
|
||||
|
||||
// Some displays support SPI reads via the MISO pin, other displays have a single
|
||||
// bi-directional SDA pin and the library will try to read this via the MOSI line.
|
||||
// To use the SDA line for reading data from the TFT uncomment the following line:
|
||||
|
||||
// #define TFT_SDA_READ // This option is for ESP32 ONLY, tested with ST7789 and GC9A01 display only
|
||||
|
||||
// For ST7735, ST7789 and ILI9341 ONLY, define the colour order IF the blue and red are swapped on your display
|
||||
// Try ONE option at a time to find the correct colour order for your display
|
||||
|
||||
// #define TFT_RGB_ORDER TFT_RGB // Colour order Red-Green-Blue
|
||||
// #define TFT_RGB_ORDER TFT_BGR // Colour order Blue-Green-Red
|
||||
|
||||
// For M5Stack ESP32 module with integrated ILI9341 display ONLY, remove // in line below
|
||||
|
||||
// #define M5STACK
|
||||
|
||||
// For ST7789, ST7735, ILI9163 and GC9A01 ONLY, define the pixel width and height in portrait orientation
|
||||
// #define TFT_WIDTH 80
|
||||
// #define TFT_WIDTH 128
|
||||
// #define TFT_WIDTH 172 // ST7789 172 x 320
|
||||
#define TFT_WIDTH 240 // ST7789 240 x 240 and 240 x 320
|
||||
// #define TFT_HEIGHT 160
|
||||
// #define TFT_HEIGHT 128
|
||||
// #define TFT_HEIGHT 240 // ST7789 240 x 240
|
||||
#define TFT_HEIGHT 320 // ST7789 240 x 320
|
||||
// #define TFT_HEIGHT 240 // GC9A01 240 x 240
|
||||
|
||||
// For ST7735 ONLY, define the type of display, originally this was based on the
|
||||
// colour of the tab on the screen protector film but this is not always true, so try
|
||||
// out the different options below if the screen does not display graphics correctly,
|
||||
// e.g. colours wrong, mirror images, or stray pixels at the edges.
|
||||
// Comment out ALL BUT ONE of these options for a ST7735 display driver, save this
|
||||
// this User_Setup file, then rebuild and upload the sketch to the board again:
|
||||
|
||||
// #define ST7735_INITB
|
||||
// #define ST7735_GREENTAB
|
||||
// #define ST7735_GREENTAB2
|
||||
// #define ST7735_GREENTAB3
|
||||
// #define ST7735_GREENTAB128 // For 128 x 128 display
|
||||
// #define ST7735_GREENTAB160x80 // For 160 x 80 display (BGR, inverted, 26 offset)
|
||||
// #define ST7735_ROBOTLCD // For some RobotLCD arduino shields (128x160, BGR, https://docs.arduino.cc/retired/getting-started-guides/TFT)
|
||||
// #define ST7735_REDTAB
|
||||
// #define ST7735_BLACKTAB
|
||||
// #define ST7735_REDTAB160x80 // For 160 x 80 display with 24 pixel offset
|
||||
|
||||
// If colours are inverted (white shows as black) then uncomment one of the next
|
||||
// 2 lines try both options, one of the options should correct the inversion.
|
||||
|
||||
#define TFT_INVERSION_ON
|
||||
// #define TFT_INVERSION_OFF
|
||||
|
||||
|
||||
// ##################################################################################
|
||||
//
|
||||
// Section 2. Define the pins that are used to interface with the display here
|
||||
//
|
||||
// ##################################################################################
|
||||
|
||||
// If a backlight control signal is available then define the TFT_BL pin in Section 2
|
||||
// below. The backlight will be turned ON when tft.begin() is called, but the library
|
||||
// needs to know if the LEDs are ON with the pin HIGH or LOW. If the LEDs are to be
|
||||
// driven with a PWM signal or turned OFF/ON then this must be handled by the user
|
||||
// sketch. e.g. with digitalWrite(TFT_BL, LOW);
|
||||
|
||||
#define TFT_BL 27 // LED back-light control pin
|
||||
#define TFT_BACKLIGHT_ON HIGH // Level to turn ON back-light (HIGH or LOW)
|
||||
|
||||
|
||||
|
||||
// We must use hardware SPI, a minimum of 3 GPIO pins is needed.
|
||||
// Typical setup for ESP8266 NodeMCU ESP-12 is :
|
||||
//
|
||||
// Display SDO/MISO to NodeMCU pin D6 (or leave disconnected if not reading TFT)
|
||||
// Display LED to NodeMCU pin VIN (or 5V, see below)
|
||||
// Display SCK to NodeMCU pin D5
|
||||
// Display SDI/MOSI to NodeMCU pin D7
|
||||
// Display DC (RS/AO)to NodeMCU pin D3
|
||||
// Display RESET to NodeMCU pin D4 (or RST, see below)
|
||||
// Display CS to NodeMCU pin D8 (or GND, see below)
|
||||
// Display GND to NodeMCU pin GND (0V)
|
||||
// Display VCC to NodeMCU 5V or 3.3V
|
||||
//
|
||||
// The TFT RESET pin can be connected to the NodeMCU RST pin or 3.3V to free up a control pin
|
||||
//
|
||||
// The DC (Data Command) pin may be labelled AO or RS (Register Select)
|
||||
//
|
||||
// With some displays such as the ILI9341 the TFT CS pin can be connected to GND if no more
|
||||
// SPI devices (e.g. an SD Card) are connected, in this case comment out the #define TFT_CS
|
||||
// line below so it is NOT defined. Other displays such at the ST7735 require the TFT CS pin
|
||||
// to be toggled during setup, so in these cases the TFT_CS line must be defined and connected.
|
||||
//
|
||||
// The NodeMCU D0 pin can be used for RST
|
||||
//
|
||||
//
|
||||
// Note: only some versions of the NodeMCU provide the USB 5V on the VIN pin
|
||||
// If 5V is not available at a pin you can use 3.3V but backlight brightness
|
||||
// will be lower.
|
||||
|
||||
|
||||
// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP8266 SETUP ######
|
||||
|
||||
// For NodeMCU - use pin numbers in the form PIN_Dx where Dx is the NodeMCU pin designation
|
||||
//#define TFT_CS PIN_D8 // Chip select control pin D8
|
||||
//#define TFT_DC PIN_D3 // Data Command control pin
|
||||
//#define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line)
|
||||
//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V
|
||||
|
||||
//#define TFT_BL PIN_D1 // LED back-light (only for ST7789 with backlight control pin)
|
||||
|
||||
//#define TOUCH_CS PIN_D2 // Chip select pin (T_CS) of touch screen
|
||||
|
||||
//#define TFT_WR PIN_D2 // Write strobe for modified Raspberry Pi TFT only
|
||||
|
||||
|
||||
// ###### FOR ESP8266 OVERLAP MODE EDIT THE PIN NUMBERS IN THE FOLLOWING LINES ######
|
||||
|
||||
// Overlap mode shares the ESP8266 FLASH SPI bus with the TFT so has a performance impact
|
||||
// but saves pins for other functions. It is best not to connect MISO as some displays
|
||||
// do not tristate that line when chip select is high!
|
||||
// Note: Only one SPI device can share the FLASH SPI lines, so a SPI touch controller
|
||||
// cannot be connected as well to the same SPI signals.
|
||||
// On NodeMCU 1.0 SD0=MISO, SD1=MOSI, CLK=SCLK to connect to TFT in overlap mode
|
||||
// On NodeMCU V3 S0 =MISO, S1 =MOSI, S2 =SCLK
|
||||
// In ESP8266 overlap mode the following must be defined
|
||||
|
||||
//#define TFT_SPI_OVERLAP
|
||||
|
||||
// In ESP8266 overlap mode the TFT chip select MUST connect to pin D3
|
||||
//#define TFT_CS PIN_D3
|
||||
//#define TFT_DC PIN_D5 // Data Command control pin
|
||||
//#define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line)
|
||||
//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V
|
||||
|
||||
|
||||
// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP32 SETUP ######
|
||||
|
||||
// For ESP32 Dev board (only tested with ILI9341 display)
|
||||
// The hardware SPI can be mapped to any pins
|
||||
|
||||
#define TFT_MISO 12
|
||||
#define TFT_MOSI 13
|
||||
#define TFT_SCLK 14
|
||||
#define TFT_CS 15 // Chip select control pin
|
||||
#define TFT_DC 2 // Data Command control pin
|
||||
//#define TFT_RST 4 // Reset pin (could connect to RST pin)
|
||||
#define TFT_RST -1 // Set TFT_RST to -1 if display RESET is connected to ESP32 board RST
|
||||
|
||||
// For ESP32 Dev board (only tested with GC9A01 display)
|
||||
// The hardware SPI can be mapped to any pins
|
||||
|
||||
//#define TFT_MOSI 15 // In some display driver board, it might be written as "SDA" and so on.
|
||||
//#define TFT_SCLK 14
|
||||
//#define TFT_CS 5 // Chip select control pin
|
||||
//#define TFT_DC 27 // Data Command control pin
|
||||
//#define TFT_RST 33 // Reset pin (could connect to Arduino RESET pin)
|
||||
//#define TFT_BL 22 // LED back-light
|
||||
|
||||
#define TOUCH_CS 33 // Chip select pin (T_CS) of touch screen
|
||||
|
||||
//#define TFT_WR 22 // Write strobe for modified Raspberry Pi TFT only
|
||||
|
||||
// For the M5Stack module use these #define lines
|
||||
//#define TFT_MISO 19
|
||||
//#define TFT_MOSI 23
|
||||
//#define TFT_SCLK 18
|
||||
//#define TFT_CS 14 // Chip select control pin
|
||||
//#define TFT_DC 27 // Data Command control pin
|
||||
//#define TFT_RST 33 // Reset pin (could connect to Arduino RESET pin)
|
||||
//#define TFT_BL 32 // LED back-light (required for M5Stack)
|
||||
|
||||
// ###### EDIT THE PINs BELOW TO SUIT YOUR ESP32 PARALLEL TFT SETUP ######
|
||||
|
||||
// The library supports 8 bit parallel TFTs with the ESP32, the pin
|
||||
// selection below is compatible with ESP32 boards in UNO format.
|
||||
// Wemos D32 boards need to be modified, see diagram in Tools folder.
|
||||
// Only ILI9481 and ILI9341 based displays have been tested!
|
||||
|
||||
// Parallel bus is only supported for the STM32 and ESP32
|
||||
// Example below is for ESP32 Parallel interface with UNO displays
|
||||
|
||||
// Tell the library to use 8 bit parallel mode (otherwise SPI is assumed)
|
||||
//#define TFT_PARALLEL_8_BIT
|
||||
|
||||
// The ESP32 and TFT the pins used for testing are:
|
||||
//#define TFT_CS 33 // Chip select control pin (library pulls permanently low
|
||||
//#define TFT_DC 15 // Data Command control pin - must use a pin in the range 0-31
|
||||
//#define TFT_RST 32 // Reset pin, toggles on startup
|
||||
|
||||
//#define TFT_WR 4 // Write strobe control pin - must use a pin in the range 0-31
|
||||
//#define TFT_RD 2 // Read strobe control pin
|
||||
|
||||
//#define TFT_D0 12 // Must use pins in the range 0-31 for the data bus
|
||||
//#define TFT_D1 13 // so a single register write sets/clears all bits.
|
||||
//#define TFT_D2 26 // Pins can be randomly assigned, this does not affect
|
||||
//#define TFT_D3 25 // TFT screen update performance.
|
||||
//#define TFT_D4 17
|
||||
//#define TFT_D5 16
|
||||
//#define TFT_D6 27
|
||||
//#define TFT_D7 14
|
||||
|
||||
// ###### EDIT THE PINs BELOW TO SUIT YOUR STM32 SPI TFT SETUP ######
|
||||
|
||||
// The TFT can be connected to SPI port 1 or 2
|
||||
//#define TFT_SPI_PORT 1 // SPI port 1 maximum clock rate is 55MHz
|
||||
//#define TFT_MOSI PA7
|
||||
//#define TFT_MISO PA6
|
||||
//#define TFT_SCLK PA5
|
||||
|
||||
//#define TFT_SPI_PORT 2 // SPI port 2 maximum clock rate is 27MHz
|
||||
//#define TFT_MOSI PB15
|
||||
//#define TFT_MISO PB14
|
||||
//#define TFT_SCLK PB13
|
||||
|
||||
// Can use Ardiuno pin references, arbitrary allocation, TFT_eSPI controls chip select
|
||||
//#define TFT_CS D5 // Chip select control pin to TFT CS
|
||||
//#define TFT_DC D6 // Data Command control pin to TFT DC (may be labelled RS = Register Select)
|
||||
//#define TFT_RST D7 // Reset pin to TFT RST (or RESET)
|
||||
// OR alternatively, we can use STM32 port reference names PXnn
|
||||
//#define TFT_CS PE11 // Nucleo-F767ZI equivalent of D5
|
||||
//#define TFT_DC PE9 // Nucleo-F767ZI equivalent of D6
|
||||
//#define TFT_RST PF13 // Nucleo-F767ZI equivalent of D7
|
||||
|
||||
//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to processor reset
|
||||
// Use an Arduino pin for initial testing as connecting to processor reset
|
||||
// may not work (pulse too short at power up?)
|
||||
|
||||
// ##################################################################################
|
||||
//
|
||||
// Section 3. Define the fonts that are to be used here
|
||||
//
|
||||
// ##################################################################################
|
||||
|
||||
// Comment out the #defines below with // to stop that font being loaded
|
||||
// The ESP8366 and ESP32 have plenty of memory so commenting out fonts is not
|
||||
// normally necessary. If all fonts are loaded the extra FLASH space required is
|
||||
// about 17Kbytes. To save FLASH space only enable the fonts you need!
|
||||
|
||||
#define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH
|
||||
#define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters
|
||||
#define LOAD_FONT4 // Font 4. Medium 26 pixel high font, needs ~5848 bytes in FLASH, 96 characters
|
||||
#define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm
|
||||
#define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:-.
|
||||
#define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-.
|
||||
//#define LOAD_FONT8N // Font 8. Alternative to Font 8 above, slightly narrower, so 3 digits fit a 160 pixel TFT
|
||||
#define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts
|
||||
|
||||
// Comment out the #define below to stop the SPIFFS filing system and smooth font code being loaded
|
||||
// this will save ~20kbytes of FLASH
|
||||
#define SMOOTH_FONT
|
||||
|
||||
|
||||
// ##################################################################################
|
||||
//
|
||||
// Section 4. Other options
|
||||
//
|
||||
// ##################################################################################
|
||||
|
||||
// For RP2040 processor and SPI displays, uncomment the following line to use the PIO interface.
|
||||
//#define RP2040_PIO_SPI // Leave commented out to use standard RP2040 SPI port interface
|
||||
|
||||
// For RP2040 processor and 8 or 16 bit parallel displays:
|
||||
// The parallel interface write cycle period is derived from a division of the CPU clock
|
||||
// speed so scales with the processor clock. This means that the divider ratio may need
|
||||
// to be increased when overclocking. I may also need to be adjusted dependant on the
|
||||
// display controller type (ILI94341, HX8357C etc). If RP2040_PIO_CLK_DIV is not defined
|
||||
// the library will set default values which may not suit your display.
|
||||
// The display controller data sheet will specify the minimum write cycle period. The
|
||||
// controllers often work reliably for shorter periods, however if the period is too short
|
||||
// the display may not initialise or graphics will become corrupted.
|
||||
// PIO write cycle frequency = (CPU clock/(4 * RP2040_PIO_CLK_DIV))
|
||||
//#define RP2040_PIO_CLK_DIV 1 // 32ns write cycle at 125MHz CPU clock
|
||||
//#define RP2040_PIO_CLK_DIV 2 // 64ns write cycle at 125MHz CPU clock
|
||||
//#define RP2040_PIO_CLK_DIV 3 // 96ns write cycle at 125MHz CPU clock
|
||||
|
||||
// For the RP2040 processor define the SPI port channel used (default 0 if undefined)
|
||||
//#define TFT_SPI_PORT 1 // Set to 0 if SPI0 pins are used, or 1 if spi1 pins used
|
||||
|
||||
// For the STM32 processor define the SPI port channel used (default 1 if undefined)
|
||||
//#define TFT_SPI_PORT 2 // Set to 1 for SPI port 1, or 2 for SPI port 2
|
||||
|
||||
// Define the SPI clock frequency, this affects the graphics rendering speed. Too
|
||||
// fast and the TFT driver will not keep up and display corruption appears.
|
||||
// With an ILI9341 display 40MHz works OK, 80MHz sometimes fails
|
||||
// With a ST7735 display more than 27MHz may not work (spurious pixels and lines)
|
||||
// With an ILI9163 display 27 MHz works OK.
|
||||
|
||||
// #define SPI_FREQUENCY 1000000
|
||||
// #define SPI_FREQUENCY 5000000
|
||||
// #define SPI_FREQUENCY 10000000
|
||||
// #define SPI_FREQUENCY 20000000
|
||||
// #define SPI_FREQUENCY 27000000
|
||||
// #define SPI_FREQUENCY 40000000
|
||||
#define SPI_FREQUENCY 55000000 // STM32 SPI1 only (SPI2 maximum is 27MHz)
|
||||
// #define SPI_FREQUENCY 80000000
|
||||
|
||||
// Optional reduced SPI frequency for reading TFT
|
||||
#define SPI_READ_FREQUENCY 20000000
|
||||
|
||||
// The XPT2046 requires a lower SPI clock rate of 2.5MHz so we define that here:
|
||||
#define SPI_TOUCH_FREQUENCY 2500000
|
||||
|
||||
// The ESP32 has 2 free SPI ports i.e. VSPI and HSPI, the VSPI is the default.
|
||||
// If the VSPI port is in use and pins are not accessible (e.g. TTGO T-Beam)
|
||||
// then uncomment the following line:
|
||||
#define USE_HSPI_PORT
|
||||
|
||||
// Comment out the following #define if "SPI Transactions" do not need to be
|
||||
// supported. When commented out the code size will be smaller and sketches will
|
||||
// run slightly faster, so leave it commented out unless you need it!
|
||||
|
||||
// Transaction support is needed to work with SD library but not needed with TFT_SdFat
|
||||
// Transaction support is required if other SPI devices are connected.
|
||||
|
||||
// Transactions are automatically enabled by the library for an ESP32 (to use HAL mutex)
|
||||
// so changing it here has no effect
|
||||
|
||||
// #define SUPPORT_TRANSACTIONS
|
||||
BIN
PacoMouseCYD/doc/options/TFT_eSPI_CYD2.8/ESP32-2432S028.jpg
Normal file
|
After Width: | Height: | Size: 118 KiB |
383
PacoMouseCYD/doc/options/TFT_eSPI_CYD2.8/User_Setup.h
Normal file
@@ -0,0 +1,383 @@
|
||||
// USER DEFINED SETTINGS
|
||||
// Set driver type, fonts to be loaded, pins used and SPI control method etc
|
||||
//
|
||||
// See the User_Setup_Select.h file if you wish to be able to define multiple
|
||||
// setups and then easily select which setup file is used by the compiler.
|
||||
//
|
||||
// If this file is edited correctly then all the library example sketches should
|
||||
// run without the need to make any more changes for a particular hardware setup!
|
||||
// Note that some sketches are designed for a particular TFT pixel width/height
|
||||
|
||||
// User defined information reported by "Read_User_Setup" test & diagnostics example
|
||||
#define USER_SETUP_INFO "User_Setup CYD 2.8"
|
||||
|
||||
// Define to disable all #warnings in library (can be put in User_Setup_Select.h)
|
||||
//#define DISABLE_ALL_LIBRARY_WARNINGS
|
||||
|
||||
// ##################################################################################
|
||||
//
|
||||
// Section 1. Call up the right driver file and any options for it
|
||||
//
|
||||
// ##################################################################################
|
||||
|
||||
// Define STM32 to invoke optimised processor support (only for STM32)
|
||||
//#define STM32
|
||||
|
||||
// Defining the STM32 board allows the library to optimise the performance
|
||||
// for UNO compatible "MCUfriend" style shields
|
||||
//#define NUCLEO_64_TFT
|
||||
//#define NUCLEO_144_TFT
|
||||
|
||||
// STM32 8 bit parallel only:
|
||||
// If STN32 Port A or B pins 0-7 are used for 8 bit parallel data bus bits 0-7
|
||||
// then this will improve rendering performance by a factor of ~8x
|
||||
//#define STM_PORTA_DATA_BUS
|
||||
//#define STM_PORTB_DATA_BUS
|
||||
|
||||
// Tell the library to use parallel mode (otherwise SPI is assumed)
|
||||
//#define TFT_PARALLEL_8_BIT
|
||||
//#defined TFT_PARALLEL_16_BIT // **** 16 bit parallel ONLY for RP2040 processor ****
|
||||
|
||||
// Display type - only define if RPi display
|
||||
//#define RPI_DISPLAY_TYPE // 20MHz maximum SPI
|
||||
|
||||
// Only define one driver, the other ones must be commented out
|
||||
//#define ILI9341_DRIVER // Generic driver for common displays
|
||||
#define ILI9341_2_DRIVER // Alternative ILI9341 driver, see https://github.com/Bodmer/TFT_eSPI/issues/1172
|
||||
//#define ST7735_DRIVER // Define additional parameters below for this display
|
||||
//#define ILI9163_DRIVER // Define additional parameters below for this display
|
||||
//#define S6D02A1_DRIVER
|
||||
//#define RPI_ILI9486_DRIVER // 20MHz maximum SPI
|
||||
//#define HX8357D_DRIVER
|
||||
//#define ILI9481_DRIVER
|
||||
//#define ILI9486_DRIVER
|
||||
//#define ILI9488_DRIVER // WARNING: Do not connect ILI9488 display SDO to MISO if other devices share the SPI bus (TFT SDO does NOT tristate when CS is high)
|
||||
//#define ST7789_DRIVER // Full configuration option, define additional parameters below for this display
|
||||
//#define ST7789_2_DRIVER // Minimal configuration option, define additional parameters below for this display
|
||||
//#define R61581_DRIVER
|
||||
//#define RM68140_DRIVER
|
||||
//#define ST7796_DRIVER
|
||||
//#define SSD1351_DRIVER
|
||||
//#define SSD1963_480_DRIVER
|
||||
//#define SSD1963_800_DRIVER
|
||||
//#define SSD1963_800ALT_DRIVER
|
||||
//#define ILI9225_DRIVER
|
||||
//#define GC9A01_DRIVER
|
||||
|
||||
// Some displays support SPI reads via the MISO pin, other displays have a single
|
||||
// bi-directional SDA pin and the library will try to read this via the MOSI line.
|
||||
// To use the SDA line for reading data from the TFT uncomment the following line:
|
||||
|
||||
// #define TFT_SDA_READ // This option is for ESP32 ONLY, tested with ST7789 and GC9A01 display only
|
||||
|
||||
// For ST7735, ST7789 and ILI9341 ONLY, define the colour order IF the blue and red are swapped on your display
|
||||
// Try ONE option at a time to find the correct colour order for your display
|
||||
|
||||
// #define TFT_RGB_ORDER TFT_RGB // Colour order Red-Green-Blue
|
||||
// #define TFT_RGB_ORDER TFT_BGR // Colour order Blue-Green-Red
|
||||
|
||||
// For M5Stack ESP32 module with integrated ILI9341 display ONLY, remove // in line below
|
||||
|
||||
// #define M5STACK
|
||||
|
||||
// For ST7789, ST7735, ILI9163 and GC9A01 ONLY, define the pixel width and height in portrait orientation
|
||||
// #define TFT_WIDTH 80
|
||||
// #define TFT_WIDTH 128
|
||||
// #define TFT_WIDTH 172 // ST7789 172 x 320
|
||||
#define TFT_WIDTH 240 // ST7789 240 x 240 and 240 x 320
|
||||
// #define TFT_HEIGHT 160
|
||||
// #define TFT_HEIGHT 128
|
||||
// #define TFT_HEIGHT 240 // ST7789 240 x 240
|
||||
#define TFT_HEIGHT 320 // ST7789 240 x 320
|
||||
// #define TFT_HEIGHT 240 // GC9A01 240 x 240
|
||||
|
||||
// For ST7735 ONLY, define the type of display, originally this was based on the
|
||||
// colour of the tab on the screen protector film but this is not always true, so try
|
||||
// out the different options below if the screen does not display graphics correctly,
|
||||
// e.g. colours wrong, mirror images, or stray pixels at the edges.
|
||||
// Comment out ALL BUT ONE of these options for a ST7735 display driver, save this
|
||||
// this User_Setup file, then rebuild and upload the sketch to the board again:
|
||||
|
||||
// #define ST7735_INITB
|
||||
// #define ST7735_GREENTAB
|
||||
// #define ST7735_GREENTAB2
|
||||
// #define ST7735_GREENTAB3
|
||||
// #define ST7735_GREENTAB128 // For 128 x 128 display
|
||||
// #define ST7735_GREENTAB160x80 // For 160 x 80 display (BGR, inverted, 26 offset)
|
||||
// #define ST7735_ROBOTLCD // For some RobotLCD arduino shields (128x160, BGR, https://docs.arduino.cc/retired/getting-started-guides/TFT)
|
||||
// #define ST7735_REDTAB
|
||||
// #define ST7735_BLACKTAB
|
||||
// #define ST7735_REDTAB160x80 // For 160 x 80 display with 24 pixel offset
|
||||
|
||||
// If colours are inverted (white shows as black) then uncomment one of the next
|
||||
// 2 lines try both options, one of the options should correct the inversion.
|
||||
|
||||
#define TFT_INVERSION_ON
|
||||
// #define TFT_INVERSION_OFF
|
||||
|
||||
|
||||
// ##################################################################################
|
||||
//
|
||||
// Section 2. Define the pins that are used to interface with the display here
|
||||
//
|
||||
// ##################################################################################
|
||||
|
||||
// If a backlight control signal is available then define the TFT_BL pin in Section 2
|
||||
// below. The backlight will be turned ON when tft.begin() is called, but the library
|
||||
// needs to know if the LEDs are ON with the pin HIGH or LOW. If the LEDs are to be
|
||||
// driven with a PWM signal or turned OFF/ON then this must be handled by the user
|
||||
// sketch. e.g. with digitalWrite(TFT_BL, LOW);
|
||||
|
||||
#define TFT_BL 21 // LED back-light control pin
|
||||
#define TFT_BACKLIGHT_ON HIGH // Level to turn ON back-light (HIGH or LOW)
|
||||
|
||||
|
||||
|
||||
// We must use hardware SPI, a minimum of 3 GPIO pins is needed.
|
||||
// Typical setup for ESP8266 NodeMCU ESP-12 is :
|
||||
//
|
||||
// Display SDO/MISO to NodeMCU pin D6 (or leave disconnected if not reading TFT)
|
||||
// Display LED to NodeMCU pin VIN (or 5V, see below)
|
||||
// Display SCK to NodeMCU pin D5
|
||||
// Display SDI/MOSI to NodeMCU pin D7
|
||||
// Display DC (RS/AO)to NodeMCU pin D3
|
||||
// Display RESET to NodeMCU pin D4 (or RST, see below)
|
||||
// Display CS to NodeMCU pin D8 (or GND, see below)
|
||||
// Display GND to NodeMCU pin GND (0V)
|
||||
// Display VCC to NodeMCU 5V or 3.3V
|
||||
//
|
||||
// The TFT RESET pin can be connected to the NodeMCU RST pin or 3.3V to free up a control pin
|
||||
//
|
||||
// The DC (Data Command) pin may be labelled AO or RS (Register Select)
|
||||
//
|
||||
// With some displays such as the ILI9341 the TFT CS pin can be connected to GND if no more
|
||||
// SPI devices (e.g. an SD Card) are connected, in this case comment out the #define TFT_CS
|
||||
// line below so it is NOT defined. Other displays such at the ST7735 require the TFT CS pin
|
||||
// to be toggled during setup, so in these cases the TFT_CS line must be defined and connected.
|
||||
//
|
||||
// The NodeMCU D0 pin can be used for RST
|
||||
//
|
||||
//
|
||||
// Note: only some versions of the NodeMCU provide the USB 5V on the VIN pin
|
||||
// If 5V is not available at a pin you can use 3.3V but backlight brightness
|
||||
// will be lower.
|
||||
|
||||
|
||||
// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP8266 SETUP ######
|
||||
|
||||
// For NodeMCU - use pin numbers in the form PIN_Dx where Dx is the NodeMCU pin designation
|
||||
//#define TFT_CS PIN_D8 // Chip select control pin D8
|
||||
//#define TFT_DC PIN_D3 // Data Command control pin
|
||||
//#define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line)
|
||||
//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V
|
||||
|
||||
//#define TFT_BL PIN_D1 // LED back-light (only for ST7789 with backlight control pin)
|
||||
|
||||
//#define TOUCH_CS PIN_D2 // Chip select pin (T_CS) of touch screen
|
||||
|
||||
//#define TFT_WR PIN_D2 // Write strobe for modified Raspberry Pi TFT only
|
||||
|
||||
|
||||
// ###### FOR ESP8266 OVERLAP MODE EDIT THE PIN NUMBERS IN THE FOLLOWING LINES ######
|
||||
|
||||
// Overlap mode shares the ESP8266 FLASH SPI bus with the TFT so has a performance impact
|
||||
// but saves pins for other functions. It is best not to connect MISO as some displays
|
||||
// do not tristate that line when chip select is high!
|
||||
// Note: Only one SPI device can share the FLASH SPI lines, so a SPI touch controller
|
||||
// cannot be connected as well to the same SPI signals.
|
||||
// On NodeMCU 1.0 SD0=MISO, SD1=MOSI, CLK=SCLK to connect to TFT in overlap mode
|
||||
// On NodeMCU V3 S0 =MISO, S1 =MOSI, S2 =SCLK
|
||||
// In ESP8266 overlap mode the following must be defined
|
||||
|
||||
//#define TFT_SPI_OVERLAP
|
||||
|
||||
// In ESP8266 overlap mode the TFT chip select MUST connect to pin D3
|
||||
//#define TFT_CS PIN_D3
|
||||
//#define TFT_DC PIN_D5 // Data Command control pin
|
||||
//#define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line)
|
||||
//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V
|
||||
|
||||
|
||||
// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP32 SETUP ######
|
||||
|
||||
// For ESP32 Dev board (only tested with ILI9341 display)
|
||||
// The hardware SPI can be mapped to any pins
|
||||
|
||||
#define TFT_MISO 12
|
||||
#define TFT_MOSI 13
|
||||
#define TFT_SCLK 14
|
||||
#define TFT_CS 15 // Chip select control pin
|
||||
#define TFT_DC 2 // Data Command control pin
|
||||
//#define TFT_RST 4 // Reset pin (could connect to RST pin)
|
||||
#define TFT_RST -1 // Set TFT_RST to -1 if display RESET is connected to ESP32 board RST
|
||||
|
||||
// For ESP32 Dev board (only tested with GC9A01 display)
|
||||
// The hardware SPI can be mapped to any pins
|
||||
|
||||
//#define TFT_MOSI 15 // In some display driver board, it might be written as "SDA" and so on.
|
||||
//#define TFT_SCLK 14
|
||||
//#define TFT_CS 5 // Chip select control pin
|
||||
//#define TFT_DC 27 // Data Command control pin
|
||||
//#define TFT_RST 33 // Reset pin (could connect to Arduino RESET pin)
|
||||
//#define TFT_BL 22 // LED back-light
|
||||
|
||||
#define TOUCH_CS 33 // Chip select pin (T_CS) of touch screen
|
||||
|
||||
//#define TFT_WR 22 // Write strobe for modified Raspberry Pi TFT only
|
||||
|
||||
// For the M5Stack module use these #define lines
|
||||
//#define TFT_MISO 19
|
||||
//#define TFT_MOSI 23
|
||||
//#define TFT_SCLK 18
|
||||
//#define TFT_CS 14 // Chip select control pin
|
||||
//#define TFT_DC 27 // Data Command control pin
|
||||
//#define TFT_RST 33 // Reset pin (could connect to Arduino RESET pin)
|
||||
//#define TFT_BL 32 // LED back-light (required for M5Stack)
|
||||
|
||||
// ###### EDIT THE PINs BELOW TO SUIT YOUR ESP32 PARALLEL TFT SETUP ######
|
||||
|
||||
// The library supports 8 bit parallel TFTs with the ESP32, the pin
|
||||
// selection below is compatible with ESP32 boards in UNO format.
|
||||
// Wemos D32 boards need to be modified, see diagram in Tools folder.
|
||||
// Only ILI9481 and ILI9341 based displays have been tested!
|
||||
|
||||
// Parallel bus is only supported for the STM32 and ESP32
|
||||
// Example below is for ESP32 Parallel interface with UNO displays
|
||||
|
||||
// Tell the library to use 8 bit parallel mode (otherwise SPI is assumed)
|
||||
//#define TFT_PARALLEL_8_BIT
|
||||
|
||||
// The ESP32 and TFT the pins used for testing are:
|
||||
//#define TFT_CS 33 // Chip select control pin (library pulls permanently low
|
||||
//#define TFT_DC 15 // Data Command control pin - must use a pin in the range 0-31
|
||||
//#define TFT_RST 32 // Reset pin, toggles on startup
|
||||
|
||||
//#define TFT_WR 4 // Write strobe control pin - must use a pin in the range 0-31
|
||||
//#define TFT_RD 2 // Read strobe control pin
|
||||
|
||||
//#define TFT_D0 12 // Must use pins in the range 0-31 for the data bus
|
||||
//#define TFT_D1 13 // so a single register write sets/clears all bits.
|
||||
//#define TFT_D2 26 // Pins can be randomly assigned, this does not affect
|
||||
//#define TFT_D3 25 // TFT screen update performance.
|
||||
//#define TFT_D4 17
|
||||
//#define TFT_D5 16
|
||||
//#define TFT_D6 27
|
||||
//#define TFT_D7 14
|
||||
|
||||
// ###### EDIT THE PINs BELOW TO SUIT YOUR STM32 SPI TFT SETUP ######
|
||||
|
||||
// The TFT can be connected to SPI port 1 or 2
|
||||
//#define TFT_SPI_PORT 1 // SPI port 1 maximum clock rate is 55MHz
|
||||
//#define TFT_MOSI PA7
|
||||
//#define TFT_MISO PA6
|
||||
//#define TFT_SCLK PA5
|
||||
|
||||
//#define TFT_SPI_PORT 2 // SPI port 2 maximum clock rate is 27MHz
|
||||
//#define TFT_MOSI PB15
|
||||
//#define TFT_MISO PB14
|
||||
//#define TFT_SCLK PB13
|
||||
|
||||
// Can use Ardiuno pin references, arbitrary allocation, TFT_eSPI controls chip select
|
||||
//#define TFT_CS D5 // Chip select control pin to TFT CS
|
||||
//#define TFT_DC D6 // Data Command control pin to TFT DC (may be labelled RS = Register Select)
|
||||
//#define TFT_RST D7 // Reset pin to TFT RST (or RESET)
|
||||
// OR alternatively, we can use STM32 port reference names PXnn
|
||||
//#define TFT_CS PE11 // Nucleo-F767ZI equivalent of D5
|
||||
//#define TFT_DC PE9 // Nucleo-F767ZI equivalent of D6
|
||||
//#define TFT_RST PF13 // Nucleo-F767ZI equivalent of D7
|
||||
|
||||
//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to processor reset
|
||||
// Use an Arduino pin for initial testing as connecting to processor reset
|
||||
// may not work (pulse too short at power up?)
|
||||
|
||||
// ##################################################################################
|
||||
//
|
||||
// Section 3. Define the fonts that are to be used here
|
||||
//
|
||||
// ##################################################################################
|
||||
|
||||
// Comment out the #defines below with // to stop that font being loaded
|
||||
// The ESP8366 and ESP32 have plenty of memory so commenting out fonts is not
|
||||
// normally necessary. If all fonts are loaded the extra FLASH space required is
|
||||
// about 17Kbytes. To save FLASH space only enable the fonts you need!
|
||||
|
||||
#define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH
|
||||
#define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters
|
||||
#define LOAD_FONT4 // Font 4. Medium 26 pixel high font, needs ~5848 bytes in FLASH, 96 characters
|
||||
#define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm
|
||||
#define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:-.
|
||||
#define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-.
|
||||
//#define LOAD_FONT8N // Font 8. Alternative to Font 8 above, slightly narrower, so 3 digits fit a 160 pixel TFT
|
||||
#define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts
|
||||
|
||||
// Comment out the #define below to stop the SPIFFS filing system and smooth font code being loaded
|
||||
// this will save ~20kbytes of FLASH
|
||||
#define SMOOTH_FONT
|
||||
|
||||
|
||||
// ##################################################################################
|
||||
//
|
||||
// Section 4. Other options
|
||||
//
|
||||
// ##################################################################################
|
||||
|
||||
// For RP2040 processor and SPI displays, uncomment the following line to use the PIO interface.
|
||||
//#define RP2040_PIO_SPI // Leave commented out to use standard RP2040 SPI port interface
|
||||
|
||||
// For RP2040 processor and 8 or 16 bit parallel displays:
|
||||
// The parallel interface write cycle period is derived from a division of the CPU clock
|
||||
// speed so scales with the processor clock. This means that the divider ratio may need
|
||||
// to be increased when overclocking. I may also need to be adjusted dependant on the
|
||||
// display controller type (ILI94341, HX8357C etc). If RP2040_PIO_CLK_DIV is not defined
|
||||
// the library will set default values which may not suit your display.
|
||||
// The display controller data sheet will specify the minimum write cycle period. The
|
||||
// controllers often work reliably for shorter periods, however if the period is too short
|
||||
// the display may not initialise or graphics will become corrupted.
|
||||
// PIO write cycle frequency = (CPU clock/(4 * RP2040_PIO_CLK_DIV))
|
||||
//#define RP2040_PIO_CLK_DIV 1 // 32ns write cycle at 125MHz CPU clock
|
||||
//#define RP2040_PIO_CLK_DIV 2 // 64ns write cycle at 125MHz CPU clock
|
||||
//#define RP2040_PIO_CLK_DIV 3 // 96ns write cycle at 125MHz CPU clock
|
||||
|
||||
// For the RP2040 processor define the SPI port channel used (default 0 if undefined)
|
||||
//#define TFT_SPI_PORT 1 // Set to 0 if SPI0 pins are used, or 1 if spi1 pins used
|
||||
|
||||
// For the STM32 processor define the SPI port channel used (default 1 if undefined)
|
||||
//#define TFT_SPI_PORT 2 // Set to 1 for SPI port 1, or 2 for SPI port 2
|
||||
|
||||
// Define the SPI clock frequency, this affects the graphics rendering speed. Too
|
||||
// fast and the TFT driver will not keep up and display corruption appears.
|
||||
// With an ILI9341 display 40MHz works OK, 80MHz sometimes fails
|
||||
// With a ST7735 display more than 27MHz may not work (spurious pixels and lines)
|
||||
// With an ILI9163 display 27 MHz works OK.
|
||||
|
||||
// #define SPI_FREQUENCY 1000000
|
||||
// #define SPI_FREQUENCY 5000000
|
||||
// #define SPI_FREQUENCY 10000000
|
||||
// #define SPI_FREQUENCY 20000000
|
||||
// #define SPI_FREQUENCY 27000000
|
||||
// #define SPI_FREQUENCY 40000000
|
||||
#define SPI_FREQUENCY 55000000 // STM32 SPI1 only (SPI2 maximum is 27MHz)
|
||||
// #define SPI_FREQUENCY 80000000
|
||||
|
||||
// Optional reduced SPI frequency for reading TFT
|
||||
#define SPI_READ_FREQUENCY 20000000
|
||||
|
||||
// The XPT2046 requires a lower SPI clock rate of 2.5MHz so we define that here:
|
||||
#define SPI_TOUCH_FREQUENCY 2500000
|
||||
|
||||
// The ESP32 has 2 free SPI ports i.e. VSPI and HSPI, the VSPI is the default.
|
||||
// If the VSPI port is in use and pins are not accessible (e.g. TTGO T-Beam)
|
||||
// then uncomment the following line:
|
||||
#define USE_HSPI_PORT
|
||||
|
||||
// Comment out the following #define if "SPI Transactions" do not need to be
|
||||
// supported. When commented out the code size will be smaller and sketches will
|
||||
// run slightly faster, so leave it commented out unless you need it!
|
||||
|
||||
// Transaction support is needed to work with SD library but not needed with TFT_SdFat
|
||||
// Transaction support is required if other SPI devices are connected.
|
||||
|
||||
// Transactions are automatically enabled by the library for an ESP32 (to use HAL mutex)
|
||||
// so changing it here has no effect
|
||||
|
||||
// #define SUPPORT_TRANSACTIONS
|
||||
383
PacoMouseCYD/doc/options/TFT_eSPI_CYD3.2/User_Setup.h
Normal file
@@ -0,0 +1,383 @@
|
||||
// USER DEFINED SETTINGS
|
||||
// Set driver type, fonts to be loaded, pins used and SPI control method etc
|
||||
//
|
||||
// See the User_Setup_Select.h file if you wish to be able to define multiple
|
||||
// setups and then easily select which setup file is used by the compiler.
|
||||
//
|
||||
// If this file is edited correctly then all the library example sketches should
|
||||
// run without the need to make any more changes for a particular hardware setup!
|
||||
// Note that some sketches are designed for a particular TFT pixel width/height
|
||||
|
||||
// User defined information reported by "Read_User_Setup" test & diagnostics example
|
||||
#define USER_SETUP_INFO "User_Setup CYD 3.2"
|
||||
|
||||
// Define to disable all #warnings in library (can be put in User_Setup_Select.h)
|
||||
//#define DISABLE_ALL_LIBRARY_WARNINGS
|
||||
|
||||
// ##################################################################################
|
||||
//
|
||||
// Section 1. Call up the right driver file and any options for it
|
||||
//
|
||||
// ##################################################################################
|
||||
|
||||
// Define STM32 to invoke optimised processor support (only for STM32)
|
||||
//#define STM32
|
||||
|
||||
// Defining the STM32 board allows the library to optimise the performance
|
||||
// for UNO compatible "MCUfriend" style shields
|
||||
//#define NUCLEO_64_TFT
|
||||
//#define NUCLEO_144_TFT
|
||||
|
||||
// STM32 8 bit parallel only:
|
||||
// If STN32 Port A or B pins 0-7 are used for 8 bit parallel data bus bits 0-7
|
||||
// then this will improve rendering performance by a factor of ~8x
|
||||
//#define STM_PORTA_DATA_BUS
|
||||
//#define STM_PORTB_DATA_BUS
|
||||
|
||||
// Tell the library to use parallel mode (otherwise SPI is assumed)
|
||||
//#define TFT_PARALLEL_8_BIT
|
||||
//#defined TFT_PARALLEL_16_BIT // **** 16 bit parallel ONLY for RP2040 processor ****
|
||||
|
||||
// Display type - only define if RPi display
|
||||
//#define RPI_DISPLAY_TYPE // 20MHz maximum SPI
|
||||
|
||||
// Only define one driver, the other ones must be commented out
|
||||
//#define ILI9341_DRIVER // Generic driver for common displays
|
||||
#define ILI9341_2_DRIVER // Alternative ILI9341 driver, see https://github.com/Bodmer/TFT_eSPI/issues/1172
|
||||
//#define ST7735_DRIVER // Define additional parameters below for this display
|
||||
//#define ILI9163_DRIVER // Define additional parameters below for this display
|
||||
//#define S6D02A1_DRIVER
|
||||
//#define RPI_ILI9486_DRIVER // 20MHz maximum SPI
|
||||
//#define HX8357D_DRIVER
|
||||
//#define ILI9481_DRIVER
|
||||
//#define ILI9486_DRIVER
|
||||
//#define ILI9488_DRIVER // WARNING: Do not connect ILI9488 display SDO to MISO if other devices share the SPI bus (TFT SDO does NOT tristate when CS is high)
|
||||
//#define ST7789_DRIVER // Full configuration option, define additional parameters below for this display
|
||||
//#define ST7789_2_DRIVER // Minimal configuration option, define additional parameters below for this display
|
||||
//#define R61581_DRIVER
|
||||
//#define RM68140_DRIVER
|
||||
//#define ST7796_DRIVER
|
||||
//#define SSD1351_DRIVER
|
||||
//#define SSD1963_480_DRIVER
|
||||
//#define SSD1963_800_DRIVER
|
||||
//#define SSD1963_800ALT_DRIVER
|
||||
//#define ILI9225_DRIVER
|
||||
//#define GC9A01_DRIVER
|
||||
|
||||
// Some displays support SPI reads via the MISO pin, other displays have a single
|
||||
// bi-directional SDA pin and the library will try to read this via the MOSI line.
|
||||
// To use the SDA line for reading data from the TFT uncomment the following line:
|
||||
|
||||
// #define TFT_SDA_READ // This option is for ESP32 ONLY, tested with ST7789 and GC9A01 display only
|
||||
|
||||
// For ST7735, ST7789 and ILI9341 ONLY, define the colour order IF the blue and red are swapped on your display
|
||||
// Try ONE option at a time to find the correct colour order for your display
|
||||
|
||||
// #define TFT_RGB_ORDER TFT_RGB // Colour order Red-Green-Blue
|
||||
// #define TFT_RGB_ORDER TFT_BGR // Colour order Blue-Green-Red
|
||||
|
||||
// For M5Stack ESP32 module with integrated ILI9341 display ONLY, remove // in line below
|
||||
|
||||
// #define M5STACK
|
||||
|
||||
// For ST7789, ST7735, ILI9163 and GC9A01 ONLY, define the pixel width and height in portrait orientation
|
||||
// #define TFT_WIDTH 80
|
||||
// #define TFT_WIDTH 128
|
||||
// #define TFT_WIDTH 172 // ST7789 172 x 320
|
||||
#define TFT_WIDTH 240 // ST7789 240 x 240 and 240 x 320
|
||||
// #define TFT_HEIGHT 160
|
||||
// #define TFT_HEIGHT 128
|
||||
// #define TFT_HEIGHT 240 // ST7789 240 x 240
|
||||
#define TFT_HEIGHT 320 // ST7789 240 x 320
|
||||
// #define TFT_HEIGHT 240 // GC9A01 240 x 240
|
||||
|
||||
// For ST7735 ONLY, define the type of display, originally this was based on the
|
||||
// colour of the tab on the screen protector film but this is not always true, so try
|
||||
// out the different options below if the screen does not display graphics correctly,
|
||||
// e.g. colours wrong, mirror images, or stray pixels at the edges.
|
||||
// Comment out ALL BUT ONE of these options for a ST7735 display driver, save this
|
||||
// this User_Setup file, then rebuild and upload the sketch to the board again:
|
||||
|
||||
// #define ST7735_INITB
|
||||
// #define ST7735_GREENTAB
|
||||
// #define ST7735_GREENTAB2
|
||||
// #define ST7735_GREENTAB3
|
||||
// #define ST7735_GREENTAB128 // For 128 x 128 display
|
||||
// #define ST7735_GREENTAB160x80 // For 160 x 80 display (BGR, inverted, 26 offset)
|
||||
// #define ST7735_ROBOTLCD // For some RobotLCD arduino shields (128x160, BGR, https://docs.arduino.cc/retired/getting-started-guides/TFT)
|
||||
// #define ST7735_REDTAB
|
||||
// #define ST7735_BLACKTAB
|
||||
// #define ST7735_REDTAB160x80 // For 160 x 80 display with 24 pixel offset
|
||||
|
||||
// If colours are inverted (white shows as black) then uncomment one of the next
|
||||
// 2 lines try both options, one of the options should correct the inversion.
|
||||
|
||||
#define TFT_INVERSION_ON
|
||||
// #define TFT_INVERSION_OFF
|
||||
|
||||
|
||||
// ##################################################################################
|
||||
//
|
||||
// Section 2. Define the pins that are used to interface with the display here
|
||||
//
|
||||
// ##################################################################################
|
||||
|
||||
// If a backlight control signal is available then define the TFT_BL pin in Section 2
|
||||
// below. The backlight will be turned ON when tft.begin() is called, but the library
|
||||
// needs to know if the LEDs are ON with the pin HIGH or LOW. If the LEDs are to be
|
||||
// driven with a PWM signal or turned OFF/ON then this must be handled by the user
|
||||
// sketch. e.g. with digitalWrite(TFT_BL, LOW);
|
||||
|
||||
#define TFT_BL 27 // LED back-light control pin
|
||||
#define TFT_BACKLIGHT_ON HIGH // Level to turn ON back-light (HIGH or LOW)
|
||||
|
||||
|
||||
|
||||
// We must use hardware SPI, a minimum of 3 GPIO pins is needed.
|
||||
// Typical setup for ESP8266 NodeMCU ESP-12 is :
|
||||
//
|
||||
// Display SDO/MISO to NodeMCU pin D6 (or leave disconnected if not reading TFT)
|
||||
// Display LED to NodeMCU pin VIN (or 5V, see below)
|
||||
// Display SCK to NodeMCU pin D5
|
||||
// Display SDI/MOSI to NodeMCU pin D7
|
||||
// Display DC (RS/AO)to NodeMCU pin D3
|
||||
// Display RESET to NodeMCU pin D4 (or RST, see below)
|
||||
// Display CS to NodeMCU pin D8 (or GND, see below)
|
||||
// Display GND to NodeMCU pin GND (0V)
|
||||
// Display VCC to NodeMCU 5V or 3.3V
|
||||
//
|
||||
// The TFT RESET pin can be connected to the NodeMCU RST pin or 3.3V to free up a control pin
|
||||
//
|
||||
// The DC (Data Command) pin may be labelled AO or RS (Register Select)
|
||||
//
|
||||
// With some displays such as the ILI9341 the TFT CS pin can be connected to GND if no more
|
||||
// SPI devices (e.g. an SD Card) are connected, in this case comment out the #define TFT_CS
|
||||
// line below so it is NOT defined. Other displays such at the ST7735 require the TFT CS pin
|
||||
// to be toggled during setup, so in these cases the TFT_CS line must be defined and connected.
|
||||
//
|
||||
// The NodeMCU D0 pin can be used for RST
|
||||
//
|
||||
//
|
||||
// Note: only some versions of the NodeMCU provide the USB 5V on the VIN pin
|
||||
// If 5V is not available at a pin you can use 3.3V but backlight brightness
|
||||
// will be lower.
|
||||
|
||||
|
||||
// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP8266 SETUP ######
|
||||
|
||||
// For NodeMCU - use pin numbers in the form PIN_Dx where Dx is the NodeMCU pin designation
|
||||
//#define TFT_CS PIN_D8 // Chip select control pin D8
|
||||
//#define TFT_DC PIN_D3 // Data Command control pin
|
||||
//#define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line)
|
||||
//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V
|
||||
|
||||
//#define TFT_BL PIN_D1 // LED back-light (only for ST7789 with backlight control pin)
|
||||
|
||||
//#define TOUCH_CS PIN_D2 // Chip select pin (T_CS) of touch screen
|
||||
|
||||
//#define TFT_WR PIN_D2 // Write strobe for modified Raspberry Pi TFT only
|
||||
|
||||
|
||||
// ###### FOR ESP8266 OVERLAP MODE EDIT THE PIN NUMBERS IN THE FOLLOWING LINES ######
|
||||
|
||||
// Overlap mode shares the ESP8266 FLASH SPI bus with the TFT so has a performance impact
|
||||
// but saves pins for other functions. It is best not to connect MISO as some displays
|
||||
// do not tristate that line when chip select is high!
|
||||
// Note: Only one SPI device can share the FLASH SPI lines, so a SPI touch controller
|
||||
// cannot be connected as well to the same SPI signals.
|
||||
// On NodeMCU 1.0 SD0=MISO, SD1=MOSI, CLK=SCLK to connect to TFT in overlap mode
|
||||
// On NodeMCU V3 S0 =MISO, S1 =MOSI, S2 =SCLK
|
||||
// In ESP8266 overlap mode the following must be defined
|
||||
|
||||
//#define TFT_SPI_OVERLAP
|
||||
|
||||
// In ESP8266 overlap mode the TFT chip select MUST connect to pin D3
|
||||
//#define TFT_CS PIN_D3
|
||||
//#define TFT_DC PIN_D5 // Data Command control pin
|
||||
//#define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line)
|
||||
//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V
|
||||
|
||||
|
||||
// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP32 SETUP ######
|
||||
|
||||
// For ESP32 Dev board (only tested with ILI9341 display)
|
||||
// The hardware SPI can be mapped to any pins
|
||||
|
||||
#define TFT_MISO 12
|
||||
#define TFT_MOSI 13
|
||||
#define TFT_SCLK 14
|
||||
#define TFT_CS 15 // Chip select control pin
|
||||
#define TFT_DC 2 // Data Command control pin
|
||||
//#define TFT_RST 4 // Reset pin (could connect to RST pin)
|
||||
#define TFT_RST -1 // Set TFT_RST to -1 if display RESET is connected to ESP32 board RST
|
||||
|
||||
// For ESP32 Dev board (only tested with GC9A01 display)
|
||||
// The hardware SPI can be mapped to any pins
|
||||
|
||||
//#define TFT_MOSI 15 // In some display driver board, it might be written as "SDA" and so on.
|
||||
//#define TFT_SCLK 14
|
||||
//#define TFT_CS 5 // Chip select control pin
|
||||
//#define TFT_DC 27 // Data Command control pin
|
||||
//#define TFT_RST 33 // Reset pin (could connect to Arduino RESET pin)
|
||||
//#define TFT_BL 22 // LED back-light
|
||||
|
||||
#define TOUCH_CS 33 // Chip select pin (T_CS) of touch screen
|
||||
|
||||
//#define TFT_WR 22 // Write strobe for modified Raspberry Pi TFT only
|
||||
|
||||
// For the M5Stack module use these #define lines
|
||||
//#define TFT_MISO 19
|
||||
//#define TFT_MOSI 23
|
||||
//#define TFT_SCLK 18
|
||||
//#define TFT_CS 14 // Chip select control pin
|
||||
//#define TFT_DC 27 // Data Command control pin
|
||||
//#define TFT_RST 33 // Reset pin (could connect to Arduino RESET pin)
|
||||
//#define TFT_BL 32 // LED back-light (required for M5Stack)
|
||||
|
||||
// ###### EDIT THE PINs BELOW TO SUIT YOUR ESP32 PARALLEL TFT SETUP ######
|
||||
|
||||
// The library supports 8 bit parallel TFTs with the ESP32, the pin
|
||||
// selection below is compatible with ESP32 boards in UNO format.
|
||||
// Wemos D32 boards need to be modified, see diagram in Tools folder.
|
||||
// Only ILI9481 and ILI9341 based displays have been tested!
|
||||
|
||||
// Parallel bus is only supported for the STM32 and ESP32
|
||||
// Example below is for ESP32 Parallel interface with UNO displays
|
||||
|
||||
// Tell the library to use 8 bit parallel mode (otherwise SPI is assumed)
|
||||
//#define TFT_PARALLEL_8_BIT
|
||||
|
||||
// The ESP32 and TFT the pins used for testing are:
|
||||
//#define TFT_CS 33 // Chip select control pin (library pulls permanently low
|
||||
//#define TFT_DC 15 // Data Command control pin - must use a pin in the range 0-31
|
||||
//#define TFT_RST 32 // Reset pin, toggles on startup
|
||||
|
||||
//#define TFT_WR 4 // Write strobe control pin - must use a pin in the range 0-31
|
||||
//#define TFT_RD 2 // Read strobe control pin
|
||||
|
||||
//#define TFT_D0 12 // Must use pins in the range 0-31 for the data bus
|
||||
//#define TFT_D1 13 // so a single register write sets/clears all bits.
|
||||
//#define TFT_D2 26 // Pins can be randomly assigned, this does not affect
|
||||
//#define TFT_D3 25 // TFT screen update performance.
|
||||
//#define TFT_D4 17
|
||||
//#define TFT_D5 16
|
||||
//#define TFT_D6 27
|
||||
//#define TFT_D7 14
|
||||
|
||||
// ###### EDIT THE PINs BELOW TO SUIT YOUR STM32 SPI TFT SETUP ######
|
||||
|
||||
// The TFT can be connected to SPI port 1 or 2
|
||||
//#define TFT_SPI_PORT 1 // SPI port 1 maximum clock rate is 55MHz
|
||||
//#define TFT_MOSI PA7
|
||||
//#define TFT_MISO PA6
|
||||
//#define TFT_SCLK PA5
|
||||
|
||||
//#define TFT_SPI_PORT 2 // SPI port 2 maximum clock rate is 27MHz
|
||||
//#define TFT_MOSI PB15
|
||||
//#define TFT_MISO PB14
|
||||
//#define TFT_SCLK PB13
|
||||
|
||||
// Can use Ardiuno pin references, arbitrary allocation, TFT_eSPI controls chip select
|
||||
//#define TFT_CS D5 // Chip select control pin to TFT CS
|
||||
//#define TFT_DC D6 // Data Command control pin to TFT DC (may be labelled RS = Register Select)
|
||||
//#define TFT_RST D7 // Reset pin to TFT RST (or RESET)
|
||||
// OR alternatively, we can use STM32 port reference names PXnn
|
||||
//#define TFT_CS PE11 // Nucleo-F767ZI equivalent of D5
|
||||
//#define TFT_DC PE9 // Nucleo-F767ZI equivalent of D6
|
||||
//#define TFT_RST PF13 // Nucleo-F767ZI equivalent of D7
|
||||
|
||||
//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to processor reset
|
||||
// Use an Arduino pin for initial testing as connecting to processor reset
|
||||
// may not work (pulse too short at power up?)
|
||||
|
||||
// ##################################################################################
|
||||
//
|
||||
// Section 3. Define the fonts that are to be used here
|
||||
//
|
||||
// ##################################################################################
|
||||
|
||||
// Comment out the #defines below with // to stop that font being loaded
|
||||
// The ESP8366 and ESP32 have plenty of memory so commenting out fonts is not
|
||||
// normally necessary. If all fonts are loaded the extra FLASH space required is
|
||||
// about 17Kbytes. To save FLASH space only enable the fonts you need!
|
||||
|
||||
#define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH
|
||||
#define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters
|
||||
#define LOAD_FONT4 // Font 4. Medium 26 pixel high font, needs ~5848 bytes in FLASH, 96 characters
|
||||
#define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm
|
||||
#define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:-.
|
||||
#define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-.
|
||||
//#define LOAD_FONT8N // Font 8. Alternative to Font 8 above, slightly narrower, so 3 digits fit a 160 pixel TFT
|
||||
#define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts
|
||||
|
||||
// Comment out the #define below to stop the SPIFFS filing system and smooth font code being loaded
|
||||
// this will save ~20kbytes of FLASH
|
||||
#define SMOOTH_FONT
|
||||
|
||||
|
||||
// ##################################################################################
|
||||
//
|
||||
// Section 4. Other options
|
||||
//
|
||||
// ##################################################################################
|
||||
|
||||
// For RP2040 processor and SPI displays, uncomment the following line to use the PIO interface.
|
||||
//#define RP2040_PIO_SPI // Leave commented out to use standard RP2040 SPI port interface
|
||||
|
||||
// For RP2040 processor and 8 or 16 bit parallel displays:
|
||||
// The parallel interface write cycle period is derived from a division of the CPU clock
|
||||
// speed so scales with the processor clock. This means that the divider ratio may need
|
||||
// to be increased when overclocking. I may also need to be adjusted dependant on the
|
||||
// display controller type (ILI94341, HX8357C etc). If RP2040_PIO_CLK_DIV is not defined
|
||||
// the library will set default values which may not suit your display.
|
||||
// The display controller data sheet will specify the minimum write cycle period. The
|
||||
// controllers often work reliably for shorter periods, however if the period is too short
|
||||
// the display may not initialise or graphics will become corrupted.
|
||||
// PIO write cycle frequency = (CPU clock/(4 * RP2040_PIO_CLK_DIV))
|
||||
//#define RP2040_PIO_CLK_DIV 1 // 32ns write cycle at 125MHz CPU clock
|
||||
//#define RP2040_PIO_CLK_DIV 2 // 64ns write cycle at 125MHz CPU clock
|
||||
//#define RP2040_PIO_CLK_DIV 3 // 96ns write cycle at 125MHz CPU clock
|
||||
|
||||
// For the RP2040 processor define the SPI port channel used (default 0 if undefined)
|
||||
//#define TFT_SPI_PORT 1 // Set to 0 if SPI0 pins are used, or 1 if spi1 pins used
|
||||
|
||||
// For the STM32 processor define the SPI port channel used (default 1 if undefined)
|
||||
//#define TFT_SPI_PORT 2 // Set to 1 for SPI port 1, or 2 for SPI port 2
|
||||
|
||||
// Define the SPI clock frequency, this affects the graphics rendering speed. Too
|
||||
// fast and the TFT driver will not keep up and display corruption appears.
|
||||
// With an ILI9341 display 40MHz works OK, 80MHz sometimes fails
|
||||
// With a ST7735 display more than 27MHz may not work (spurious pixels and lines)
|
||||
// With an ILI9163 display 27 MHz works OK.
|
||||
|
||||
// #define SPI_FREQUENCY 1000000
|
||||
// #define SPI_FREQUENCY 5000000
|
||||
// #define SPI_FREQUENCY 10000000
|
||||
// #define SPI_FREQUENCY 20000000
|
||||
// #define SPI_FREQUENCY 27000000
|
||||
// #define SPI_FREQUENCY 40000000
|
||||
#define SPI_FREQUENCY 55000000 // STM32 SPI1 only (SPI2 maximum is 27MHz)
|
||||
// #define SPI_FREQUENCY 80000000
|
||||
|
||||
// Optional reduced SPI frequency for reading TFT
|
||||
#define SPI_READ_FREQUENCY 20000000
|
||||
|
||||
// The XPT2046 requires a lower SPI clock rate of 2.5MHz so we define that here:
|
||||
#define SPI_TOUCH_FREQUENCY 2500000
|
||||
|
||||
// The ESP32 has 2 free SPI ports i.e. VSPI and HSPI, the VSPI is the default.
|
||||
// If the VSPI port is in use and pins are not accessible (e.g. TTGO T-Beam)
|
||||
// then uncomment the following line:
|
||||
#define USE_HSPI_PORT
|
||||
|
||||
// Comment out the following #define if "SPI Transactions" do not need to be
|
||||
// supported. When commented out the code size will be smaller and sketches will
|
||||
// run slightly faster, so leave it commented out unless you need it!
|
||||
|
||||
// Transaction support is needed to work with SD library but not needed with TFT_SdFat
|
||||
// Transaction support is required if other SPI devices are connected.
|
||||
|
||||
// Transactions are automatically enabled by the library for an ESP32 (to use HAL mutex)
|
||||
// so changing it here has no effect
|
||||
|
||||
// #define SUPPORT_TRANSACTIONS
|
||||
|
After Width: | Height: | Size: 180 KiB |
@@ -0,0 +1,386 @@
|
||||
// USER DEFINED SETTINGS
|
||||
// Set driver type, fonts to be loaded, pins used and SPI control method etc
|
||||
//
|
||||
// See the User_Setup_Select.h file if you wish to be able to define multiple
|
||||
// setups and then easily select which setup file is used by the compiler.
|
||||
//
|
||||
// If this file is edited correctly then all the library example sketches should
|
||||
// run without the need to make any more changes for a particular hardware setup!
|
||||
// Note that some sketches are designed for a particular TFT pixel width/height
|
||||
|
||||
// User defined information reported by "Read_User_Setup" test & diagnostics example
|
||||
#define USER_SETUP_INFO "User_Setup USER DEFINED - ESP32-035"
|
||||
|
||||
// Define to disable all #warnings in library (can be put in User_Setup_Select.h)
|
||||
//#define DISABLE_ALL_LIBRARY_WARNINGS
|
||||
|
||||
// ##################################################################################
|
||||
//
|
||||
// Section 1. Call up the right driver file and any options for it
|
||||
//
|
||||
// ##################################################################################
|
||||
|
||||
// Define STM32 to invoke optimised processor support (only for STM32)
|
||||
//#define STM32
|
||||
|
||||
// Defining the STM32 board allows the library to optimise the performance
|
||||
// for UNO compatible "MCUfriend" style shields
|
||||
//#define NUCLEO_64_TFT
|
||||
//#define NUCLEO_144_TFT
|
||||
|
||||
// STM32 8 bit parallel only:
|
||||
// If STN32 Port A or B pins 0-7 are used for 8 bit parallel data bus bits 0-7
|
||||
// then this will improve rendering performance by a factor of ~8x
|
||||
//#define STM_PORTA_DATA_BUS
|
||||
//#define STM_PORTB_DATA_BUS
|
||||
|
||||
// Tell the library to use parallel mode (otherwise SPI is assumed)
|
||||
//#define TFT_PARALLEL_8_BIT
|
||||
//#defined TFT_PARALLEL_16_BIT // **** 16 bit parallel ONLY for RP2040 processor ****
|
||||
|
||||
// Display type - only define if RPi display
|
||||
//#define RPI_DISPLAY_TYPE // 20MHz maximum SPI
|
||||
|
||||
// Only define one driver, the other ones must be commented out
|
||||
//#define ILI9341_DRIVER // Generic driver for common displays
|
||||
//#define ILI9341_2_DRIVER // Alternative ILI9341 driver, see https://github.com/Bodmer/TFT_eSPI/issues/1172
|
||||
//#define ST7735_DRIVER // Define additional parameters below for this display
|
||||
//#define ILI9163_DRIVER // Define additional parameters below for this display
|
||||
//#define S6D02A1_DRIVER
|
||||
//#define RPI_ILI9486_DRIVER // 20MHz maximum SPI
|
||||
//#define HX8357D_DRIVER
|
||||
//#define ILI9481_DRIVER
|
||||
//#define ILI9486_DRIVER
|
||||
//#define ILI9488_DRIVER // WARNING: Do not connect ILI9488 display SDO to MISO if other devices share the SPI bus (TFT SDO does NOT tristate when CS is high)
|
||||
//#define ST7789_DRIVER // Full configuration option, define additional parameters below for this display
|
||||
//#define ST7789_2_DRIVER // Minimal configuration option, define additional parameters below for this display
|
||||
//#define R61581_DRIVER
|
||||
//#define RM68140_DRIVER
|
||||
#define ST7796_DRIVER
|
||||
//#define SSD1351_DRIVER
|
||||
//#define SSD1963_480_DRIVER
|
||||
//#define SSD1963_800_DRIVER
|
||||
//#define SSD1963_800ALT_DRIVER
|
||||
//#define ILI9225_DRIVER
|
||||
//#define GC9A01_DRIVER
|
||||
|
||||
// Some displays support SPI reads via the MISO pin, other displays have a single
|
||||
// bi-directional SDA pin and the library will try to read this via the MOSI line.
|
||||
// To use the SDA line for reading data from the TFT uncomment the following line:
|
||||
|
||||
// #define TFT_SDA_READ // This option is for ESP32 ONLY, tested with ST7789 and GC9A01 display only
|
||||
|
||||
// For ST7735, ST7789 and ILI9341 ONLY, define the colour order IF the blue and red are swapped on your display
|
||||
// Try ONE option at a time to find the correct colour order for your display
|
||||
|
||||
// #define TFT_RGB_ORDER TFT_RGB // Colour order Red-Green-Blue
|
||||
// #define TFT_RGB_ORDER TFT_BGR // Colour order Blue-Green-Red
|
||||
|
||||
// For M5Stack ESP32 module with integrated ILI9341 display ONLY, remove // in line below
|
||||
|
||||
// #define M5STACK
|
||||
|
||||
// For ST7789, ST7735, ILI9163 and GC9A01 ONLY, define the pixel width and height in portrait orientation
|
||||
// #define TFT_WIDTH 80
|
||||
// #define TFT_WIDTH 128
|
||||
// #define TFT_WIDTH 172 // ST7789 172 x 320
|
||||
// #define TFT_WIDTH 240 // ST7789 240 x 240 and 240 x 320
|
||||
#define TFT_WIDTH 320
|
||||
// #define TFT_HEIGHT 160
|
||||
// #define TFT_HEIGHT 128
|
||||
// #define TFT_HEIGHT 240 // ST7789 240 x 240
|
||||
// #define TFT_HEIGHT 320 // ST7789 240 x 320
|
||||
#define TFT_HEIGHT 480
|
||||
// #define TFT_HEIGHT 240 // GC9A01 240 x 240
|
||||
|
||||
// For ST7735 ONLY, define the type of display, originally this was based on the
|
||||
// colour of the tab on the screen protector film but this is not always true, so try
|
||||
// out the different options below if the screen does not display graphics correctly,
|
||||
// e.g. colours wrong, mirror images, or stray pixels at the edges.
|
||||
// Comment out ALL BUT ONE of these options for a ST7735 display driver, save this
|
||||
// this User_Setup file, then rebuild and upload the sketch to the board again:
|
||||
|
||||
// #define ST7735_INITB
|
||||
// #define ST7735_GREENTAB
|
||||
// #define ST7735_GREENTAB2
|
||||
// #define ST7735_GREENTAB3
|
||||
// #define ST7735_GREENTAB128 // For 128 x 128 display
|
||||
// #define ST7735_GREENTAB160x80 // For 160 x 80 display (BGR, inverted, 26 offset)
|
||||
// #define ST7735_ROBOTLCD // For some RobotLCD arduino shields (128x160, BGR, https://docs.arduino.cc/retired/getting-started-guides/TFT)
|
||||
// #define ST7735_REDTAB
|
||||
// #define ST7735_BLACKTAB
|
||||
// #define ST7735_REDTAB160x80 // For 160 x 80 display with 24 pixel offset
|
||||
|
||||
// If colours are inverted (white shows as black) then uncomment one of the next
|
||||
// 2 lines try both options, one of the options should correct the inversion.
|
||||
|
||||
// #define TFT_INVERSION_ON
|
||||
#define TFT_INVERSION_OFF
|
||||
|
||||
|
||||
// ##################################################################################
|
||||
//
|
||||
// Section 2. Define the pins that are used to interface with the display here
|
||||
//
|
||||
// ##################################################################################
|
||||
|
||||
// If a backlight control signal is available then define the TFT_BL pin in Section 2
|
||||
// below. The backlight will be turned ON when tft.begin() is called, but the library
|
||||
// needs to know if the LEDs are ON with the pin HIGH or LOW. If the LEDs are to be
|
||||
// driven with a PWM signal or turned OFF/ON then this must be handled by the user
|
||||
// sketch. e.g. with digitalWrite(TFT_BL, LOW);
|
||||
|
||||
#define TFT_BL 27 // LED back-light control pin
|
||||
#define TFT_BACKLIGHT_ON HIGH // Level to turn ON back-light (HIGH or LOW)
|
||||
|
||||
|
||||
|
||||
// We must use hardware SPI, a minimum of 3 GPIO pins is needed.
|
||||
// Typical setup for ESP8266 NodeMCU ESP-12 is :
|
||||
//
|
||||
// Display SDO/MISO to NodeMCU pin D6 (or leave disconnected if not reading TFT)
|
||||
// Display LED to NodeMCU pin VIN (or 5V, see below)
|
||||
// Display SCK to NodeMCU pin D5
|
||||
// Display SDI/MOSI to NodeMCU pin D7
|
||||
// Display DC (RS/AO)to NodeMCU pin D3
|
||||
// Display RESET to NodeMCU pin D4 (or RST, see below)
|
||||
// Display CS to NodeMCU pin D8 (or GND, see below)
|
||||
// Display GND to NodeMCU pin GND (0V)
|
||||
// Display VCC to NodeMCU 5V or 3.3V
|
||||
//
|
||||
// The TFT RESET pin can be connected to the NodeMCU RST pin or 3.3V to free up a control pin
|
||||
//
|
||||
// The DC (Data Command) pin may be labelled AO or RS (Register Select)
|
||||
//
|
||||
// With some displays such as the ILI9341 the TFT CS pin can be connected to GND if no more
|
||||
// SPI devices (e.g. an SD Card) are connected, in this case comment out the #define TFT_CS
|
||||
// line below so it is NOT defined. Other displays such at the ST7735 require the TFT CS pin
|
||||
// to be toggled during setup, so in these cases the TFT_CS line must be defined and connected.
|
||||
//
|
||||
// The NodeMCU D0 pin can be used for RST
|
||||
//
|
||||
//
|
||||
// Note: only some versions of the NodeMCU provide the USB 5V on the VIN pin
|
||||
// If 5V is not available at a pin you can use 3.3V but backlight brightness
|
||||
// will be lower.
|
||||
|
||||
|
||||
// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP8266 SETUP ######
|
||||
|
||||
// For NodeMCU - use pin numbers in the form PIN_Dx where Dx is the NodeMCU pin designation
|
||||
//#define TFT_CS PIN_D8 // Chip select control pin D8
|
||||
//#define TFT_DC PIN_D3 // Data Command control pin
|
||||
//#define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line)
|
||||
//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V
|
||||
|
||||
//#define TFT_BL PIN_D1 // LED back-light (only for ST7789 with backlight control pin)
|
||||
|
||||
//#define TOUCH_CS PIN_D2 // Chip select pin (T_CS) of touch screen
|
||||
|
||||
//#define TFT_WR PIN_D2 // Write strobe for modified Raspberry Pi TFT only
|
||||
|
||||
|
||||
// ###### FOR ESP8266 OVERLAP MODE EDIT THE PIN NUMBERS IN THE FOLLOWING LINES ######
|
||||
|
||||
// Overlap mode shares the ESP8266 FLASH SPI bus with the TFT so has a performance impact
|
||||
// but saves pins for other functions. It is best not to connect MISO as some displays
|
||||
// do not tristate that line when chip select is high!
|
||||
// Note: Only one SPI device can share the FLASH SPI lines, so a SPI touch controller
|
||||
// cannot be connected as well to the same SPI signals.
|
||||
// On NodeMCU 1.0 SD0=MISO, SD1=MOSI, CLK=SCLK to connect to TFT in overlap mode
|
||||
// On NodeMCU V3 S0 =MISO, S1 =MOSI, S2 =SCLK
|
||||
// In ESP8266 overlap mode the following must be defined
|
||||
|
||||
//#define TFT_SPI_OVERLAP
|
||||
|
||||
// In ESP8266 overlap mode the TFT chip select MUST connect to pin D3
|
||||
//#define TFT_CS PIN_D3
|
||||
//#define TFT_DC PIN_D5 // Data Command control pin
|
||||
//#define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line)
|
||||
//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V
|
||||
|
||||
|
||||
// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP32 SETUP ######
|
||||
|
||||
// For ESP32 Dev board (only tested with ILI9341 display)
|
||||
// The hardware SPI can be mapped to any pins
|
||||
|
||||
#define TFT_MISO 12
|
||||
#define TFT_MOSI 13
|
||||
#define TFT_SCLK 14
|
||||
#define TFT_CS 15 // Chip select control pin
|
||||
#define TFT_DC 2 // Data Command control pin
|
||||
//#define TFT_RST 4 // Reset pin (could connect to RST pin)
|
||||
#define TFT_RST -1 // Set TFT_RST to -1 if display RESET is connected to ESP32 board RST
|
||||
|
||||
// For ESP32 Dev board (only tested with GC9A01 display)
|
||||
// The hardware SPI can be mapped to any pins
|
||||
|
||||
//#define TFT_MOSI 15 // In some display driver board, it might be written as "SDA" and so on.
|
||||
//#define TFT_SCLK 14
|
||||
//#define TFT_CS 5 // Chip select control pin
|
||||
//#define TFT_DC 27 // Data Command control pin
|
||||
//#define TFT_RST 33 // Reset pin (could connect to Arduino RESET pin)
|
||||
//#define TFT_BL 22 // LED back-light
|
||||
|
||||
#define TOUCH_CS 33 // Chip select pin (T_CS) of touch screen
|
||||
|
||||
//#define TFT_WR 22 // Write strobe for modified Raspberry Pi TFT only
|
||||
|
||||
// For the M5Stack module use these #define lines
|
||||
//#define TFT_MISO 19
|
||||
//#define TFT_MOSI 23
|
||||
//#define TFT_SCLK 18
|
||||
//#define TFT_CS 14 // Chip select control pin
|
||||
//#define TFT_DC 27 // Data Command control pin
|
||||
//#define TFT_RST 33 // Reset pin (could connect to Arduino RESET pin)
|
||||
//#define TFT_BL 32 // LED back-light (required for M5Stack)
|
||||
|
||||
// ###### EDIT THE PINs BELOW TO SUIT YOUR ESP32 PARALLEL TFT SETUP ######
|
||||
|
||||
// The library supports 8 bit parallel TFTs with the ESP32, the pin
|
||||
// selection below is compatible with ESP32 boards in UNO format.
|
||||
// Wemos D32 boards need to be modified, see diagram in Tools folder.
|
||||
// Only ILI9481 and ILI9341 based displays have been tested!
|
||||
|
||||
// Parallel bus is only supported for the STM32 and ESP32
|
||||
// Example below is for ESP32 Parallel interface with UNO displays
|
||||
|
||||
// Tell the library to use 8 bit parallel mode (otherwise SPI is assumed)
|
||||
//#define TFT_PARALLEL_8_BIT
|
||||
|
||||
// The ESP32 and TFT the pins used for testing are:
|
||||
//#define TFT_CS 33 // Chip select control pin (library pulls permanently low
|
||||
//#define TFT_DC 15 // Data Command control pin - must use a pin in the range 0-31
|
||||
//#define TFT_RST 32 // Reset pin, toggles on startup
|
||||
|
||||
//#define TFT_WR 4 // Write strobe control pin - must use a pin in the range 0-31
|
||||
//#define TFT_RD 2 // Read strobe control pin
|
||||
|
||||
//#define TFT_D0 12 // Must use pins in the range 0-31 for the data bus
|
||||
//#define TFT_D1 13 // so a single register write sets/clears all bits.
|
||||
//#define TFT_D2 26 // Pins can be randomly assigned, this does not affect
|
||||
//#define TFT_D3 25 // TFT screen update performance.
|
||||
//#define TFT_D4 17
|
||||
//#define TFT_D5 16
|
||||
//#define TFT_D6 27
|
||||
//#define TFT_D7 14
|
||||
|
||||
// ###### EDIT THE PINs BELOW TO SUIT YOUR STM32 SPI TFT SETUP ######
|
||||
|
||||
// The TFT can be connected to SPI port 1 or 2
|
||||
//#define TFT_SPI_PORT 1 // SPI port 1 maximum clock rate is 55MHz
|
||||
//#define TFT_MOSI PA7
|
||||
//#define TFT_MISO PA6
|
||||
//#define TFT_SCLK PA5
|
||||
|
||||
//#define TFT_SPI_PORT 2 // SPI port 2 maximum clock rate is 27MHz
|
||||
//#define TFT_MOSI PB15
|
||||
//#define TFT_MISO PB14
|
||||
//#define TFT_SCLK PB13
|
||||
|
||||
// Can use Ardiuno pin references, arbitrary allocation, TFT_eSPI controls chip select
|
||||
//#define TFT_CS D5 // Chip select control pin to TFT CS
|
||||
//#define TFT_DC D6 // Data Command control pin to TFT DC (may be labelled RS = Register Select)
|
||||
//#define TFT_RST D7 // Reset pin to TFT RST (or RESET)
|
||||
// OR alternatively, we can use STM32 port reference names PXnn
|
||||
//#define TFT_CS PE11 // Nucleo-F767ZI equivalent of D5
|
||||
//#define TFT_DC PE9 // Nucleo-F767ZI equivalent of D6
|
||||
//#define TFT_RST PF13 // Nucleo-F767ZI equivalent of D7
|
||||
|
||||
//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to processor reset
|
||||
// Use an Arduino pin for initial testing as connecting to processor reset
|
||||
// may not work (pulse too short at power up?)
|
||||
|
||||
// ##################################################################################
|
||||
//
|
||||
// Section 3. Define the fonts that are to be used here
|
||||
//
|
||||
// ##################################################################################
|
||||
|
||||
// Comment out the #defines below with // to stop that font being loaded
|
||||
// The ESP8366 and ESP32 have plenty of memory so commenting out fonts is not
|
||||
// normally necessary. If all fonts are loaded the extra FLASH space required is
|
||||
// about 17Kbytes. To save FLASH space only enable the fonts you need!
|
||||
|
||||
#define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH
|
||||
#define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters
|
||||
#define LOAD_FONT4 // Font 4. Medium 26 pixel high font, needs ~5848 bytes in FLASH, 96 characters
|
||||
#define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm
|
||||
#define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:-.
|
||||
#define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-.
|
||||
//#define LOAD_FONT8N // Font 8. Alternative to Font 8 above, slightly narrower, so 3 digits fit a 160 pixel TFT
|
||||
#define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts
|
||||
|
||||
// Comment out the #define below to stop the SPIFFS filing system and smooth font code being loaded
|
||||
// this will save ~20kbytes of FLASH
|
||||
#define SMOOTH_FONT
|
||||
|
||||
|
||||
// ##################################################################################
|
||||
//
|
||||
// Section 4. Other options
|
||||
//
|
||||
// ##################################################################################
|
||||
|
||||
// For RP2040 processor and SPI displays, uncomment the following line to use the PIO interface.
|
||||
//#define RP2040_PIO_SPI // Leave commented out to use standard RP2040 SPI port interface
|
||||
|
||||
// For RP2040 processor and 8 or 16 bit parallel displays:
|
||||
// The parallel interface write cycle period is derived from a division of the CPU clock
|
||||
// speed so scales with the processor clock. This means that the divider ratio may need
|
||||
// to be increased when overclocking. I may also need to be adjusted dependant on the
|
||||
// display controller type (ILI94341, HX8357C etc). If RP2040_PIO_CLK_DIV is not defined
|
||||
// the library will set default values which may not suit your display.
|
||||
// The display controller data sheet will specify the minimum write cycle period. The
|
||||
// controllers often work reliably for shorter periods, however if the period is too short
|
||||
// the display may not initialise or graphics will become corrupted.
|
||||
// PIO write cycle frequency = (CPU clock/(4 * RP2040_PIO_CLK_DIV))
|
||||
//#define RP2040_PIO_CLK_DIV 1 // 32ns write cycle at 125MHz CPU clock
|
||||
//#define RP2040_PIO_CLK_DIV 2 // 64ns write cycle at 125MHz CPU clock
|
||||
//#define RP2040_PIO_CLK_DIV 3 // 96ns write cycle at 125MHz CPU clock
|
||||
|
||||
// For the RP2040 processor define the SPI port channel used (default 0 if undefined)
|
||||
//#define TFT_SPI_PORT 1 // Set to 0 if SPI0 pins are used, or 1 if spi1 pins used
|
||||
|
||||
// For the STM32 processor define the SPI port channel used (default 1 if undefined)
|
||||
//#define TFT_SPI_PORT 2 // Set to 1 for SPI port 1, or 2 for SPI port 2
|
||||
|
||||
// Define the SPI clock frequency, this affects the graphics rendering speed. Too
|
||||
// fast and the TFT driver will not keep up and display corruption appears.
|
||||
// With an ILI9341 display 40MHz works OK, 80MHz sometimes fails
|
||||
// With a ST7735 display more than 27MHz may not work (spurious pixels and lines)
|
||||
// With an ILI9163 display 27 MHz works OK.
|
||||
|
||||
// #define SPI_FREQUENCY 1000000
|
||||
// #define SPI_FREQUENCY 5000000
|
||||
// #define SPI_FREQUENCY 10000000
|
||||
// #define SPI_FREQUENCY 20000000
|
||||
// #define SPI_FREQUENCY 27000000
|
||||
// #define SPI_FREQUENCY 40000000
|
||||
// #define SPI_FREQUENCY 55000000 // STM32 SPI1 only (SPI2 maximum is 27MHz)
|
||||
#define SPI_FREQUENCY 65000000
|
||||
// #define SPI_FREQUENCY 80000000
|
||||
|
||||
// Optional reduced SPI frequency for reading TFT
|
||||
#define SPI_READ_FREQUENCY 20000000
|
||||
|
||||
// The XPT2046 requires a lower SPI clock rate of 2.5MHz so we define that here:
|
||||
#define SPI_TOUCH_FREQUENCY 2500000
|
||||
|
||||
// The ESP32 has 2 free SPI ports i.e. VSPI and HSPI, the VSPI is the default.
|
||||
// If the VSPI port is in use and pins are not accessible (e.g. TTGO T-Beam)
|
||||
// then uncomment the following line:
|
||||
#define USE_HSPI_PORT
|
||||
|
||||
// Comment out the following #define if "SPI Transactions" do not need to be
|
||||
// supported. When commented out the code size will be smaller and sketches will
|
||||
// run slightly faster, so leave it commented out unless you need it!
|
||||
|
||||
// Transaction support is needed to work with SD library but not needed with TFT_SdFat
|
||||
// Transaction support is required if other SPI devices are connected.
|
||||
|
||||
// Transactions are automatically enabled by the library for an ESP32 (to use HAL mutex)
|
||||
// so changing it here has no effect
|
||||
|
||||
// #define SUPPORT_TRANSACTIONS
|
||||
|
After Width: | Height: | Size: 136 KiB |
@@ -0,0 +1,383 @@
|
||||
// USER DEFINED SETTINGS
|
||||
// Set driver type, fonts to be loaded, pins used and SPI control method etc
|
||||
//
|
||||
// See the User_Setup_Select.h file if you wish to be able to define multiple
|
||||
// setups and then easily select which setup file is used by the compiler.
|
||||
//
|
||||
// If this file is edited correctly then all the library example sketches should
|
||||
// run without the need to make any more changes for a particular hardware setup!
|
||||
// Note that some sketches are designed for a particular TFT pixel width/height
|
||||
|
||||
// User defined information reported by "Read_User_Setup" test & diagnostics example
|
||||
#define USER_SETUP_INFO "User_Setup USER_DEFINED - ESP32-32E"
|
||||
|
||||
// Define to disable all #warnings in library (can be put in User_Setup_Select.h)
|
||||
//#define DISABLE_ALL_LIBRARY_WARNINGS
|
||||
|
||||
// ##################################################################################
|
||||
//
|
||||
// Section 1. Call up the right driver file and any options for it
|
||||
//
|
||||
// ##################################################################################
|
||||
|
||||
// Define STM32 to invoke optimised processor support (only for STM32)
|
||||
//#define STM32
|
||||
|
||||
// Defining the STM32 board allows the library to optimise the performance
|
||||
// for UNO compatible "MCUfriend" style shields
|
||||
//#define NUCLEO_64_TFT
|
||||
//#define NUCLEO_144_TFT
|
||||
|
||||
// STM32 8 bit parallel only:
|
||||
// If STN32 Port A or B pins 0-7 are used for 8 bit parallel data bus bits 0-7
|
||||
// then this will improve rendering performance by a factor of ~8x
|
||||
//#define STM_PORTA_DATA_BUS
|
||||
//#define STM_PORTB_DATA_BUS
|
||||
|
||||
// Tell the library to use parallel mode (otherwise SPI is assumed)
|
||||
//#define TFT_PARALLEL_8_BIT
|
||||
//#defined TFT_PARALLEL_16_BIT // **** 16 bit parallel ONLY for RP2040 processor ****
|
||||
|
||||
// Display type - only define if RPi display
|
||||
//#define RPI_DISPLAY_TYPE // 20MHz maximum SPI
|
||||
|
||||
// Only define one driver, the other ones must be commented out
|
||||
//#define ILI9341_DRIVER // Generic driver for common displays
|
||||
#define ILI9341_2_DRIVER // Alternative ILI9341 driver, see https://github.com/Bodmer/TFT_eSPI/issues/1172
|
||||
//#define ST7735_DRIVER // Define additional parameters below for this display
|
||||
//#define ILI9163_DRIVER // Define additional parameters below for this display
|
||||
//#define S6D02A1_DRIVER
|
||||
//#define RPI_ILI9486_DRIVER // 20MHz maximum SPI
|
||||
//#define HX8357D_DRIVER
|
||||
//#define ILI9481_DRIVER
|
||||
//#define ILI9486_DRIVER
|
||||
//#define ILI9488_DRIVER // WARNING: Do not connect ILI9488 display SDO to MISO if other devices share the SPI bus (TFT SDO does NOT tristate when CS is high)
|
||||
//#define ST7789_DRIVER // Full configuration option, define additional parameters below for this display
|
||||
//#define ST7789_2_DRIVER // Minimal configuration option, define additional parameters below for this display
|
||||
//#define R61581_DRIVER
|
||||
//#define RM68140_DRIVER
|
||||
//#define ST7796_DRIVER
|
||||
//#define SSD1351_DRIVER
|
||||
//#define SSD1963_480_DRIVER
|
||||
//#define SSD1963_800_DRIVER
|
||||
//#define SSD1963_800ALT_DRIVER
|
||||
//#define ILI9225_DRIVER
|
||||
//#define GC9A01_DRIVER
|
||||
|
||||
// Some displays support SPI reads via the MISO pin, other displays have a single
|
||||
// bi-directional SDA pin and the library will try to read this via the MOSI line.
|
||||
// To use the SDA line for reading data from the TFT uncomment the following line:
|
||||
|
||||
// #define TFT_SDA_READ // This option is for ESP32 ONLY, tested with ST7789 and GC9A01 display only
|
||||
|
||||
// For ST7735, ST7789 and ILI9341 ONLY, define the colour order IF the blue and red are swapped on your display
|
||||
// Try ONE option at a time to find the correct colour order for your display
|
||||
|
||||
// #define TFT_RGB_ORDER TFT_RGB // Colour order Red-Green-Blue
|
||||
// #define TFT_RGB_ORDER TFT_BGR // Colour order Blue-Green-Red
|
||||
|
||||
// For M5Stack ESP32 module with integrated ILI9341 display ONLY, remove // in line below
|
||||
|
||||
// #define M5STACK
|
||||
|
||||
// For ST7789, ST7735, ILI9163 and GC9A01 ONLY, define the pixel width and height in portrait orientation
|
||||
// #define TFT_WIDTH 80
|
||||
// #define TFT_WIDTH 128
|
||||
// #define TFT_WIDTH 172 // ST7789 172 x 320
|
||||
#define TFT_WIDTH 240 // ST7789 240 x 240 and 240 x 320
|
||||
// #define TFT_HEIGHT 160
|
||||
// #define TFT_HEIGHT 128
|
||||
// #define TFT_HEIGHT 240 // ST7789 240 x 240
|
||||
#define TFT_HEIGHT 320 // ST7789 240 x 320
|
||||
// #define TFT_HEIGHT 240 // GC9A01 240 x 240
|
||||
|
||||
// For ST7735 ONLY, define the type of display, originally this was based on the
|
||||
// colour of the tab on the screen protector film but this is not always true, so try
|
||||
// out the different options below if the screen does not display graphics correctly,
|
||||
// e.g. colours wrong, mirror images, or stray pixels at the edges.
|
||||
// Comment out ALL BUT ONE of these options for a ST7735 display driver, save this
|
||||
// this User_Setup file, then rebuild and upload the sketch to the board again:
|
||||
|
||||
// #define ST7735_INITB
|
||||
// #define ST7735_GREENTAB
|
||||
// #define ST7735_GREENTAB2
|
||||
// #define ST7735_GREENTAB3
|
||||
// #define ST7735_GREENTAB128 // For 128 x 128 display
|
||||
// #define ST7735_GREENTAB160x80 // For 160 x 80 display (BGR, inverted, 26 offset)
|
||||
// #define ST7735_ROBOTLCD // For some RobotLCD arduino shields (128x160, BGR, https://docs.arduino.cc/retired/getting-started-guides/TFT)
|
||||
// #define ST7735_REDTAB
|
||||
// #define ST7735_BLACKTAB
|
||||
// #define ST7735_REDTAB160x80 // For 160 x 80 display with 24 pixel offset
|
||||
|
||||
// If colours are inverted (white shows as black) then uncomment one of the next
|
||||
// 2 lines try both options, one of the options should correct the inversion.
|
||||
|
||||
// #define TFT_INVERSION_ON
|
||||
#define TFT_INVERSION_OFF
|
||||
|
||||
|
||||
// ##################################################################################
|
||||
//
|
||||
// Section 2. Define the pins that are used to interface with the display here
|
||||
//
|
||||
// ##################################################################################
|
||||
|
||||
// If a backlight control signal is available then define the TFT_BL pin in Section 2
|
||||
// below. The backlight will be turned ON when tft.begin() is called, but the library
|
||||
// needs to know if the LEDs are ON with the pin HIGH or LOW. If the LEDs are to be
|
||||
// driven with a PWM signal or turned OFF/ON then this must be handled by the user
|
||||
// sketch. e.g. with digitalWrite(TFT_BL, LOW);
|
||||
|
||||
#define TFT_BL 21 // LED back-light control pin
|
||||
#define TFT_BACKLIGHT_ON HIGH // Level to turn ON back-light (HIGH or LOW)
|
||||
|
||||
|
||||
|
||||
// We must use hardware SPI, a minimum of 3 GPIO pins is needed.
|
||||
// Typical setup for ESP8266 NodeMCU ESP-12 is :
|
||||
//
|
||||
// Display SDO/MISO to NodeMCU pin D6 (or leave disconnected if not reading TFT)
|
||||
// Display LED to NodeMCU pin VIN (or 5V, see below)
|
||||
// Display SCK to NodeMCU pin D5
|
||||
// Display SDI/MOSI to NodeMCU pin D7
|
||||
// Display DC (RS/AO)to NodeMCU pin D3
|
||||
// Display RESET to NodeMCU pin D4 (or RST, see below)
|
||||
// Display CS to NodeMCU pin D8 (or GND, see below)
|
||||
// Display GND to NodeMCU pin GND (0V)
|
||||
// Display VCC to NodeMCU 5V or 3.3V
|
||||
//
|
||||
// The TFT RESET pin can be connected to the NodeMCU RST pin or 3.3V to free up a control pin
|
||||
//
|
||||
// The DC (Data Command) pin may be labelled AO or RS (Register Select)
|
||||
//
|
||||
// With some displays such as the ILI9341 the TFT CS pin can be connected to GND if no more
|
||||
// SPI devices (e.g. an SD Card) are connected, in this case comment out the #define TFT_CS
|
||||
// line below so it is NOT defined. Other displays such at the ST7735 require the TFT CS pin
|
||||
// to be toggled during setup, so in these cases the TFT_CS line must be defined and connected.
|
||||
//
|
||||
// The NodeMCU D0 pin can be used for RST
|
||||
//
|
||||
//
|
||||
// Note: only some versions of the NodeMCU provide the USB 5V on the VIN pin
|
||||
// If 5V is not available at a pin you can use 3.3V but backlight brightness
|
||||
// will be lower.
|
||||
|
||||
|
||||
// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP8266 SETUP ######
|
||||
|
||||
// For NodeMCU - use pin numbers in the form PIN_Dx where Dx is the NodeMCU pin designation
|
||||
//#define TFT_CS PIN_D8 // Chip select control pin D8
|
||||
//#define TFT_DC PIN_D3 // Data Command control pin
|
||||
//#define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line)
|
||||
//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V
|
||||
|
||||
//#define TFT_BL PIN_D1 // LED back-light (only for ST7789 with backlight control pin)
|
||||
|
||||
//#define TOUCH_CS PIN_D2 // Chip select pin (T_CS) of touch screen
|
||||
|
||||
//#define TFT_WR PIN_D2 // Write strobe for modified Raspberry Pi TFT only
|
||||
|
||||
|
||||
// ###### FOR ESP8266 OVERLAP MODE EDIT THE PIN NUMBERS IN THE FOLLOWING LINES ######
|
||||
|
||||
// Overlap mode shares the ESP8266 FLASH SPI bus with the TFT so has a performance impact
|
||||
// but saves pins for other functions. It is best not to connect MISO as some displays
|
||||
// do not tristate that line when chip select is high!
|
||||
// Note: Only one SPI device can share the FLASH SPI lines, so a SPI touch controller
|
||||
// cannot be connected as well to the same SPI signals.
|
||||
// On NodeMCU 1.0 SD0=MISO, SD1=MOSI, CLK=SCLK to connect to TFT in overlap mode
|
||||
// On NodeMCU V3 S0 =MISO, S1 =MOSI, S2 =SCLK
|
||||
// In ESP8266 overlap mode the following must be defined
|
||||
|
||||
//#define TFT_SPI_OVERLAP
|
||||
|
||||
// In ESP8266 overlap mode the TFT chip select MUST connect to pin D3
|
||||
//#define TFT_CS PIN_D3
|
||||
//#define TFT_DC PIN_D5 // Data Command control pin
|
||||
//#define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line)
|
||||
//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V
|
||||
|
||||
|
||||
// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP32 SETUP ######
|
||||
|
||||
// For ESP32 Dev board (only tested with ILI9341 display)
|
||||
// The hardware SPI can be mapped to any pins
|
||||
|
||||
#define TFT_MISO 12
|
||||
#define TFT_MOSI 13
|
||||
#define TFT_SCLK 14
|
||||
#define TFT_CS 15 // Chip select control pin
|
||||
#define TFT_DC 2 // Data Command control pin
|
||||
//#define TFT_RST 4 // Reset pin (could connect to RST pin)
|
||||
#define TFT_RST -1 // Set TFT_RST to -1 if display RESET is connected to ESP32 board RST
|
||||
|
||||
// For ESP32 Dev board (only tested with GC9A01 display)
|
||||
// The hardware SPI can be mapped to any pins
|
||||
|
||||
//#define TFT_MOSI 15 // In some display driver board, it might be written as "SDA" and so on.
|
||||
//#define TFT_SCLK 14
|
||||
//#define TFT_CS 5 // Chip select control pin
|
||||
//#define TFT_DC 27 // Data Command control pin
|
||||
//#define TFT_RST 33 // Reset pin (could connect to Arduino RESET pin)
|
||||
//#define TFT_BL 22 // LED back-light
|
||||
|
||||
#define TOUCH_CS 33 // Chip select pin (T_CS) of touch screen
|
||||
|
||||
//#define TFT_WR 22 // Write strobe for modified Raspberry Pi TFT only
|
||||
|
||||
// For the M5Stack module use these #define lines
|
||||
//#define TFT_MISO 19
|
||||
//#define TFT_MOSI 23
|
||||
//#define TFT_SCLK 18
|
||||
//#define TFT_CS 14 // Chip select control pin
|
||||
//#define TFT_DC 27 // Data Command control pin
|
||||
//#define TFT_RST 33 // Reset pin (could connect to Arduino RESET pin)
|
||||
//#define TFT_BL 32 // LED back-light (required for M5Stack)
|
||||
|
||||
// ###### EDIT THE PINs BELOW TO SUIT YOUR ESP32 PARALLEL TFT SETUP ######
|
||||
|
||||
// The library supports 8 bit parallel TFTs with the ESP32, the pin
|
||||
// selection below is compatible with ESP32 boards in UNO format.
|
||||
// Wemos D32 boards need to be modified, see diagram in Tools folder.
|
||||
// Only ILI9481 and ILI9341 based displays have been tested!
|
||||
|
||||
// Parallel bus is only supported for the STM32 and ESP32
|
||||
// Example below is for ESP32 Parallel interface with UNO displays
|
||||
|
||||
// Tell the library to use 8 bit parallel mode (otherwise SPI is assumed)
|
||||
//#define TFT_PARALLEL_8_BIT
|
||||
|
||||
// The ESP32 and TFT the pins used for testing are:
|
||||
//#define TFT_CS 33 // Chip select control pin (library pulls permanently low
|
||||
//#define TFT_DC 15 // Data Command control pin - must use a pin in the range 0-31
|
||||
//#define TFT_RST 32 // Reset pin, toggles on startup
|
||||
|
||||
//#define TFT_WR 4 // Write strobe control pin - must use a pin in the range 0-31
|
||||
//#define TFT_RD 2 // Read strobe control pin
|
||||
|
||||
//#define TFT_D0 12 // Must use pins in the range 0-31 for the data bus
|
||||
//#define TFT_D1 13 // so a single register write sets/clears all bits.
|
||||
//#define TFT_D2 26 // Pins can be randomly assigned, this does not affect
|
||||
//#define TFT_D3 25 // TFT screen update performance.
|
||||
//#define TFT_D4 17
|
||||
//#define TFT_D5 16
|
||||
//#define TFT_D6 27
|
||||
//#define TFT_D7 14
|
||||
|
||||
// ###### EDIT THE PINs BELOW TO SUIT YOUR STM32 SPI TFT SETUP ######
|
||||
|
||||
// The TFT can be connected to SPI port 1 or 2
|
||||
//#define TFT_SPI_PORT 1 // SPI port 1 maximum clock rate is 55MHz
|
||||
//#define TFT_MOSI PA7
|
||||
//#define TFT_MISO PA6
|
||||
//#define TFT_SCLK PA5
|
||||
|
||||
//#define TFT_SPI_PORT 2 // SPI port 2 maximum clock rate is 27MHz
|
||||
//#define TFT_MOSI PB15
|
||||
//#define TFT_MISO PB14
|
||||
//#define TFT_SCLK PB13
|
||||
|
||||
// Can use Ardiuno pin references, arbitrary allocation, TFT_eSPI controls chip select
|
||||
//#define TFT_CS D5 // Chip select control pin to TFT CS
|
||||
//#define TFT_DC D6 // Data Command control pin to TFT DC (may be labelled RS = Register Select)
|
||||
//#define TFT_RST D7 // Reset pin to TFT RST (or RESET)
|
||||
// OR alternatively, we can use STM32 port reference names PXnn
|
||||
//#define TFT_CS PE11 // Nucleo-F767ZI equivalent of D5
|
||||
//#define TFT_DC PE9 // Nucleo-F767ZI equivalent of D6
|
||||
//#define TFT_RST PF13 // Nucleo-F767ZI equivalent of D7
|
||||
|
||||
//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to processor reset
|
||||
// Use an Arduino pin for initial testing as connecting to processor reset
|
||||
// may not work (pulse too short at power up?)
|
||||
|
||||
// ##################################################################################
|
||||
//
|
||||
// Section 3. Define the fonts that are to be used here
|
||||
//
|
||||
// ##################################################################################
|
||||
|
||||
// Comment out the #defines below with // to stop that font being loaded
|
||||
// The ESP8366 and ESP32 have plenty of memory so commenting out fonts is not
|
||||
// normally necessary. If all fonts are loaded the extra FLASH space required is
|
||||
// about 17Kbytes. To save FLASH space only enable the fonts you need!
|
||||
|
||||
#define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH
|
||||
#define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters
|
||||
#define LOAD_FONT4 // Font 4. Medium 26 pixel high font, needs ~5848 bytes in FLASH, 96 characters
|
||||
#define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm
|
||||
#define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:-.
|
||||
#define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-.
|
||||
//#define LOAD_FONT8N // Font 8. Alternative to Font 8 above, slightly narrower, so 3 digits fit a 160 pixel TFT
|
||||
#define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts
|
||||
|
||||
// Comment out the #define below to stop the SPIFFS filing system and smooth font code being loaded
|
||||
// this will save ~20kbytes of FLASH
|
||||
#define SMOOTH_FONT
|
||||
|
||||
|
||||
// ##################################################################################
|
||||
//
|
||||
// Section 4. Other options
|
||||
//
|
||||
// ##################################################################################
|
||||
|
||||
// For RP2040 processor and SPI displays, uncomment the following line to use the PIO interface.
|
||||
//#define RP2040_PIO_SPI // Leave commented out to use standard RP2040 SPI port interface
|
||||
|
||||
// For RP2040 processor and 8 or 16 bit parallel displays:
|
||||
// The parallel interface write cycle period is derived from a division of the CPU clock
|
||||
// speed so scales with the processor clock. This means that the divider ratio may need
|
||||
// to be increased when overclocking. I may also need to be adjusted dependant on the
|
||||
// display controller type (ILI94341, HX8357C etc). If RP2040_PIO_CLK_DIV is not defined
|
||||
// the library will set default values which may not suit your display.
|
||||
// The display controller data sheet will specify the minimum write cycle period. The
|
||||
// controllers often work reliably for shorter periods, however if the period is too short
|
||||
// the display may not initialise or graphics will become corrupted.
|
||||
// PIO write cycle frequency = (CPU clock/(4 * RP2040_PIO_CLK_DIV))
|
||||
//#define RP2040_PIO_CLK_DIV 1 // 32ns write cycle at 125MHz CPU clock
|
||||
//#define RP2040_PIO_CLK_DIV 2 // 64ns write cycle at 125MHz CPU clock
|
||||
//#define RP2040_PIO_CLK_DIV 3 // 96ns write cycle at 125MHz CPU clock
|
||||
|
||||
// For the RP2040 processor define the SPI port channel used (default 0 if undefined)
|
||||
//#define TFT_SPI_PORT 1 // Set to 0 if SPI0 pins are used, or 1 if spi1 pins used
|
||||
|
||||
// For the STM32 processor define the SPI port channel used (default 1 if undefined)
|
||||
//#define TFT_SPI_PORT 2 // Set to 1 for SPI port 1, or 2 for SPI port 2
|
||||
|
||||
// Define the SPI clock frequency, this affects the graphics rendering speed. Too
|
||||
// fast and the TFT driver will not keep up and display corruption appears.
|
||||
// With an ILI9341 display 40MHz works OK, 80MHz sometimes fails
|
||||
// With a ST7735 display more than 27MHz may not work (spurious pixels and lines)
|
||||
// With an ILI9163 display 27 MHz works OK.
|
||||
|
||||
// #define SPI_FREQUENCY 1000000
|
||||
// #define SPI_FREQUENCY 5000000
|
||||
// #define SPI_FREQUENCY 10000000
|
||||
// #define SPI_FREQUENCY 20000000
|
||||
// #define SPI_FREQUENCY 27000000
|
||||
// #define SPI_FREQUENCY 40000000
|
||||
#define SPI_FREQUENCY 55000000 // STM32 SPI1 only (SPI2 maximum is 27MHz)
|
||||
// #define SPI_FREQUENCY 80000000
|
||||
|
||||
// Optional reduced SPI frequency for reading TFT
|
||||
#define SPI_READ_FREQUENCY 20000000
|
||||
|
||||
// The XPT2046 requires a lower SPI clock rate of 2.5MHz so we define that here:
|
||||
#define SPI_TOUCH_FREQUENCY 2500000
|
||||
|
||||
// The ESP32 has 2 free SPI ports i.e. VSPI and HSPI, the VSPI is the default.
|
||||
// If the VSPI port is in use and pins are not accessible (e.g. TTGO T-Beam)
|
||||
// then uncomment the following line:
|
||||
#define USE_HSPI_PORT
|
||||
|
||||
// Comment out the following #define if "SPI Transactions" do not need to be
|
||||
// supported. When commented out the code size will be smaller and sketches will
|
||||
// run slightly faster, so leave it commented out unless you need it!
|
||||
|
||||
// Transaction support is needed to work with SD library but not needed with TFT_SdFat
|
||||
// Transaction support is required if other SPI devices are connected.
|
||||
|
||||
// Transactions are automatically enabled by the library for an ESP32 (to use HAL mutex)
|
||||
// so changing it here has no effect
|
||||
|
||||
// #define SUPPORT_TRANSACTIONS
|
||||
127
PacoMouseCYD/doc/options/TFT_eSPI_User_Defined/README.md
Normal file
@@ -0,0 +1,127 @@
|
||||
# CYD_USER_DEFINED
|
||||
|
||||
|
||||
> You need to modify the User_Setup.h file according to your board and copy it into the TFT_eSPI library folder.
|
||||
In the program's config.h file, select CYD_USER_DEFINED as the hardware and modify the USER DEFINED HARDWARE section according to your board.
|
||||
|
||||
---
|
||||
|
||||
> Tiene que modificar el archivo User_Setup.h de acuerdo a su placa y copiarlo en la carpeta de la biblioteca TFT_eSPI.
|
||||
En el archivo config.h del programa seleccionar CYD_USER_DEFINED como hardware y modifique la seccion USER DEFINED HARDWARE de acuerdo a su placa.
|
||||
|
||||
---
|
||||
|
||||
> Heu de modificar el fitxer User_Setup.h segons la vostra placa i copiar-lo a la carpeta de la biblioteca TFT_eSPI.
|
||||
Al fitxer config.h del programa, seleccioneu CYD_USER_DEFINED com a hardware i modifiqueu la secció USER DEFINED HARDWARE segons la vostra placa.
|
||||
|
||||
---
|
||||
|
||||
> Sie müssen die Datei User_Setup.h entsprechend Ihrer Platine ändern und in den TFT_eSPI-Bibliotheksordner kopieren.
|
||||
Wählen Sie in der Datei config.h des Programms CYD_USER_DEFINED als Hardware aus und passen Sie den Abschnitt USER DEFINED HARDWARE entsprechend Ihrem Board an.
|
||||
|
||||
---
|
||||
|
||||
<br>
|
||||
<br>
|
||||
|
||||
|
||||
# config.h
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////<br>
|
||||
// ***** USER OPTIONS *****<br>
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
// Seleccione la version hardware del CYD (Cheap Yellow Display) - Select the hardware version of CYD (Cheap Yellow Display): CYD_TFT_28 / CYD_TFT_24 / CYD_TFT_32 / CYD_USER_DEFINED<br>
|
||||
// Use el archivo User_Setup.h correcto para la libreria TFT_eSPI - Use the correct User_Setup.h file for library TFT_eSPI
|
||||
|
||||
#define CYD_HW_VERSION CYD_USER_DEFINED<br>
|
||||
|
||||
|
||||
## Examples
|
||||
|
||||
////////////////////////////////////////////////////////////<br>
|
||||
// ***** USER DEFINED HARDWARE EXAMPLES *****<br>
|
||||
////////////////////////////////////////////////////////////<br>
|
||||
|
||||
### ESP32-32E
|
||||
---
|
||||
|
||||
|
||||
|
||||
//================================================================================================ <br>
|
||||
// CYD 240x320 2.8" - ESP32-32E (using RGB LED pins for encoder connection)<br>
|
||||
//================================================================================================ <br>
|
||||
|
||||
// Seleccione el modo de acceso al chip XPT2046 - Select XPT2046 chip access mode : MODE_SPI / MODE_BITBANG<br>
|
||||
#define XPT_MODE MODE_BITBANG<br>
|
||||
|
||||
// Seleccione rotacion de la pantalla tactil - Select Touchscreen rotation: 0 / 1 / 2 / 3<br>
|
||||
#define XPT_ROTATION 0<br>
|
||||
|
||||
// Touchscreen <br>
|
||||
#define XPT2046_IRQ 36 // T_IRQ<br>
|
||||
#define XPT2046_MOSI 32 // T_DIN<br>
|
||||
#define XPT2046_MISO 39 // T_OUT<br>
|
||||
#define XPT2046_CLK 25 // T_CLK<br>
|
||||
#define XPT2046_CS 33 // T_CS<br>
|
||||
|
||||
// Seleccione si usa el LED RGB - Select if use the RGB LED: PRESENT / UNUSED<br>
|
||||
#define USE_RGB_LED UNUSED<br>
|
||||
|
||||
//RGB LED Pins<br>
|
||||
#define RGB_LED_R 22<br>
|
||||
#define RGB_LED_G 16<br>
|
||||
#define RGB_LED_B 17<br>
|
||||
|
||||
//SD Pins<br>
|
||||
#define SD_CS 5<br>
|
||||
|
||||
// Encoder Pins<br>
|
||||
#define ENCODER_A 16<br>
|
||||
#define ENCODER_B 17<br>
|
||||
#define ENCODER_SW 22 <br>
|
||||
|
||||
|
||||
<br>
|
||||
|
||||
### ESP32-035
|
||||
---
|
||||
//================================================================================================<br>
|
||||
// CYD 320x480 3.5" - ESP32-035<br>
|
||||
//================================================================================================<br>
|
||||
|
||||
// Seleccione el modo de acceso al chip XPT2046 - Select XPT2046 chip access mode : MODE_SPI / MODE_BITBANG<br>
|
||||
#define XPT_MODE MODE_SPI<br>
|
||||
|
||||
// Seleccione rotacion de la pantalla tactil - Select Touchscreen rotation: 0 / 1 / 2 / 3<br>
|
||||
#define XPT_ROTATION 3<br>
|
||||
|
||||
// Touchscreen <br>
|
||||
#define XPT2046_IRQ 36 // T_IRQ<br>
|
||||
#define XPT2046_MOSI 13 // T_DIN<br>
|
||||
#define XPT2046_MISO 12 // T_OUT<br>
|
||||
#define XPT2046_CLK 14 // T_CLK<br>
|
||||
#define XPT2046_CS 33 // T_CS<br>
|
||||
|
||||
// Seleccione si usa el LED RGB - Select if use the RGB LED: PRESENT / UNUSED<br>
|
||||
#define USE_RGB_LED PRESENT <br>
|
||||
|
||||
//RGB LED Pins<br>
|
||||
#define RGB_LED_R 4<br>
|
||||
#define RGB_LED_G 17<br>
|
||||
#define RGB_LED_B 16<br>
|
||||
|
||||
//SD Pins<br>
|
||||
#define SD_CS 5<br>
|
||||
|
||||
// Encoder Pins<br>
|
||||
#define ENCODER_A 22<br>
|
||||
#define ENCODER_B 21<br>
|
||||
#define ENCODER_SW 35<br>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
383
PacoMouseCYD/doc/options/TFT_eSPI_User_Defined/User_Setup.h
Normal file
@@ -0,0 +1,383 @@
|
||||
// USER DEFINED SETTINGS
|
||||
// Set driver type, fonts to be loaded, pins used and SPI control method etc
|
||||
//
|
||||
// See the User_Setup_Select.h file if you wish to be able to define multiple
|
||||
// setups and then easily select which setup file is used by the compiler.
|
||||
//
|
||||
// If this file is edited correctly then all the library example sketches should
|
||||
// run without the need to make any more changes for a particular hardware setup!
|
||||
// Note that some sketches are designed for a particular TFT pixel width/height
|
||||
|
||||
// User defined information reported by "Read_User_Setup" test & diagnostics example
|
||||
#define USER_SETUP_INFO "User_Setup USER DEFINED"
|
||||
|
||||
// Define to disable all #warnings in library (can be put in User_Setup_Select.h)
|
||||
//#define DISABLE_ALL_LIBRARY_WARNINGS
|
||||
|
||||
// ##################################################################################
|
||||
//
|
||||
// Section 1. Call up the right driver file and any options for it
|
||||
//
|
||||
// ##################################################################################
|
||||
|
||||
// Define STM32 to invoke optimised processor support (only for STM32)
|
||||
//#define STM32
|
||||
|
||||
// Defining the STM32 board allows the library to optimise the performance
|
||||
// for UNO compatible "MCUfriend" style shields
|
||||
//#define NUCLEO_64_TFT
|
||||
//#define NUCLEO_144_TFT
|
||||
|
||||
// STM32 8 bit parallel only:
|
||||
// If STN32 Port A or B pins 0-7 are used for 8 bit parallel data bus bits 0-7
|
||||
// then this will improve rendering performance by a factor of ~8x
|
||||
//#define STM_PORTA_DATA_BUS
|
||||
//#define STM_PORTB_DATA_BUS
|
||||
|
||||
// Tell the library to use parallel mode (otherwise SPI is assumed)
|
||||
//#define TFT_PARALLEL_8_BIT
|
||||
//#defined TFT_PARALLEL_16_BIT // **** 16 bit parallel ONLY for RP2040 processor ****
|
||||
|
||||
// Display type - only define if RPi display
|
||||
//#define RPI_DISPLAY_TYPE // 20MHz maximum SPI
|
||||
|
||||
// Only define one driver, the other ones must be commented out
|
||||
//#define ILI9341_DRIVER // Generic driver for common displays
|
||||
#define ILI9341_2_DRIVER // Alternative ILI9341 driver, see https://github.com/Bodmer/TFT_eSPI/issues/1172
|
||||
//#define ST7735_DRIVER // Define additional parameters below for this display
|
||||
//#define ILI9163_DRIVER // Define additional parameters below for this display
|
||||
//#define S6D02A1_DRIVER
|
||||
//#define RPI_ILI9486_DRIVER // 20MHz maximum SPI
|
||||
//#define HX8357D_DRIVER
|
||||
//#define ILI9481_DRIVER
|
||||
//#define ILI9486_DRIVER
|
||||
//#define ILI9488_DRIVER // WARNING: Do not connect ILI9488 display SDO to MISO if other devices share the SPI bus (TFT SDO does NOT tristate when CS is high)
|
||||
//#define ST7789_DRIVER // Full configuration option, define additional parameters below for this display
|
||||
//#define ST7789_2_DRIVER // Minimal configuration option, define additional parameters below for this display
|
||||
//#define R61581_DRIVER
|
||||
//#define RM68140_DRIVER
|
||||
//#define ST7796_DRIVER
|
||||
//#define SSD1351_DRIVER
|
||||
//#define SSD1963_480_DRIVER
|
||||
//#define SSD1963_800_DRIVER
|
||||
//#define SSD1963_800ALT_DRIVER
|
||||
//#define ILI9225_DRIVER
|
||||
//#define GC9A01_DRIVER
|
||||
|
||||
// Some displays support SPI reads via the MISO pin, other displays have a single
|
||||
// bi-directional SDA pin and the library will try to read this via the MOSI line.
|
||||
// To use the SDA line for reading data from the TFT uncomment the following line:
|
||||
|
||||
// #define TFT_SDA_READ // This option is for ESP32 ONLY, tested with ST7789 and GC9A01 display only
|
||||
|
||||
// For ST7735, ST7789 and ILI9341 ONLY, define the colour order IF the blue and red are swapped on your display
|
||||
// Try ONE option at a time to find the correct colour order for your display
|
||||
|
||||
// #define TFT_RGB_ORDER TFT_RGB // Colour order Red-Green-Blue
|
||||
// #define TFT_RGB_ORDER TFT_BGR // Colour order Blue-Green-Red
|
||||
|
||||
// For M5Stack ESP32 module with integrated ILI9341 display ONLY, remove // in line below
|
||||
|
||||
// #define M5STACK
|
||||
|
||||
// For ST7789, ST7735, ILI9163 and GC9A01 ONLY, define the pixel width and height in portrait orientation
|
||||
// #define TFT_WIDTH 80
|
||||
// #define TFT_WIDTH 128
|
||||
// #define TFT_WIDTH 172 // ST7789 172 x 320
|
||||
#define TFT_WIDTH 240 // ST7789 240 x 240 and 240 x 320
|
||||
// #define TFT_HEIGHT 160
|
||||
// #define TFT_HEIGHT 128
|
||||
// #define TFT_HEIGHT 240 // ST7789 240 x 240
|
||||
#define TFT_HEIGHT 320 // ST7789 240 x 320
|
||||
// #define TFT_HEIGHT 240 // GC9A01 240 x 240
|
||||
|
||||
// For ST7735 ONLY, define the type of display, originally this was based on the
|
||||
// colour of the tab on the screen protector film but this is not always true, so try
|
||||
// out the different options below if the screen does not display graphics correctly,
|
||||
// e.g. colours wrong, mirror images, or stray pixels at the edges.
|
||||
// Comment out ALL BUT ONE of these options for a ST7735 display driver, save this
|
||||
// this User_Setup file, then rebuild and upload the sketch to the board again:
|
||||
|
||||
// #define ST7735_INITB
|
||||
// #define ST7735_GREENTAB
|
||||
// #define ST7735_GREENTAB2
|
||||
// #define ST7735_GREENTAB3
|
||||
// #define ST7735_GREENTAB128 // For 128 x 128 display
|
||||
// #define ST7735_GREENTAB160x80 // For 160 x 80 display (BGR, inverted, 26 offset)
|
||||
// #define ST7735_ROBOTLCD // For some RobotLCD arduino shields (128x160, BGR, https://docs.arduino.cc/retired/getting-started-guides/TFT)
|
||||
// #define ST7735_REDTAB
|
||||
// #define ST7735_BLACKTAB
|
||||
// #define ST7735_REDTAB160x80 // For 160 x 80 display with 24 pixel offset
|
||||
|
||||
// If colours are inverted (white shows as black) then uncomment one of the next
|
||||
// 2 lines try both options, one of the options should correct the inversion.
|
||||
|
||||
#define TFT_INVERSION_ON
|
||||
// #define TFT_INVERSION_OFF
|
||||
|
||||
|
||||
// ##################################################################################
|
||||
//
|
||||
// Section 2. Define the pins that are used to interface with the display here
|
||||
//
|
||||
// ##################################################################################
|
||||
|
||||
// If a backlight control signal is available then define the TFT_BL pin in Section 2
|
||||
// below. The backlight will be turned ON when tft.begin() is called, but the library
|
||||
// needs to know if the LEDs are ON with the pin HIGH or LOW. If the LEDs are to be
|
||||
// driven with a PWM signal or turned OFF/ON then this must be handled by the user
|
||||
// sketch. e.g. with digitalWrite(TFT_BL, LOW);
|
||||
|
||||
#define TFT_BL 21 // LED back-light control pin
|
||||
#define TFT_BACKLIGHT_ON HIGH // Level to turn ON back-light (HIGH or LOW)
|
||||
|
||||
|
||||
|
||||
// We must use hardware SPI, a minimum of 3 GPIO pins is needed.
|
||||
// Typical setup for ESP8266 NodeMCU ESP-12 is :
|
||||
//
|
||||
// Display SDO/MISO to NodeMCU pin D6 (or leave disconnected if not reading TFT)
|
||||
// Display LED to NodeMCU pin VIN (or 5V, see below)
|
||||
// Display SCK to NodeMCU pin D5
|
||||
// Display SDI/MOSI to NodeMCU pin D7
|
||||
// Display DC (RS/AO)to NodeMCU pin D3
|
||||
// Display RESET to NodeMCU pin D4 (or RST, see below)
|
||||
// Display CS to NodeMCU pin D8 (or GND, see below)
|
||||
// Display GND to NodeMCU pin GND (0V)
|
||||
// Display VCC to NodeMCU 5V or 3.3V
|
||||
//
|
||||
// The TFT RESET pin can be connected to the NodeMCU RST pin or 3.3V to free up a control pin
|
||||
//
|
||||
// The DC (Data Command) pin may be labelled AO or RS (Register Select)
|
||||
//
|
||||
// With some displays such as the ILI9341 the TFT CS pin can be connected to GND if no more
|
||||
// SPI devices (e.g. an SD Card) are connected, in this case comment out the #define TFT_CS
|
||||
// line below so it is NOT defined. Other displays such at the ST7735 require the TFT CS pin
|
||||
// to be toggled during setup, so in these cases the TFT_CS line must be defined and connected.
|
||||
//
|
||||
// The NodeMCU D0 pin can be used for RST
|
||||
//
|
||||
//
|
||||
// Note: only some versions of the NodeMCU provide the USB 5V on the VIN pin
|
||||
// If 5V is not available at a pin you can use 3.3V but backlight brightness
|
||||
// will be lower.
|
||||
|
||||
|
||||
// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP8266 SETUP ######
|
||||
|
||||
// For NodeMCU - use pin numbers in the form PIN_Dx where Dx is the NodeMCU pin designation
|
||||
//#define TFT_CS PIN_D8 // Chip select control pin D8
|
||||
//#define TFT_DC PIN_D3 // Data Command control pin
|
||||
//#define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line)
|
||||
//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V
|
||||
|
||||
//#define TFT_BL PIN_D1 // LED back-light (only for ST7789 with backlight control pin)
|
||||
|
||||
//#define TOUCH_CS PIN_D2 // Chip select pin (T_CS) of touch screen
|
||||
|
||||
//#define TFT_WR PIN_D2 // Write strobe for modified Raspberry Pi TFT only
|
||||
|
||||
|
||||
// ###### FOR ESP8266 OVERLAP MODE EDIT THE PIN NUMBERS IN THE FOLLOWING LINES ######
|
||||
|
||||
// Overlap mode shares the ESP8266 FLASH SPI bus with the TFT so has a performance impact
|
||||
// but saves pins for other functions. It is best not to connect MISO as some displays
|
||||
// do not tristate that line when chip select is high!
|
||||
// Note: Only one SPI device can share the FLASH SPI lines, so a SPI touch controller
|
||||
// cannot be connected as well to the same SPI signals.
|
||||
// On NodeMCU 1.0 SD0=MISO, SD1=MOSI, CLK=SCLK to connect to TFT in overlap mode
|
||||
// On NodeMCU V3 S0 =MISO, S1 =MOSI, S2 =SCLK
|
||||
// In ESP8266 overlap mode the following must be defined
|
||||
|
||||
//#define TFT_SPI_OVERLAP
|
||||
|
||||
// In ESP8266 overlap mode the TFT chip select MUST connect to pin D3
|
||||
//#define TFT_CS PIN_D3
|
||||
//#define TFT_DC PIN_D5 // Data Command control pin
|
||||
//#define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line)
|
||||
//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V
|
||||
|
||||
|
||||
// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP32 SETUP ######
|
||||
|
||||
// For ESP32 Dev board (only tested with ILI9341 display)
|
||||
// The hardware SPI can be mapped to any pins
|
||||
|
||||
#define TFT_MISO 12
|
||||
#define TFT_MOSI 13
|
||||
#define TFT_SCLK 14
|
||||
#define TFT_CS 15 // Chip select control pin
|
||||
#define TFT_DC 2 // Data Command control pin
|
||||
//#define TFT_RST 4 // Reset pin (could connect to RST pin)
|
||||
#define TFT_RST -1 // Set TFT_RST to -1 if display RESET is connected to ESP32 board RST
|
||||
|
||||
// For ESP32 Dev board (only tested with GC9A01 display)
|
||||
// The hardware SPI can be mapped to any pins
|
||||
|
||||
//#define TFT_MOSI 15 // In some display driver board, it might be written as "SDA" and so on.
|
||||
//#define TFT_SCLK 14
|
||||
//#define TFT_CS 5 // Chip select control pin
|
||||
//#define TFT_DC 27 // Data Command control pin
|
||||
//#define TFT_RST 33 // Reset pin (could connect to Arduino RESET pin)
|
||||
//#define TFT_BL 22 // LED back-light
|
||||
|
||||
#define TOUCH_CS 33 // Chip select pin (T_CS) of touch screen
|
||||
|
||||
//#define TFT_WR 22 // Write strobe for modified Raspberry Pi TFT only
|
||||
|
||||
// For the M5Stack module use these #define lines
|
||||
//#define TFT_MISO 19
|
||||
//#define TFT_MOSI 23
|
||||
//#define TFT_SCLK 18
|
||||
//#define TFT_CS 14 // Chip select control pin
|
||||
//#define TFT_DC 27 // Data Command control pin
|
||||
//#define TFT_RST 33 // Reset pin (could connect to Arduino RESET pin)
|
||||
//#define TFT_BL 32 // LED back-light (required for M5Stack)
|
||||
|
||||
// ###### EDIT THE PINs BELOW TO SUIT YOUR ESP32 PARALLEL TFT SETUP ######
|
||||
|
||||
// The library supports 8 bit parallel TFTs with the ESP32, the pin
|
||||
// selection below is compatible with ESP32 boards in UNO format.
|
||||
// Wemos D32 boards need to be modified, see diagram in Tools folder.
|
||||
// Only ILI9481 and ILI9341 based displays have been tested!
|
||||
|
||||
// Parallel bus is only supported for the STM32 and ESP32
|
||||
// Example below is for ESP32 Parallel interface with UNO displays
|
||||
|
||||
// Tell the library to use 8 bit parallel mode (otherwise SPI is assumed)
|
||||
//#define TFT_PARALLEL_8_BIT
|
||||
|
||||
// The ESP32 and TFT the pins used for testing are:
|
||||
//#define TFT_CS 33 // Chip select control pin (library pulls permanently low
|
||||
//#define TFT_DC 15 // Data Command control pin - must use a pin in the range 0-31
|
||||
//#define TFT_RST 32 // Reset pin, toggles on startup
|
||||
|
||||
//#define TFT_WR 4 // Write strobe control pin - must use a pin in the range 0-31
|
||||
//#define TFT_RD 2 // Read strobe control pin
|
||||
|
||||
//#define TFT_D0 12 // Must use pins in the range 0-31 for the data bus
|
||||
//#define TFT_D1 13 // so a single register write sets/clears all bits.
|
||||
//#define TFT_D2 26 // Pins can be randomly assigned, this does not affect
|
||||
//#define TFT_D3 25 // TFT screen update performance.
|
||||
//#define TFT_D4 17
|
||||
//#define TFT_D5 16
|
||||
//#define TFT_D6 27
|
||||
//#define TFT_D7 14
|
||||
|
||||
// ###### EDIT THE PINs BELOW TO SUIT YOUR STM32 SPI TFT SETUP ######
|
||||
|
||||
// The TFT can be connected to SPI port 1 or 2
|
||||
//#define TFT_SPI_PORT 1 // SPI port 1 maximum clock rate is 55MHz
|
||||
//#define TFT_MOSI PA7
|
||||
//#define TFT_MISO PA6
|
||||
//#define TFT_SCLK PA5
|
||||
|
||||
//#define TFT_SPI_PORT 2 // SPI port 2 maximum clock rate is 27MHz
|
||||
//#define TFT_MOSI PB15
|
||||
//#define TFT_MISO PB14
|
||||
//#define TFT_SCLK PB13
|
||||
|
||||
// Can use Ardiuno pin references, arbitrary allocation, TFT_eSPI controls chip select
|
||||
//#define TFT_CS D5 // Chip select control pin to TFT CS
|
||||
//#define TFT_DC D6 // Data Command control pin to TFT DC (may be labelled RS = Register Select)
|
||||
//#define TFT_RST D7 // Reset pin to TFT RST (or RESET)
|
||||
// OR alternatively, we can use STM32 port reference names PXnn
|
||||
//#define TFT_CS PE11 // Nucleo-F767ZI equivalent of D5
|
||||
//#define TFT_DC PE9 // Nucleo-F767ZI equivalent of D6
|
||||
//#define TFT_RST PF13 // Nucleo-F767ZI equivalent of D7
|
||||
|
||||
//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to processor reset
|
||||
// Use an Arduino pin for initial testing as connecting to processor reset
|
||||
// may not work (pulse too short at power up?)
|
||||
|
||||
// ##################################################################################
|
||||
//
|
||||
// Section 3. Define the fonts that are to be used here
|
||||
//
|
||||
// ##################################################################################
|
||||
|
||||
// Comment out the #defines below with // to stop that font being loaded
|
||||
// The ESP8366 and ESP32 have plenty of memory so commenting out fonts is not
|
||||
// normally necessary. If all fonts are loaded the extra FLASH space required is
|
||||
// about 17Kbytes. To save FLASH space only enable the fonts you need!
|
||||
|
||||
#define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH
|
||||
#define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters
|
||||
#define LOAD_FONT4 // Font 4. Medium 26 pixel high font, needs ~5848 bytes in FLASH, 96 characters
|
||||
#define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm
|
||||
#define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:-.
|
||||
#define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-.
|
||||
//#define LOAD_FONT8N // Font 8. Alternative to Font 8 above, slightly narrower, so 3 digits fit a 160 pixel TFT
|
||||
#define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts
|
||||
|
||||
// Comment out the #define below to stop the SPIFFS filing system and smooth font code being loaded
|
||||
// this will save ~20kbytes of FLASH
|
||||
#define SMOOTH_FONT
|
||||
|
||||
|
||||
// ##################################################################################
|
||||
//
|
||||
// Section 4. Other options
|
||||
//
|
||||
// ##################################################################################
|
||||
|
||||
// For RP2040 processor and SPI displays, uncomment the following line to use the PIO interface.
|
||||
//#define RP2040_PIO_SPI // Leave commented out to use standard RP2040 SPI port interface
|
||||
|
||||
// For RP2040 processor and 8 or 16 bit parallel displays:
|
||||
// The parallel interface write cycle period is derived from a division of the CPU clock
|
||||
// speed so scales with the processor clock. This means that the divider ratio may need
|
||||
// to be increased when overclocking. I may also need to be adjusted dependant on the
|
||||
// display controller type (ILI94341, HX8357C etc). If RP2040_PIO_CLK_DIV is not defined
|
||||
// the library will set default values which may not suit your display.
|
||||
// The display controller data sheet will specify the minimum write cycle period. The
|
||||
// controllers often work reliably for shorter periods, however if the period is too short
|
||||
// the display may not initialise or graphics will become corrupted.
|
||||
// PIO write cycle frequency = (CPU clock/(4 * RP2040_PIO_CLK_DIV))
|
||||
//#define RP2040_PIO_CLK_DIV 1 // 32ns write cycle at 125MHz CPU clock
|
||||
//#define RP2040_PIO_CLK_DIV 2 // 64ns write cycle at 125MHz CPU clock
|
||||
//#define RP2040_PIO_CLK_DIV 3 // 96ns write cycle at 125MHz CPU clock
|
||||
|
||||
// For the RP2040 processor define the SPI port channel used (default 0 if undefined)
|
||||
//#define TFT_SPI_PORT 1 // Set to 0 if SPI0 pins are used, or 1 if spi1 pins used
|
||||
|
||||
// For the STM32 processor define the SPI port channel used (default 1 if undefined)
|
||||
//#define TFT_SPI_PORT 2 // Set to 1 for SPI port 1, or 2 for SPI port 2
|
||||
|
||||
// Define the SPI clock frequency, this affects the graphics rendering speed. Too
|
||||
// fast and the TFT driver will not keep up and display corruption appears.
|
||||
// With an ILI9341 display 40MHz works OK, 80MHz sometimes fails
|
||||
// With a ST7735 display more than 27MHz may not work (spurious pixels and lines)
|
||||
// With an ILI9163 display 27 MHz works OK.
|
||||
|
||||
// #define SPI_FREQUENCY 1000000
|
||||
// #define SPI_FREQUENCY 5000000
|
||||
// #define SPI_FREQUENCY 10000000
|
||||
// #define SPI_FREQUENCY 20000000
|
||||
// #define SPI_FREQUENCY 27000000
|
||||
// #define SPI_FREQUENCY 40000000
|
||||
#define SPI_FREQUENCY 55000000 // STM32 SPI1 only (SPI2 maximum is 27MHz)
|
||||
// #define SPI_FREQUENCY 80000000
|
||||
|
||||
// Optional reduced SPI frequency for reading TFT
|
||||
#define SPI_READ_FREQUENCY 20000000
|
||||
|
||||
// The XPT2046 requires a lower SPI clock rate of 2.5MHz so we define that here:
|
||||
#define SPI_TOUCH_FREQUENCY 2500000
|
||||
|
||||
// The ESP32 has 2 free SPI ports i.e. VSPI and HSPI, the VSPI is the default.
|
||||
// If the VSPI port is in use and pins are not accessible (e.g. TTGO T-Beam)
|
||||
// then uncomment the following line:
|
||||
#define USE_HSPI_PORT
|
||||
|
||||
// Comment out the following #define if "SPI Transactions" do not need to be
|
||||
// supported. When commented out the code size will be smaller and sketches will
|
||||
// run slightly faster, so leave it commented out unless you need it!
|
||||
|
||||
// Transaction support is needed to work with SD library but not needed with TFT_SdFat
|
||||
// Transaction support is required if other SPI devices are connected.
|
||||
|
||||
// Transactions are automatically enabled by the library for an ESP32 (to use HAL mutex)
|
||||
// so changing it here has no effect
|
||||
|
||||
// #define SUPPORT_TRANSACTIONS
|
||||
BIN
PacoMouseCYD/images/EC11_error10K.png
Normal file
|
After Width: | Height: | Size: 661 KiB |
BIN
PacoMouseCYD/images/KY40_error10K.png
Normal file
|
After Width: | Height: | Size: 434 KiB |
BIN
PacoMouseCYD/images/LocoEditor.png
Normal file
|
After Width: | Height: | Size: 137 KiB |
BIN
PacoMouseCYD/images/PacoMouseCYD.png
Normal file
|
After Width: | Height: | Size: 345 KiB |
BIN
PacoMouseCYD/images/languages.png
Normal file
|
After Width: | Height: | Size: 6.0 KiB |
BIN
PacoMouseCYD/images/schematics.png
Normal file
|
After Width: | Height: | Size: 1.7 MiB |
9
PacoMouseCYD/license.txt
Normal file
@@ -0,0 +1,9 @@
|
||||
## Copyright
|
||||
Copyright (c) 2025-2026 Paco Cañada, [The Pows](https://usuaris.tinet.cat/fmco/)
|
||||
All rights reserved.
|
||||
|
||||
## License
|
||||
Proprietary.
|
||||
Sources are only provided to compile and upload to the device.
|
||||
Modifiyng source code or forking/publishing this project ist not allowed.
|
||||
Commercial use is forbidden.
|
||||
164
PacoMouseCYD/src/PacoMouseCYD/FreeSans7pt7b.h
Normal file
@@ -0,0 +1,164 @@
|
||||
/* 7pt font https://rop.nl/truetype2gfx/ */
|
||||
|
||||
const uint8_t FreeSans7pt7bBitmaps[] = {
|
||||
0x00, 0xFF, 0x40, 0xB6, 0xD0, 0x12, 0x28, 0xD3, 0xF2, 0x44, 0xBF, 0x94,
|
||||
0x48, 0x90, 0x10, 0x71, 0x52, 0x95, 0x0E, 0x07, 0x09, 0xD2, 0xA5, 0xF0,
|
||||
0x81, 0x00, 0x00, 0x87, 0x88, 0x89, 0x08, 0x90, 0x72, 0x00, 0x00, 0x04,
|
||||
0xE0, 0x91, 0x09, 0x11, 0x0E, 0x30, 0x48, 0x48, 0x48, 0x30, 0x52, 0x9A,
|
||||
0x8C, 0x8E, 0xFA, 0xF0, 0x29, 0x49, 0x24, 0x99, 0x22, 0x91, 0x24, 0x9A,
|
||||
0x49, 0x48, 0x4F, 0x4A, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0xD8, 0xE0,
|
||||
0xC0, 0x10, 0x22, 0x04, 0x44, 0x88, 0x33, 0x68, 0xE1, 0x86, 0x18, 0x61,
|
||||
0x89, 0xE0, 0x13, 0xF1, 0x11, 0x11, 0x11, 0x18, 0xCD, 0x0A, 0x10, 0x61,
|
||||
0x8C, 0x30, 0x40, 0xFC, 0x38, 0xC9, 0x18, 0x31, 0xC3, 0x80, 0xE1, 0x46,
|
||||
0xF8, 0x04, 0x18, 0x71, 0xE2, 0xC9, 0xB3, 0x7F, 0x0C, 0x18, 0x7E, 0x81,
|
||||
0x02, 0x07, 0xC8, 0xC0, 0x81, 0x46, 0xF8, 0x31, 0x28, 0x60, 0xFB, 0x38,
|
||||
0x61, 0x8D, 0xE0, 0xFC, 0x10, 0x82, 0x10, 0xC2, 0x08, 0x61, 0x00, 0x18,
|
||||
0xC9, 0x1A, 0x33, 0xCD, 0x90, 0xA1, 0x46, 0xF8, 0x73, 0x68, 0xE1, 0x8F,
|
||||
0x72, 0x43, 0x8B, 0xE0, 0xC0, 0x0C, 0x40, 0x0D, 0xC0, 0x00, 0x33, 0x30,
|
||||
0xE0, 0xE0, 0x40, 0xFC, 0x00, 0x00, 0x03, 0x03, 0x03, 0x1D, 0xC8, 0x00,
|
||||
0x7B, 0x38, 0x43, 0x18, 0x43, 0x00, 0x00, 0xC0, 0x0F, 0xC0, 0xC3, 0x08,
|
||||
0x04, 0x8E, 0xB4, 0xCC, 0xA4, 0x47, 0x22, 0x29, 0x12, 0x4E, 0xE3, 0x00,
|
||||
0x0E, 0x00, 0x1F, 0x00, 0x0C, 0x0E, 0x05, 0x02, 0xC2, 0x21, 0x11, 0xFC,
|
||||
0x82, 0x41, 0x60, 0xC0, 0xFC, 0x86, 0x82, 0x82, 0xFC, 0x86, 0x82, 0x83,
|
||||
0x82, 0xFC, 0x3E, 0x43, 0xC1, 0x80, 0x80, 0x80, 0x81, 0x81, 0x43, 0x7E,
|
||||
0xFC, 0xC6, 0xC3, 0xC1, 0xC1, 0xC1, 0xC1, 0xC3, 0xC6, 0xFC, 0xFF, 0x83,
|
||||
0x06, 0x0F, 0xF8, 0x30, 0x60, 0xC1, 0xFC, 0xFF, 0x83, 0x06, 0x0F, 0xD8,
|
||||
0x30, 0x60, 0xC1, 0x80, 0x3E, 0x21, 0xB0, 0x50, 0x08, 0x04, 0x3E, 0x03,
|
||||
0x03, 0x41, 0x9F, 0x40, 0x81, 0x81, 0x81, 0x81, 0xFF, 0x81, 0x81, 0x81,
|
||||
0x81, 0x81, 0xFF, 0xFF, 0xF0, 0x04, 0x10, 0x41, 0x04, 0x10, 0x71, 0xCD,
|
||||
0xE0, 0x82, 0x84, 0x88, 0x90, 0xB0, 0xD8, 0x8C, 0x84, 0x86, 0x83, 0x82,
|
||||
0x08, 0x20, 0x82, 0x08, 0x20, 0x83, 0xF0, 0xC1, 0xE0, 0xE8, 0x74, 0x7A,
|
||||
0x2C, 0x96, 0x5B, 0x29, 0x8C, 0xC6, 0x40, 0xC1, 0xC1, 0xA1, 0xB1, 0x91,
|
||||
0x89, 0x8D, 0x85, 0x87, 0x83, 0x3E, 0x21, 0xA0, 0x70, 0x18, 0x0C, 0x06,
|
||||
0x03, 0x03, 0x43, 0x1F, 0x00, 0xFD, 0x8F, 0x0E, 0x1C, 0x7F, 0xB0, 0x60,
|
||||
0xC1, 0x80, 0x3E, 0x21, 0xA0, 0x70, 0x18, 0x0C, 0x06, 0x03, 0x0B, 0x43,
|
||||
0x1F, 0x80, 0x20, 0xFE, 0xC3, 0xC1, 0xC1, 0xC6, 0xFE, 0xC3, 0xC3, 0xC3,
|
||||
0xC1, 0x7C, 0xC6, 0x82, 0xC0, 0x70, 0x1E, 0x02, 0x83, 0xC2, 0x7C, 0xFF,
|
||||
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x81, 0x81, 0x81,
|
||||
0x81, 0x81, 0x81, 0x81, 0x81, 0xC3, 0x7E, 0x41, 0xA0, 0x98, 0x44, 0x62,
|
||||
0x21, 0x90, 0x58, 0x28, 0x1C, 0x06, 0x00, 0xC2, 0x1A, 0x38, 0x91, 0x44,
|
||||
0xCA, 0x26, 0x53, 0x14, 0x50, 0xA2, 0x85, 0x14, 0x38, 0xE0, 0x82, 0x00,
|
||||
0x41, 0x11, 0x8C, 0x82, 0x80, 0xC0, 0xE0, 0x50, 0x44, 0x63, 0x20, 0xC0,
|
||||
0xC1, 0xB0, 0x88, 0xC6, 0xC1, 0x40, 0x60, 0x20, 0x10, 0x08, 0x04, 0x00,
|
||||
0x7F, 0x03, 0x06, 0x04, 0x08, 0x18, 0x30, 0x60, 0x40, 0xFF, 0xEA, 0xAA,
|
||||
0xAA, 0xC0, 0x88, 0x04, 0x40, 0x22, 0x01, 0xE4, 0x92, 0x49, 0x24, 0x9E,
|
||||
0x23, 0x15, 0x29, 0x00, 0x00, 0x44, 0xFA, 0x20, 0xBE, 0x8A, 0x2F, 0xC0,
|
||||
0x82, 0x08, 0x3E, 0x8E, 0x18, 0x61, 0x8F, 0xE0, 0x7C, 0x89, 0x06, 0x0C,
|
||||
0x08, 0x9F, 0x00, 0x02, 0x04, 0x0B, 0xD4, 0x78, 0x70, 0xE1, 0x46, 0xF4,
|
||||
0x7A, 0x38, 0x7F, 0x82, 0x37, 0x80, 0x34, 0x4F, 0x44, 0x44, 0x44, 0x7A,
|
||||
0x8F, 0x1E, 0x1C, 0x68, 0xDE, 0x83, 0x44, 0x70, 0x82, 0x08, 0x3E, 0x8E,
|
||||
0x18, 0x61, 0x86, 0x10, 0x9F, 0xC0, 0x41, 0x55, 0x55, 0xC0, 0x82, 0x08,
|
||||
0x26, 0xB3, 0x8F, 0x24, 0x8A, 0x30, 0xFF, 0xC0, 0xFF, 0xC6, 0x62, 0x31,
|
||||
0x18, 0x8C, 0x46, 0x22, 0xFA, 0x38, 0x61, 0x86, 0x18, 0x40, 0x7C, 0x8D,
|
||||
0x0E, 0x14, 0x28, 0xCF, 0x00, 0xFA, 0x38, 0x61, 0x86, 0x3F, 0xA0, 0x82,
|
||||
0x00, 0x7E, 0x8F, 0x0E, 0x1C, 0x28, 0xDE, 0x81, 0x02, 0x04, 0xFA, 0x49,
|
||||
0x20, 0x7D, 0x14, 0x0E, 0x05, 0x17, 0xC0, 0x4B, 0xA4, 0x92, 0x60, 0x8E,
|
||||
0x38, 0xE3, 0x8E, 0x3F, 0x40, 0xC4, 0x89, 0x33, 0x42, 0x86, 0x0C, 0x00,
|
||||
0xCC, 0xD3, 0x24, 0xC9, 0x5E, 0x73, 0x0C, 0xC3, 0x30, 0x44, 0xA3, 0x84,
|
||||
0x29, 0xA4, 0x40, 0x44, 0x89, 0x31, 0x42, 0x86, 0x04, 0x08, 0x20, 0xC0,
|
||||
0x7C, 0x31, 0x8C, 0x21, 0x0F, 0xC0, 0x69, 0x25, 0xA6, 0x49, 0x26, 0xFF,
|
||||
0xF8, 0xC6, 0x66, 0x22, 0x12, 0x26, 0x66, 0xC0, 0xE6, 0x70 };
|
||||
|
||||
const GFXglyph FreeSans7pt7bGlyphs[] PROGMEM = {
|
||||
{ 0, 1, 1, 4, 0, 0 }, // 0x20 ' '
|
||||
{ 1, 1, 10, 4, 2, -9 }, // 0x21 '!'
|
||||
{ 3, 3, 4, 5, 1, -9 }, // 0x22 '"'
|
||||
{ 5, 7, 10, 8, 0, -9 }, // 0x23 '#'
|
||||
{ 14, 7, 13, 8, 0, -10 }, // 0x24 '$'
|
||||
{ 26, 12, 10, 12, 0, -9 }, // 0x25 '%'
|
||||
{ 41, 8, 10, 9, 1, -9 }, // 0x26 '&'
|
||||
{ 51, 1, 4, 3, 1, -9 }, // 0x27 '''
|
||||
{ 52, 3, 13, 5, 1, -9 }, // 0x28 '('
|
||||
{ 57, 3, 13, 5, 1, -9 }, // 0x29 ')'
|
||||
{ 62, 4, 4, 5, 1, -9 }, // 0x2A '*'
|
||||
{ 64, 6, 7, 8, 1, -6 }, // 0x2B '+'
|
||||
{ 70, 2, 3, 4, 1, 0 }, // 0x2C ','
|
||||
{ 71, 3, 1, 5, 1, -3 }, // 0x2D '-'
|
||||
{ 72, 2, 1, 4, 1, 0 }, // 0x2E '.'
|
||||
{ 73, 4, 10, 4, 0, -9 }, // 0x2F '/'
|
||||
{ 78, 6, 10, 8, 1, -9 }, // 0x30 '0'
|
||||
{ 86, 4, 10, 8, 1, -9 }, // 0x31 '1'
|
||||
{ 91, 7, 10, 8, 0, -9 }, // 0x32 '2'
|
||||
{ 100, 7, 10, 8, 0, -9 }, // 0x33 '3'
|
||||
{ 109, 7, 10, 8, 0, -9 }, // 0x34 '4'
|
||||
{ 118, 7, 10, 8, 0, -9 }, // 0x35 '5'
|
||||
{ 127, 6, 10, 8, 1, -9 }, // 0x36 '6'
|
||||
{ 135, 6, 10, 8, 1, -9 }, // 0x37 '7'
|
||||
{ 143, 7, 10, 8, 0, -9 }, // 0x38 '8'
|
||||
{ 152, 6, 10, 8, 1, -9 }, // 0x39 '9'
|
||||
{ 160, 2, 7, 4, 1, -6 }, // 0x3A ':'
|
||||
{ 162, 2, 9, 4, 1, -6 }, // 0x3B ';'
|
||||
{ 165, 6, 7, 8, 1, -6 }, // 0x3C '<'
|
||||
{ 171, 6, 3, 8, 1, -4 }, // 0x3D '='
|
||||
{ 174, 6, 7, 8, 1, -6 }, // 0x3E '>'
|
||||
{ 180, 6, 10, 8, 1, -9 }, // 0x3F '?'
|
||||
{ 188, 13, 12, 14, 0, -9 }, // 0x40 '@'
|
||||
{ 208, 9, 10, 9, 0, -9 }, // 0x41 'A'
|
||||
{ 220, 8, 10, 9, 1, -9 }, // 0x42 'B'
|
||||
{ 230, 8, 10, 10, 1, -9 }, // 0x43 'C'
|
||||
{ 240, 8, 10, 10, 1, -9 }, // 0x44 'D'
|
||||
{ 250, 7, 10, 9, 1, -9 }, // 0x45 'E'
|
||||
{ 259, 7, 10, 8, 1, -9 }, // 0x46 'F'
|
||||
{ 268, 9, 10, 11, 1, -9 }, // 0x47 'G'
|
||||
{ 280, 8, 10, 10, 1, -9 }, // 0x48 'H'
|
||||
{ 290, 2, 10, 4, 1, -9 }, // 0x49 'I'
|
||||
{ 293, 6, 10, 7, 0, -9 }, // 0x4A 'J'
|
||||
{ 301, 8, 10, 9, 1, -9 }, // 0x4B 'K'
|
||||
{ 311, 6, 10, 8, 1, -9 }, // 0x4C 'L'
|
||||
{ 319, 9, 10, 11, 1, -9 }, // 0x4D 'M'
|
||||
{ 331, 8, 10, 10, 1, -9 }, // 0x4E 'N'
|
||||
{ 341, 9, 10, 11, 1, -9 }, // 0x4F 'O'
|
||||
{ 353, 7, 10, 9, 1, -9 }, // 0x50 'P'
|
||||
{ 362, 9, 11, 11, 1, -9 }, // 0x51 'Q'
|
||||
{ 375, 8, 10, 10, 1, -9 }, // 0x52 'R'
|
||||
{ 385, 8, 10, 9, 1, -9 }, // 0x53 'S'
|
||||
{ 395, 8, 10, 8, 0, -9 }, // 0x54 'T'
|
||||
{ 405, 8, 10, 10, 1, -9 }, // 0x55 'U'
|
||||
{ 415, 9, 10, 9, 0, -9 }, // 0x56 'V'
|
||||
{ 427, 13, 10, 13, 0, -9 }, // 0x57 'W'
|
||||
{ 444, 9, 10, 9, 0, -9 }, // 0x58 'X'
|
||||
{ 456, 9, 10, 9, 0, -9 }, // 0x59 'Y'
|
||||
{ 468, 8, 10, 8, 0, -9 }, // 0x5A 'Z'
|
||||
{ 478, 2, 13, 4, 1, -9 }, // 0x5B '['
|
||||
{ 482, 4, 10, 4, 0, -9 }, // 0x5C '\'
|
||||
{ 487, 3, 13, 4, 0, -9 }, // 0x5D ']'
|
||||
{ 492, 5, 5, 6, 1, -9 }, // 0x5E '^'
|
||||
{ 496, 8, 1, 8, 0, 3 }, // 0x5F '_'
|
||||
{ 497, 3, 2, 5, 0, -9 }, // 0x60 '`'
|
||||
{ 498, 6, 7, 8, 1, -6 }, // 0x61 'a'
|
||||
{ 504, 6, 10, 8, 1, -9 }, // 0x62 'b'
|
||||
{ 512, 7, 7, 7, 0, -6 }, // 0x63 'c'
|
||||
{ 519, 7, 10, 8, 0, -9 }, // 0x64 'd'
|
||||
{ 528, 6, 7, 8, 1, -6 }, // 0x65 'e'
|
||||
{ 534, 4, 10, 4, 0, -9 }, // 0x66 'f'
|
||||
{ 539, 7, 10, 8, 0, -6 }, // 0x67 'g'
|
||||
{ 548, 6, 10, 8, 1, -9 }, // 0x68 'h'
|
||||
{ 556, 1, 10, 3, 1, -9 }, // 0x69 'i'
|
||||
{ 558, 2, 13, 3, 0, -9 }, // 0x6A 'j'
|
||||
{ 562, 6, 10, 7, 1, -9 }, // 0x6B 'k'
|
||||
{ 570, 1, 10, 3, 1, -9 }, // 0x6C 'l'
|
||||
{ 572, 9, 7, 11, 1, -6 }, // 0x6D 'm'
|
||||
{ 580, 6, 7, 8, 1, -6 }, // 0x6E 'n'
|
||||
{ 586, 7, 7, 8, 0, -6 }, // 0x6F 'o'
|
||||
{ 593, 6, 10, 8, 1, -6 }, // 0x70 'p'
|
||||
{ 601, 7, 10, 8, 0, -6 }, // 0x71 'q'
|
||||
{ 610, 3, 7, 5, 1, -6 }, // 0x72 'r'
|
||||
{ 613, 6, 7, 7, 0, -6 }, // 0x73 's'
|
||||
{ 619, 3, 9, 4, 0, -8 }, // 0x74 't'
|
||||
{ 623, 6, 7, 8, 1, -6 }, // 0x75 'u'
|
||||
{ 629, 7, 7, 7, 0, -6 }, // 0x76 'v'
|
||||
{ 636, 10, 7, 10, 0, -6 }, // 0x77 'w'
|
||||
{ 645, 6, 7, 7, 0, -6 }, // 0x78 'x'
|
||||
{ 651, 7, 10, 7, 0, -6 }, // 0x79 'y'
|
||||
{ 660, 6, 7, 7, 0, -6 }, // 0x7A 'z'
|
||||
{ 666, 3, 13, 5, 1, -9 }, // 0x7B '{'
|
||||
{ 671, 1, 13, 4, 1, -9 }, // 0x7C '|'
|
||||
{ 673, 4, 13, 5, 0, -9 }, // 0x7D '}'
|
||||
{ 680, 6, 2, 8, 1, -5 } }; // 0x7E '~'
|
||||
|
||||
const GFXfont FreeSans7pt7b = {
|
||||
(uint8_t *)FreeSans7pt7bBitmaps,
|
||||
(GFXglyph *)FreeSans7pt7bGlyphs,
|
||||
0x20, 0x7E, 23 };
|
||||
|
||||
// Approx. 1354 bytes
|
||||
153
PacoMouseCYD/src/PacoMouseCYD/FreeSansBold6pt7b.h
Normal file
@@ -0,0 +1,153 @@
|
||||
/* 6pt font https://rop.nl/truetype2gfx/ */
|
||||
|
||||
const uint8_t FreeSansBold6pt7bBitmaps[] = {
|
||||
0x00, 0xFF, 0x57, 0xC0, 0xBB, 0x90, 0x2C, 0x5B, 0xFB, 0x44, 0x9F, 0x96,
|
||||
0x28, 0x11, 0xFD, 0xF4, 0x70, 0x71, 0x77, 0x7C, 0x40, 0x71, 0x36, 0x8D,
|
||||
0x81, 0xD0, 0x0B, 0xC2, 0x91, 0x24, 0x4F, 0x00, 0xF1, 0x63, 0x87, 0x1E,
|
||||
0xA7, 0x66, 0xFE, 0xE0, 0x32, 0x64, 0x4C, 0xC4, 0x46, 0x20, 0x89, 0x92,
|
||||
0x49, 0x69, 0x00, 0x2A, 0x65, 0x21, 0x09, 0xF2, 0x10, 0xF2, 0xFF, 0xF0,
|
||||
0x24, 0x24, 0x84, 0x01, 0xE4, 0xF3, 0xCF, 0x3C, 0xD3, 0x78, 0x3C, 0x92,
|
||||
0x49, 0x01, 0xF4, 0xF3, 0x0C, 0x66, 0x18, 0xFC, 0x01, 0xEC, 0xC3, 0x18,
|
||||
0x30, 0xF3, 0x78, 0x18, 0xA2, 0x92, 0xCB, 0xF0, 0x82, 0x7D, 0x05, 0x1F,
|
||||
0x0C, 0x3C, 0xDE, 0x01, 0xF4, 0xF0, 0xFF, 0x3C, 0x53, 0x78, 0xFC, 0x31,
|
||||
0x84, 0x30, 0xC2, 0x08, 0x01, 0xE4, 0xD3, 0x39, 0x3C, 0x73, 0x78, 0x01,
|
||||
0xEC, 0xF3, 0xCD, 0xF0, 0xD3, 0x78, 0xF0, 0xF0, 0xF0, 0xF7, 0x00, 0x77,
|
||||
0x30, 0x38, 0x10, 0xFF, 0xC1, 0xF0, 0x83, 0x81, 0xC3, 0x7B, 0x00, 0x73,
|
||||
0xE8, 0x82, 0x18, 0xC2, 0x0C, 0x30, 0x0F, 0x06, 0x18, 0x81, 0x27, 0x94,
|
||||
0x93, 0x22, 0x64, 0x4A, 0xFE, 0x60, 0x06, 0x20, 0x38, 0x00, 0x18, 0x1C,
|
||||
0x1C, 0x34, 0x36, 0x26, 0x7E, 0x63, 0xC3, 0xF9, 0xFB, 0x1E, 0x2F, 0x98,
|
||||
0xF1, 0xE7, 0xFC, 0x38, 0xFB, 0x1C, 0x08, 0x10, 0x31, 0xE3, 0x7C, 0xF1,
|
||||
0xFB, 0x1E, 0x3C, 0x78, 0xF1, 0xE6, 0xF8, 0xFF, 0xFC, 0x30, 0xFF, 0x0C,
|
||||
0x30, 0xFC, 0xFF, 0xFC, 0x30, 0xFB, 0x0C, 0x30, 0xC0, 0x1C, 0x3F, 0x63,
|
||||
0x40, 0x47, 0x47, 0x61, 0x73, 0x3F, 0xC7, 0x8F, 0x1E, 0x3F, 0xF8, 0xF1,
|
||||
0xE3, 0xC6, 0xFF, 0xFF, 0xC0, 0x0C, 0x30, 0xC3, 0x0C, 0x3C, 0xF3, 0x78,
|
||||
0xC7, 0x9B, 0x67, 0x8F, 0x1B, 0x36, 0x66, 0xC6, 0xC3, 0x0C, 0x30, 0xC3,
|
||||
0x0C, 0x30, 0xFC, 0xC7, 0xE7, 0xE7, 0xE7, 0xE7, 0xFF, 0xFB, 0xDB, 0xDB,
|
||||
0xC7, 0x8F, 0x9F, 0x3F, 0x7B, 0xF3, 0xE7, 0xC6, 0x1C, 0x1F, 0x98, 0xC8,
|
||||
0x3C, 0x1A, 0x0D, 0x84, 0xE6, 0x3E, 0x00, 0xF3, 0xFC, 0x71, 0xFF, 0xEC,
|
||||
0x30, 0xC0, 0x1C, 0x1F, 0x98, 0xC8, 0x34, 0x1A, 0x0D, 0x94, 0xE6, 0x3F,
|
||||
0x80, 0x00, 0xF9, 0xFF, 0x1E, 0x3F, 0xDF, 0xB1, 0xE3, 0xC6, 0x38, 0xFD,
|
||||
0x1B, 0x07, 0xC1, 0xF0, 0xB3, 0x7E, 0xFF, 0xFC, 0x60, 0xC1, 0x83, 0x06,
|
||||
0x0C, 0x18, 0xC7, 0x8F, 0x1E, 0x3C, 0x78, 0xF1, 0xE6, 0x7C, 0xC3, 0x42,
|
||||
0x66, 0x66, 0x24, 0x3C, 0x3C, 0x18, 0x18, 0xC4, 0x79, 0xCD, 0x39, 0x35,
|
||||
0x66, 0xAC, 0x57, 0x8E, 0xE1, 0x8C, 0x31, 0x80, 0xC7, 0x66, 0x3C, 0x3C,
|
||||
0x18, 0x38, 0x3C, 0x66, 0x66, 0xC3, 0x66, 0x66, 0x3C, 0x3C, 0x18, 0x18,
|
||||
0x18, 0x18, 0xFF, 0xFC, 0x30, 0xE1, 0x86, 0x18, 0x60, 0xFE, 0xFE, 0x49,
|
||||
0x24, 0x93, 0x80, 0x91, 0x24, 0x49, 0xFC, 0x92, 0x49, 0x27, 0x80, 0x63,
|
||||
0x95, 0xB8, 0x80, 0xFE, 0x48, 0x7F, 0x33, 0xF3, 0xCD, 0xF0, 0x82, 0x08,
|
||||
0x3E, 0xCE, 0x38, 0xF2, 0xF8, 0x7D, 0x3C, 0x30, 0x4D, 0xE0, 0x04, 0x10,
|
||||
0x5F, 0x4F, 0x1C, 0x53, 0x7C, 0x7B, 0x3F, 0xF0, 0x4D, 0xE0, 0x37, 0x6F,
|
||||
0x66, 0x66, 0x60, 0x7D, 0x3C, 0x71, 0x6D, 0xF0, 0x5F, 0x10, 0x84, 0x21,
|
||||
0xFC, 0xC6, 0x31, 0x88, 0xDF, 0x80, 0x51, 0x55, 0x5F, 0x84, 0x21, 0x3B,
|
||||
0x73, 0xD3, 0x98, 0xFF, 0x80, 0xFF, 0x6C, 0xE6, 0x73, 0x39, 0x9C, 0xCC,
|
||||
0xFE, 0x63, 0x18, 0xC4, 0x7C, 0x8B, 0x1E, 0x36, 0x4F, 0x80, 0xFB, 0x38,
|
||||
0xE3, 0xCB, 0xE8, 0x20, 0x80, 0x7D, 0x3C, 0x71, 0x4D, 0xF0, 0x41, 0x04,
|
||||
0xBA, 0x49, 0x00, 0x7D, 0x37, 0x87, 0xCD, 0xF0, 0x66, 0xF6, 0x66, 0x67,
|
||||
0x8C, 0x63, 0x1D, 0xFC, 0xCD, 0x36, 0x8A, 0x38, 0xC0, 0xCD, 0xAE, 0x95,
|
||||
0x4E, 0xE7, 0x71, 0xB0, 0x6D, 0xE3, 0x0E, 0x69, 0x30, 0xCD, 0x36, 0x9A,
|
||||
0x38, 0xC3, 0x1C, 0x40, 0xF8, 0x63, 0x18, 0xC3, 0xF0, 0x37, 0x66, 0x6C,
|
||||
0x66, 0x66, 0x30, 0xFF, 0xE0, 0x99, 0x24, 0xDA, 0x4B, 0x00, 0xC5, 0xC0 };
|
||||
|
||||
const GFXglyph FreeSansBold6pt7bGlyphs[] PROGMEM = {
|
||||
{ 0, 1, 1, 3, 0, 0 }, // 0x20 ' '
|
||||
{ 1, 2, 9, 4, 1, -8 }, // 0x21 '!'
|
||||
{ 4, 4, 3, 6, 1, -8 }, // 0x22 '"'
|
||||
{ 6, 7, 8, 7, 0, -7 }, // 0x23 '#'
|
||||
{ 13, 6, 10, 7, 0, -8 }, // 0x24 '$'
|
||||
{ 21, 10, 8, 10, 0, -7 }, // 0x25 '%'
|
||||
{ 31, 7, 9, 8, 1, -8 }, // 0x26 '&'
|
||||
{ 39, 1, 3, 3, 1, -8 }, // 0x27 '''
|
||||
{ 40, 4, 11, 4, 0, -8 }, // 0x28 '('
|
||||
{ 46, 3, 11, 4, 0, -8 }, // 0x29 ')'
|
||||
{ 51, 4, 4, 5, 0, -8 }, // 0x2A '*'
|
||||
{ 53, 5, 6, 7, 1, -5 }, // 0x2B '+'
|
||||
{ 57, 2, 4, 3, 1, -1 }, // 0x2C ','
|
||||
{ 58, 4, 2, 4, 0, -3 }, // 0x2D '-'
|
||||
{ 59, 2, 2, 3, 1, -1 }, // 0x2E '.'
|
||||
{ 60, 3, 8, 3, 0, -7 }, // 0x2F '/'
|
||||
{ 63, 6, 9, 7, 0, -8 }, // 0x30 '0'
|
||||
{ 70, 3, 8, 7, 1, -7 }, // 0x31 '1'
|
||||
{ 73, 6, 9, 7, 0, -8 }, // 0x32 '2'
|
||||
{ 80, 6, 9, 7, 0, -8 }, // 0x33 '3'
|
||||
{ 87, 6, 8, 7, 0, -7 }, // 0x34 '4'
|
||||
{ 93, 6, 8, 7, 0, -7 }, // 0x35 '5'
|
||||
{ 99, 6, 9, 7, 0, -8 }, // 0x36 '6'
|
||||
{ 106, 6, 8, 7, 0, -7 }, // 0x37 '7'
|
||||
{ 112, 6, 9, 7, 0, -8 }, // 0x38 '8'
|
||||
{ 119, 6, 9, 7, 0, -8 }, // 0x39 '9'
|
||||
{ 126, 2, 6, 4, 1, -5 }, // 0x3A ':'
|
||||
{ 128, 2, 8, 4, 1, -5 }, // 0x3B ';'
|
||||
{ 130, 6, 6, 7, 0, -5 }, // 0x3C '<'
|
||||
{ 135, 5, 4, 7, 1, -4 }, // 0x3D '='
|
||||
{ 138, 6, 6, 7, 0, -5 }, // 0x3E '>'
|
||||
{ 143, 6, 9, 7, 1, -8 }, // 0x3F '?'
|
||||
{ 150, 11, 11, 11, 0, -8 }, // 0x40 '@'
|
||||
{ 166, 8, 9, 8, 0, -8 }, // 0x41 'A'
|
||||
{ 175, 7, 9, 8, 1, -8 }, // 0x42 'B'
|
||||
{ 183, 7, 9, 8, 1, -8 }, // 0x43 'C'
|
||||
{ 191, 7, 9, 8, 1, -8 }, // 0x44 'D'
|
||||
{ 199, 6, 9, 8, 1, -8 }, // 0x45 'E'
|
||||
{ 206, 6, 9, 7, 1, -8 }, // 0x46 'F'
|
||||
{ 213, 8, 9, 9, 0, -8 }, // 0x47 'G'
|
||||
{ 222, 7, 9, 8, 1, -8 }, // 0x48 'H'
|
||||
{ 230, 2, 9, 3, 1, -8 }, // 0x49 'I'
|
||||
{ 233, 6, 9, 7, 0, -8 }, // 0x4A 'J'
|
||||
{ 240, 7, 9, 8, 1, -8 }, // 0x4B 'K'
|
||||
{ 248, 6, 9, 7, 1, -8 }, // 0x4C 'L'
|
||||
{ 255, 8, 9, 10, 1, -8 }, // 0x4D 'M'
|
||||
{ 264, 7, 9, 8, 1, -8 }, // 0x4E 'N'
|
||||
{ 272, 9, 9, 9, 0, -8 }, // 0x4F 'O'
|
||||
{ 283, 6, 9, 8, 1, -8 }, // 0x50 'P'
|
||||
{ 290, 9, 10, 9, 0, -8 }, // 0x51 'Q'
|
||||
{ 302, 7, 9, 8, 1, -8 }, // 0x52 'R'
|
||||
{ 310, 7, 9, 8, 0, -8 }, // 0x53 'S'
|
||||
{ 318, 7, 9, 7, 0, -8 }, // 0x54 'T'
|
||||
{ 326, 7, 9, 8, 1, -8 }, // 0x55 'U'
|
||||
{ 334, 8, 9, 8, 0, -8 }, // 0x56 'V'
|
||||
{ 343, 11, 9, 11, 0, -8 }, // 0x57 'W'
|
||||
{ 356, 8, 9, 8, 0, -8 }, // 0x58 'X'
|
||||
{ 365, 8, 9, 8, 0, -8 }, // 0x59 'Y'
|
||||
{ 374, 7, 9, 7, 0, -8 }, // 0x5A 'Z'
|
||||
{ 382, 3, 11, 4, 1, -8 }, // 0x5B '['
|
||||
{ 387, 3, 8, 3, 0, -7 }, // 0x5C '\'
|
||||
{ 390, 3, 11, 4, 0, -8 }, // 0x5D ']'
|
||||
{ 395, 5, 5, 7, 1, -7 }, // 0x5E '^'
|
||||
{ 399, 7, 1, 7, 0, 2 }, // 0x5F '_'
|
||||
{ 400, 3, 2, 4, 0, -8 }, // 0x60 '`'
|
||||
{ 401, 6, 6, 7, 0, -5 }, // 0x61 'a'
|
||||
{ 406, 6, 9, 7, 1, -8 }, // 0x62 'b'
|
||||
{ 413, 6, 6, 7, 0, -5 }, // 0x63 'c'
|
||||
{ 418, 6, 9, 7, 0, -8 }, // 0x64 'd'
|
||||
{ 425, 6, 6, 7, 0, -5 }, // 0x65 'e'
|
||||
{ 430, 4, 9, 4, 0, -8 }, // 0x66 'f'
|
||||
{ 435, 6, 9, 7, 0, -5 }, // 0x67 'g'
|
||||
{ 442, 5, 9, 7, 1, -8 }, // 0x68 'h'
|
||||
{ 448, 1, 9, 3, 1, -8 }, // 0x69 'i'
|
||||
{ 450, 2, 12, 3, 0, -8 }, // 0x6A 'j'
|
||||
{ 453, 5, 9, 7, 1, -8 }, // 0x6B 'k'
|
||||
{ 459, 1, 9, 3, 1, -8 }, // 0x6C 'l'
|
||||
{ 461, 9, 6, 10, 1, -5 }, // 0x6D 'm'
|
||||
{ 468, 5, 6, 7, 1, -5 }, // 0x6E 'n'
|
||||
{ 472, 7, 6, 7, 0, -5 }, // 0x6F 'o'
|
||||
{ 478, 6, 9, 7, 1, -5 }, // 0x70 'p'
|
||||
{ 485, 6, 9, 7, 0, -5 }, // 0x71 'q'
|
||||
{ 492, 3, 6, 5, 1, -5 }, // 0x72 'r'
|
||||
{ 495, 6, 6, 7, 0, -5 }, // 0x73 's'
|
||||
{ 500, 4, 8, 4, 0, -7 }, // 0x74 't'
|
||||
{ 504, 5, 6, 7, 1, -5 }, // 0x75 'u'
|
||||
{ 508, 6, 6, 7, 0, -5 }, // 0x76 'v'
|
||||
{ 513, 9, 6, 9, 0, -5 }, // 0x77 'w'
|
||||
{ 520, 6, 6, 7, 0, -5 }, // 0x78 'x'
|
||||
{ 525, 6, 9, 7, 0, -5 }, // 0x79 'y'
|
||||
{ 532, 6, 6, 6, 0, -5 }, // 0x7A 'z'
|
||||
{ 537, 4, 11, 5, 0, -8 }, // 0x7B '{'
|
||||
{ 543, 1, 11, 3, 1, -8 }, // 0x7C '|'
|
||||
{ 545, 3, 11, 5, 1, -8 }, // 0x7D '}'
|
||||
{ 550, 5, 2, 7, 1, -3 } }; // 0x7E '~'
|
||||
|
||||
const GFXfont FreeSansBold6pt7b = {
|
||||
(uint8_t *)FreeSansBold6pt7bBitmaps,
|
||||
(GFXglyph *)FreeSansBold6pt7bGlyphs,
|
||||
0x20, 0x7E, 19 };
|
||||
|
||||
// Approx. 1224 bytes
|
||||
1724
PacoMouseCYD/src/PacoMouseCYD/PacoMouseCYD.ino
Normal file
197
PacoMouseCYD/src/PacoMouseCYD/XPT2046.cpp
Normal file
@@ -0,0 +1,197 @@
|
||||
/* PacoMouseCYD throttle -- F. Cañada 2025-2026 -- https://usuaris.tinet.cat/fmco/
|
||||
Simple XPT2046 SPI/Bitbang interface for PacoMouseCYD
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "XPT2046.h"
|
||||
|
||||
|
||||
#define Z_THRESHOLD 300
|
||||
#define MSEC_THRESHOLD 4
|
||||
|
||||
XPT2046_TS::XPT2046_TS(uint8_t mosiPin, uint8_t misoPin, uint8_t clkPin, uint8_t csPin) :
|
||||
_mosiPin(mosiPin), _misoPin(misoPin), _clkPin(clkPin), _csPin(csPin) {
|
||||
cal = TouchCalibration{0, 4095, 0, 4095, 0}; // other initializations, if required
|
||||
_msraw = millis();
|
||||
#ifdef USE_XPT2046_SPI
|
||||
hspi = new SPIClass(HSPI); // XPT2046 connected to HSPI in CYD 2.4"
|
||||
hspi->begin();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void XPT2046_TS::begin(uint16_t width, uint16_t height) {
|
||||
pinMode(_csPin, OUTPUT);
|
||||
digitalWrite(_csPin, HIGH);
|
||||
#ifdef USE_XPT2046_BITBANG
|
||||
pinMode(_clkPin, OUTPUT); // init all pins in bitbang mode only (CYD 2.8")
|
||||
digitalWrite(_clkPin, LOW);
|
||||
pinMode(_mosiPin, OUTPUT);
|
||||
pinMode(_misoPin, INPUT);
|
||||
#endif
|
||||
_width = width;
|
||||
_height = height;
|
||||
}
|
||||
|
||||
|
||||
void XPT2046_TS::setCalibration(uint16_t xMin, uint16_t xMax, uint16_t yMin, uint16_t yMax) {
|
||||
cal.xMin = xMin;
|
||||
cal.xMax = xMax;
|
||||
cal.yMin = yMin;
|
||||
cal.yMax = yMax;
|
||||
}
|
||||
|
||||
|
||||
TouchCalibration XPT2046_TS::getCalibration() {
|
||||
return cal;
|
||||
}
|
||||
|
||||
|
||||
void XPT2046_TS::setRotation(uint8_t n) {
|
||||
cal.rotation = n % 4;
|
||||
}
|
||||
|
||||
|
||||
bool XPT2046_TS::touched() {
|
||||
update();
|
||||
return (_zraw > Z_THRESHOLD);
|
||||
}
|
||||
|
||||
|
||||
TSPoint XPT2046_TS::getTouch() {
|
||||
update();
|
||||
uint16_t x = map(_xraw, cal.xMin, cal.xMax, 0, _width);
|
||||
uint16_t y = map(_yraw, cal.yMin, cal.yMax, 0, _height);
|
||||
if ((x >= _width) || (x <= 0) || (y >= _height) || (y <= 0))
|
||||
_zraw = 0;
|
||||
return TSPoint{x, y, _zraw};
|
||||
}
|
||||
|
||||
|
||||
void XPT2046_TS::readData(uint16_t *x, uint16_t *y, uint16_t *z) {
|
||||
update();
|
||||
*x = _xraw; // read raw data
|
||||
*y = _yraw;
|
||||
*z = _zraw;
|
||||
}
|
||||
|
||||
|
||||
#ifdef USE_XPT2046_BITBANG
|
||||
uint16_t XPT2046_TS::readSPI(byte command) {
|
||||
uint16_t result = 0;
|
||||
for (int i = 7; i >= 0; i--) {
|
||||
digitalWrite(_mosiPin, command & (1 << i)); // send command
|
||||
digitalWrite(_clkPin, HIGH);
|
||||
delayMicroseconds(7);
|
||||
digitalWrite(_clkPin, LOW);
|
||||
delayMicroseconds(7);
|
||||
}
|
||||
for (int i = 11; i >= 0; i--) { // read data
|
||||
digitalWrite(_clkPin, HIGH);
|
||||
delayMicroseconds(7);
|
||||
digitalWrite(_clkPin, LOW);
|
||||
delayMicroseconds(7);
|
||||
result |= (digitalRead(_misoPin) << i);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void XPT2046_TS::update() {
|
||||
int t;
|
||||
uint32_t now = millis();
|
||||
if (now - _msraw < MSEC_THRESHOLD)
|
||||
return;
|
||||
digitalWrite(_csPin, LOW);
|
||||
readSPI(0xB0);
|
||||
readSPI(0xB0);
|
||||
readSPI(0xB0);
|
||||
int z1 = readSPI(0xB0);
|
||||
_zraw = z1 + 4095;
|
||||
readSPI(0xC0);
|
||||
readSPI(0xC0);
|
||||
readSPI(0xC0);
|
||||
int z2 = readSPI(0xC0);
|
||||
_zraw -= z2;
|
||||
readSPI(0x90);
|
||||
readSPI(0x90);
|
||||
readSPI(0x90);
|
||||
_xraw = readSPI(0x90);
|
||||
readSPI(0xD0);
|
||||
readSPI(0xD0);
|
||||
readSPI(0xD0);
|
||||
_yraw = readSPI(0xD0);
|
||||
digitalWrite(_csPin, HIGH);
|
||||
_msraw = now;
|
||||
switch (cal.rotation) {
|
||||
case 0:
|
||||
t = 4095 - _yraw;
|
||||
_yraw = _xraw;
|
||||
_xraw = t;
|
||||
break;
|
||||
case 1:
|
||||
break;
|
||||
case 2:
|
||||
t = _xraw;
|
||||
_xraw = _yraw;
|
||||
_yraw = 4095 - t;
|
||||
break;
|
||||
default:
|
||||
_xraw = 4095 - _xraw;
|
||||
_yraw = 4095 - _yraw;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef USE_XPT2046_SPI
|
||||
void XPT2046_TS::update() {
|
||||
int t;
|
||||
uint32_t now = millis();
|
||||
if (now - _msraw < MSEC_THRESHOLD)
|
||||
return;
|
||||
hspi->beginTransaction(SPISettings(2000000, MSBFIRST, SPI_MODE0));
|
||||
digitalWrite(_csPin, LOW);
|
||||
hspi->transfer(0xB0);
|
||||
hspi->transfer16(0xB0);
|
||||
hspi->transfer16(0xB0);
|
||||
hspi->transfer16(0xB0);
|
||||
int z1 = hspi->transfer16(0xC0) >> 3;
|
||||
_zraw = z1 + 4095;
|
||||
hspi->transfer16(0xC0);
|
||||
hspi->transfer16(0xC0);
|
||||
hspi->transfer16(0xC0);
|
||||
int z2 = hspi->transfer16(0x90) >> 3;
|
||||
_zraw -= z2;
|
||||
hspi->transfer16(0x90);
|
||||
hspi->transfer16(0x90);
|
||||
hspi->transfer16(0x90);
|
||||
_xraw = hspi->transfer16(0xD0) >> 3;
|
||||
hspi->transfer16(0xD0);
|
||||
hspi->transfer16(0xD0);
|
||||
hspi->transfer16(0xD0);
|
||||
_yraw = hspi->transfer16(0x0) >> 3;
|
||||
digitalWrite(_csPin, HIGH);
|
||||
hspi->endTransaction();
|
||||
_msraw = now;
|
||||
switch (cal.rotation) {
|
||||
case 0:
|
||||
_xraw = 4095 - _xraw;
|
||||
break;
|
||||
case 1:
|
||||
t = _yraw;
|
||||
_yraw = _xraw;
|
||||
_xraw = t;
|
||||
break;
|
||||
case 2:
|
||||
_yraw = 4095 - _yraw;
|
||||
break;
|
||||
default:
|
||||
t = _yraw;
|
||||
_yraw = 4095 - _xraw;
|
||||
_xraw = 4095 - t;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
62
PacoMouseCYD/src/PacoMouseCYD/XPT2046.h
Normal file
@@ -0,0 +1,62 @@
|
||||
/* PacoMouseCYD throttle -- F. Cañada 2025-2026 -- https://usuaris.tinet.cat/fmco/
|
||||
Simple XPT2046 SPI/Bitbang interface for PacoMouseCYD
|
||||
*/
|
||||
|
||||
|
||||
#ifndef XPT2046_TS_h
|
||||
#define XPT2046_TS_h
|
||||
|
||||
#include "Arduino.h"
|
||||
#include "config.h"
|
||||
#ifdef USE_XPT2046_SPI
|
||||
#include <SPI.h>
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
uint16_t x;
|
||||
uint16_t y;
|
||||
uint16_t z;
|
||||
} TSPoint;
|
||||
|
||||
struct TouchCalibration {
|
||||
uint16_t xMin;
|
||||
uint16_t xMax;
|
||||
uint16_t yMin;
|
||||
uint16_t yMax;
|
||||
uint16_t rotation;
|
||||
};
|
||||
|
||||
class XPT2046_TS {
|
||||
public:
|
||||
XPT2046_TS(uint8_t mosiPin, uint8_t misoPin, uint8_t clkPin, uint8_t csPin);
|
||||
void begin(uint16_t width = 240, uint16_t height = 320);
|
||||
bool touched();
|
||||
TSPoint getTouch();
|
||||
void setRotation(uint8_t n);
|
||||
void setCalibration(uint16_t xMin, uint16_t xMax, uint16_t yMin, uint16_t yMax);
|
||||
TouchCalibration getCalibration();
|
||||
void readData(uint16_t *x, uint16_t *y, uint16_t *z);
|
||||
|
||||
private:
|
||||
uint8_t _mosiPin;
|
||||
uint8_t _misoPin;
|
||||
uint8_t _clkPin;
|
||||
uint8_t _csPin;
|
||||
uint8_t _irqPin;
|
||||
uint16_t _width;
|
||||
uint16_t _height;
|
||||
uint16_t _xraw;
|
||||
uint16_t _yraw;
|
||||
uint16_t _zraw;
|
||||
uint32_t _msraw;
|
||||
TouchCalibration cal;
|
||||
#ifdef USE_XPT2046_SPI
|
||||
SPIClass *hspi = NULL;
|
||||
#endif
|
||||
#ifdef USE_XPT2046_BITBANG
|
||||
uint16_t readSPI(byte command);
|
||||
#endif
|
||||
void update();
|
||||
};
|
||||
|
||||
#endif
|
||||
358
PacoMouseCYD/src/PacoMouseCYD/accessories.ino
Normal file
@@ -0,0 +1,358 @@
|
||||
/* PacoMouseCYD throttle -- F. Cañada 2025-2026 -- https://usuaris.tinet.cat/fmco/
|
||||
*/
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// ***** ACCESSORY FIFO *****
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
void initFIFO() {
|
||||
lastInFIFO = 0;
|
||||
firstOutFIFO = 0;
|
||||
cntFIFO = 0;
|
||||
stateFIFO = FIFO_EMPTY;
|
||||
}
|
||||
|
||||
|
||||
unsigned int readFIFO () {
|
||||
firstOutFIFO = (firstOutFIFO + 1 ) & 0x1F; // next one (hardcoded)
|
||||
cntFIFO--;
|
||||
return (accessoryFIFO[firstOutFIFO]);
|
||||
}
|
||||
|
||||
|
||||
void writeFIFO (uint16_t FAdr, uint8_t pos) {
|
||||
lastInFIFO = (lastInFIFO + 1 ) & 0x1F; // next one (hardcoded)
|
||||
cntFIFO++;
|
||||
if (pos > 0)
|
||||
FAdr |= 0x8000;
|
||||
accessoryFIFO[lastInFIFO] = FAdr; // save in FIFO
|
||||
}
|
||||
|
||||
|
||||
void sendAccessoryFIFO () {
|
||||
switch (stateFIFO) {
|
||||
case FIFO_ACC_CDU: // wait for CDU recharge
|
||||
case FIFO_EMPTY:
|
||||
if (cntFIFO > 0) { // activate accessory from FIFO
|
||||
lastAccessory = readFIFO();
|
||||
sendAccessory(lastAccessory & 0x7FFF, bitRead(lastAccessory, 15), true);
|
||||
setTimer(TMR_ACCESSORY, TIME_ACC_ON, TMR_ONESHOT);
|
||||
stateFIFO = FIFO_ACC_ON;
|
||||
DEBUG_MSG("Moving acc. %d-%d", lastAccessory & 0x7FFF, lastAccessory >> 15);
|
||||
}
|
||||
else
|
||||
stateFIFO = FIFO_EMPTY;
|
||||
break;
|
||||
case FIFO_ACC_ON: // deactivate accessory
|
||||
sendAccessory(lastAccessory & 0x7FFF, bitRead(lastAccessory, 15), false);
|
||||
setTimer(TMR_ACCESSORY, TIME_ACC_CDU, TMR_ONESHOT);
|
||||
stateFIFO = FIFO_ACC_CDU;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// ***** ACCESSORY *****
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
void moveAccessory(uint16_t FAdr, uint8_t pos) {
|
||||
writeFIFO(FAdr, pos); // put accessory in FIFO
|
||||
if (stateFIFO == FIFO_EMPTY) // if not pending accessories, force sending now
|
||||
sendAccessoryFIFO();
|
||||
}
|
||||
|
||||
void setAccAspect(uint16_t FAdr, uint16_t FAdr2, uint8_t aspect, uint16_t outs) {
|
||||
uint8_t pos;
|
||||
pos = aspect * 4;
|
||||
if (FAdr > 0) {
|
||||
if (bitRead(outs, pos)) {
|
||||
moveAccessory(FAdr, 0);
|
||||
}
|
||||
else {
|
||||
if (bitRead(outs, pos + 1))
|
||||
moveAccessory(FAdr, 1);
|
||||
}
|
||||
}
|
||||
if (FAdr2 > 0) {
|
||||
if (bitRead(outs, pos + 2)) {
|
||||
moveAccessory(FAdr2, 0);
|
||||
}
|
||||
else {
|
||||
if (bitRead(outs, pos + 3))
|
||||
moveAccessory(FAdr2, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// ***** PANEL *****
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
void deleteAccPanelElement(uint8_t pos) {
|
||||
accPanel[pos].type = ACC_UNDEF;
|
||||
accPanel[pos].currAspect = 0;
|
||||
accPanel[pos].addr = 0;
|
||||
accPanel[pos].addr2 = 0;
|
||||
accPanel[pos].activeOutput = 0;
|
||||
accPanel[pos].accName[0] = '\0';
|
||||
}
|
||||
|
||||
void loadDefaultAccPanel() {
|
||||
uint8_t n;
|
||||
for (n = 0; n < 16; n++) { // Default panel is all blank with only a keypad button
|
||||
deleteAccPanelElement(n);
|
||||
}
|
||||
accPanel[15].type = ACC_KEYPAD;
|
||||
}
|
||||
|
||||
|
||||
void updateAccPanel() {
|
||||
uint8_t n, type, aspect;
|
||||
|
||||
snprintf(panelNameBuf, PANEL_LNG + 1, panelNamesBuf[currPanel]);
|
||||
for (n = 0; n < 16; n++) {
|
||||
type = accPanel[n].type;
|
||||
aspect = accPanel[n].currAspect;
|
||||
snprintf(accNamesBuf[n], ACC_LNG + 1, accPanel[n].accName);
|
||||
fncData[FNC_ACC0 + n].num = accDef[type].num;
|
||||
fncData[FNC_ACC0 + n].idIcon = accDef[type].icon[aspect].fncIcon;
|
||||
fncData[FNC_ACC0 + n].color = accDef[type].icon[aspect].color;
|
||||
fncData[FNC_ACC0 + n].colorOn = accDef[type].icon[aspect].colorOn;
|
||||
fncData[FNC_ACC0 + n].backgnd = (type == ACC_UNDEF) ? COLOR_WHITE : COLOR_LIGHTGREY;
|
||||
buttonData[BUT_ACC_0 + n].backgnd = (type == ACC_UNDEF) ? COLOR_WHITE : COLOR_LIGHTGREY;
|
||||
}
|
||||
}
|
||||
|
||||
void saveCurrentAspects() {
|
||||
uint8_t n;
|
||||
for (n = 0; n < 16; n++)
|
||||
savedAspect[currPanel][n] = accPanel[n].currAspect;
|
||||
}
|
||||
|
||||
void getLastAspects() {
|
||||
uint8_t n;
|
||||
for (n = 0; n < 16; n++)
|
||||
accPanel[n].currAspect = savedAspect[currPanel][n];
|
||||
}
|
||||
|
||||
void deleteLastAspects() {
|
||||
uint8_t n;
|
||||
for (n = 0; n < 16; n++)
|
||||
accPanel[n].currAspect = 0;
|
||||
}
|
||||
|
||||
void initLastAspects() {
|
||||
uint8_t i, j;
|
||||
for (i = 0; i < 16; i++)
|
||||
for (j = 0; j < 16; j++)
|
||||
savedAspect[i][j] = 0;;
|
||||
}
|
||||
|
||||
void populateAccPanel() {
|
||||
loadDefaultAccPanel(); // Load panel data
|
||||
if (sdDetected) {
|
||||
if (loadAccPanel(SD))
|
||||
getLastAspects();
|
||||
else
|
||||
deleteLastAspects();
|
||||
}
|
||||
else {
|
||||
if (loadAccPanel(LittleFS))
|
||||
getLastAspects();
|
||||
else
|
||||
deleteLastAspects();
|
||||
}
|
||||
updateAccPanel();
|
||||
}
|
||||
|
||||
void accPanelClick(uint8_t pos) {
|
||||
uint16_t addr, outs;
|
||||
uint8_t type, aspect;
|
||||
currPanelAcc = pos;
|
||||
if (editAccessory) {
|
||||
paramChild = pos;
|
||||
type = accPanel[pos].type;
|
||||
fncData[FNC_ACC_TYPE].num = accDef[type].num;
|
||||
fncData[FNC_ACC_TYPE].idIcon = accDef[type].icon[0].fncIcon;
|
||||
fncData[FNC_ACC_TYPE].color = accDef[type].icon[0].color;
|
||||
fncData[FNC_ACC_TYPE].colorOn = accDef[type].icon[0].colorOn;
|
||||
encoderValue = type;
|
||||
encoderMax = ACC_MAX - 1;
|
||||
openWindow(WIN_ACC_TYPE);
|
||||
}
|
||||
else {
|
||||
type = accPanel[pos].type;
|
||||
switch (type) {
|
||||
case ACC_UNDEF:
|
||||
break;
|
||||
case ACC_KEYPAD:
|
||||
openWindow(WIN_ACC_CTRL);
|
||||
break;
|
||||
default:
|
||||
addr = accPanel[pos].addr;
|
||||
outs = accPanel[pos].activeOutput;
|
||||
switch (accDef[type].aspects) {
|
||||
case 2:
|
||||
aspect = (accPanel[pos].currAspect > 0) ? 0 : 1;
|
||||
accPanel[pos].currAspect = aspect;
|
||||
fncData[FNC_ACC0 + pos].idIcon = accDef[type].icon[aspect].fncIcon;
|
||||
fncData[FNC_ACC0 + pos].color = accDef[type].icon[aspect].color;
|
||||
fncData[FNC_ACC0 + pos].colorOn = accDef[type].icon[aspect].colorOn;
|
||||
setAccAspect(addr, 0, aspect, outs);
|
||||
newEvent(OBJ_BUTTON, BUT_ACC_0 + pos, EVNT_DRAW);
|
||||
break;
|
||||
case 3:
|
||||
currAccAspects = 3;
|
||||
winData[WIN_ACC_ASPECT].x = 30;
|
||||
winData[WIN_ACC_ASPECT].w = 180;
|
||||
buttonData[BUT_ACC_ASPECT0].x = 50;
|
||||
buttonData[BUT_ACC_ASPECT1].x = 100;
|
||||
buttonData[BUT_ACC_ASPECT2].x = 150;
|
||||
fncData[FNC_ASPECT0].x = 54;
|
||||
fncData[FNC_ASPECT0].idIcon = accDef[type].icon[0].fncIcon;
|
||||
fncData[FNC_ASPECT0].color = accDef[type].icon[0].color;
|
||||
fncData[FNC_ASPECT0].colorOn = accDef[type].icon[0].colorOn;
|
||||
fncData[FNC_ASPECT1].x = 104;
|
||||
fncData[FNC_ASPECT1].idIcon = accDef[type].icon[1].fncIcon;
|
||||
fncData[FNC_ASPECT1].color = accDef[type].icon[1].color;
|
||||
fncData[FNC_ASPECT1].colorOn = accDef[type].icon[1].colorOn;
|
||||
fncData[FNC_ASPECT2].x = 154;
|
||||
fncData[FNC_ASPECT2].idIcon = accDef[type].icon[2].fncIcon;
|
||||
fncData[FNC_ASPECT2].color = accDef[type].icon[2].color;
|
||||
fncData[FNC_ASPECT2].colorOn = accDef[type].icon[2].colorOn;
|
||||
openWindow(WIN_ACC_ASPECT);
|
||||
break;
|
||||
case 4:
|
||||
currAccAspects = 4;
|
||||
winData[WIN_ACC_ASPECT].x = 5;
|
||||
winData[WIN_ACC_ASPECT].w = 230;
|
||||
buttonData[BUT_ACC_ASPECT0].x = 25;
|
||||
buttonData[BUT_ACC_ASPECT1].x = 75;
|
||||
buttonData[BUT_ACC_ASPECT2].x = 125;
|
||||
buttonData[BUT_ACC_ASPECT3].x = 175;
|
||||
fncData[FNC_ASPECT0].x = 29;
|
||||
fncData[FNC_ASPECT0].idIcon = accDef[type].icon[0].fncIcon;
|
||||
fncData[FNC_ASPECT0].color = accDef[type].icon[0].color;
|
||||
fncData[FNC_ASPECT0].colorOn = accDef[type].icon[0].colorOn;
|
||||
fncData[FNC_ASPECT1].x = 79;
|
||||
fncData[FNC_ASPECT1].idIcon = accDef[type].icon[1].fncIcon;
|
||||
fncData[FNC_ASPECT1].color = accDef[type].icon[1].color;
|
||||
fncData[FNC_ASPECT1].colorOn = accDef[type].icon[1].colorOn;
|
||||
fncData[FNC_ASPECT2].x = 129;
|
||||
fncData[FNC_ASPECT2].idIcon = accDef[type].icon[2].fncIcon;
|
||||
fncData[FNC_ASPECT2].color = accDef[type].icon[2].color;
|
||||
fncData[FNC_ASPECT2].colorOn = accDef[type].icon[2].colorOn;
|
||||
fncData[FNC_ASPECT3].x = 179;
|
||||
fncData[FNC_ASPECT3].idIcon = accDef[type].icon[3].fncIcon;
|
||||
fncData[FNC_ASPECT3].color = accDef[type].icon[3].color;
|
||||
fncData[FNC_ASPECT3].colorOn = accDef[type].icon[3].colorOn;
|
||||
openWindow(WIN_ACC_ASPECT);
|
||||
break;
|
||||
default:
|
||||
buttonData[BUT_ACC_0 + pos].backgnd = COLOR_BLACK;
|
||||
drawObject(OBJ_BUTTON, BUT_ACC_0 + pos);
|
||||
buttonData[BUT_ACC_0 + pos].backgnd = COLOR_LIGHTGREY;
|
||||
setAccAspect(addr, 0, 0, outs);
|
||||
newEvent(OBJ_BUTTON, BUT_ACC_0 + pos, EVNT_DRAW);
|
||||
delay(80);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void accAspectClick(uint8_t aspect) {
|
||||
uint16_t addr, addr2, outs;
|
||||
uint8_t type;
|
||||
type = accPanel[currPanelAcc].type;
|
||||
accPanel[currPanelAcc].currAspect = aspect;
|
||||
fncData[FNC_ACC0 + currPanelAcc].idIcon = accDef[type].icon[aspect].fncIcon;
|
||||
fncData[FNC_ACC0 + currPanelAcc].color = accDef[type].icon[aspect].color;
|
||||
fncData[FNC_ACC0 + currPanelAcc].colorOn = accDef[type].icon[aspect].colorOn;
|
||||
addr = accPanel[currPanelAcc].addr;
|
||||
addr2 = accPanel[currPanelAcc].addr2;
|
||||
outs = accPanel[currPanelAcc].activeOutput;
|
||||
setAccAspect(addr, addr2, aspect, outs);
|
||||
}
|
||||
|
||||
|
||||
void accTypeClick() {
|
||||
uint8_t index, n;
|
||||
index = encoderValue;
|
||||
switch (index) {
|
||||
case ACC_UNDEF:
|
||||
alertWindow(ERR_ASK_SURE);
|
||||
break;
|
||||
case ACC_KEYPAD:
|
||||
editAccessory = false;
|
||||
winData[WIN_ACCESSORY].backgnd = COLOR_WHITE;
|
||||
deleteAccPanelElement(paramChild);
|
||||
accPanel[paramChild].type = ACC_KEYPAD;
|
||||
updateAccPanel();
|
||||
updateSpeedHID(); // set encoder
|
||||
closeWindow(WIN_ACC_TYPE);
|
||||
break;
|
||||
default:
|
||||
if (index != accPanel[paramChild].type) {
|
||||
currAccEdit.type = (accType)index;
|
||||
currAccEdit.addr = 0;
|
||||
currAccEdit.addr2 = 0;
|
||||
currAccEdit.currAspect = 0;
|
||||
currAccEdit.activeOutput = accOutDefault[index];
|
||||
currAccEdit.accName[0] = '\0';
|
||||
}
|
||||
else {
|
||||
currAccEdit = accPanel[paramChild];
|
||||
}
|
||||
snprintf(accKeybName, ACC_LNG + 1, currAccEdit.accName);
|
||||
snprintf(accKeybAddr1, ADDR_LNG + 1, "%d", currAccEdit.addr);
|
||||
snprintf(accKeybAddr2, ADDR_LNG + 1, "%d", currAccEdit.addr2);
|
||||
for (n = 0; n < 4; n++) {
|
||||
fncData[FNC_EDIT_ASPECT0 + n].idIcon = accDef[index].icon[n].fncIcon;
|
||||
fncData[FNC_EDIT_ASPECT0 + n].color = accDef[index].icon[n].color;
|
||||
fncData[FNC_EDIT_ASPECT0 + n].colorOn = accDef[index].icon[n].colorOn;
|
||||
}
|
||||
accOutUpdate();
|
||||
closeWindow(WIN_ACC_TYPE);
|
||||
openWindow(WIN_ACC_EDIT);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void accOutUpdate() {
|
||||
uint8_t n;
|
||||
for (n = 0; n < 16; n += 2) {
|
||||
buttonData[BUT_ACC_OUT0 + n].backgnd = bitRead(currAccEdit.activeOutput, n) ? COLOR_RED : COLOR_LIGHTBLACK;
|
||||
buttonData[BUT_ACC_OUT0 + n + 1].backgnd = bitRead(currAccEdit.activeOutput, n + 1) ? COLOR_GREEN : COLOR_LIGHTBLACK;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void accOutClick(uint8_t out) {
|
||||
uint8_t outR, outG;
|
||||
outR = out & 0xFE;
|
||||
outG = out | 0x01;
|
||||
currAccEdit.activeOutput ^= bit(out);
|
||||
if (bitRead(out, 0)) { // green
|
||||
if (bitRead(currAccEdit.activeOutput, outG))
|
||||
bitClear(currAccEdit.activeOutput, outR);
|
||||
}
|
||||
else { // red
|
||||
if (bitRead(currAccEdit.activeOutput, outR))
|
||||
bitClear(currAccEdit.activeOutput, outG);
|
||||
}
|
||||
accOutUpdate();
|
||||
newEvent(OBJ_BUTTON, BUT_ACC_OUT0 + outR, EVNT_DRAW);
|
||||
newEvent(OBJ_BUTTON, BUT_ACC_OUT0 + outG, EVNT_DRAW);
|
||||
}
|
||||
|
||||
|
||||
void updateAccChange() {
|
||||
accPanel[paramChild] = currAccEdit;
|
||||
updateAccPanel();
|
||||
accPanelChanged = true;
|
||||
}
|
||||
184
PacoMouseCYD/src/PacoMouseCYD/config.h
Normal file
@@ -0,0 +1,184 @@
|
||||
/* PacoMouseCYD throttle -- F. Cañada 2025-2026 -- https://usuaris.tinet.cat/fmco/
|
||||
*/
|
||||
|
||||
#ifndef PACOMOUSECYD_CFG_H
|
||||
#define PACOMOUSECYD_CFG_H
|
||||
|
||||
#define CYD_TFT_28 0 // Cheap Yellow Display 2.8"
|
||||
#define CYD_TFT_24 1 // Cheap Yellow Display 2.4"
|
||||
#define CYD_TFT_32 2 // Cheap Yellow Display 3.2"
|
||||
#define CYD_USER_DEFINED 3 // User defined board
|
||||
|
||||
#define PRESENT 1
|
||||
#define UNUSED 0
|
||||
|
||||
#define MODE_SPI 0
|
||||
#define MODE_BITBANG 1
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// ***** USER OPTIONS *****
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
// Seleccione la version hardware del CYD (Cheap Yellow Display) - Select the hardware version of CYD (Cheap Yellow Display): CYD_TFT_28 / CYD_TFT_24 / CYD_TFT_32 / CYD_USER_DEFINED
|
||||
// Use el archivo User_Setup.h correcto para la libreria TFT_eSPI - Use the correct User_Setup.h file for library TFT_eSPI
|
||||
|
||||
#define CYD_HW_VERSION CYD_TFT_28
|
||||
|
||||
// Max. locomotoras guardadas en stack (hasta 254) - Max. locomotives saved in stack (up to 254):
|
||||
|
||||
#define LOCOS_IN_STACK 100
|
||||
|
||||
// Delimitador en fichero CSV - CSV file delimiter: ';' / ','
|
||||
#define CSV_FILE_DELIMITER ';'
|
||||
|
||||
|
||||
|
||||
#if (CYD_HW_VERSION == CYD_USER_DEFINED)
|
||||
////////////////////////////////////////////////////////////
|
||||
// ***** USER DEFINED HARDWARE *****
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
// Seleccione el modo de acceso al chip XPT2046 - Select XPT2046 chip access mode : MODE_SPI / MODE_BITBANG
|
||||
#define XPT_MODE MODE_SPI
|
||||
|
||||
// Seleccione rotacion de la pantalla tactil - Select Touchscreen rotation: 0 / 1 / 2 / 3
|
||||
#define XPT_ROTATION 3
|
||||
|
||||
// Touchscreen
|
||||
#define XPT2046_IRQ 36 // T_IRQ
|
||||
#define XPT2046_MOSI 13 // T_DIN
|
||||
#define XPT2046_MISO 12 // T_OUT
|
||||
#define XPT2046_CLK 14 // T_CLK
|
||||
#define XPT2046_CS 33 // T_CS
|
||||
|
||||
// Seleccione si usa el LED RGB - Select if use the RGB LED: PRESENT / UNUSED
|
||||
#define USE_RGB_LED PRESENT
|
||||
|
||||
//RGB LED Pins
|
||||
#define RGB_LED_R 4
|
||||
#define RGB_LED_G 17
|
||||
#define RGB_LED_B 16
|
||||
|
||||
//SD Pins
|
||||
#define SD_CS 5
|
||||
|
||||
// Encoder Pins
|
||||
#define ENCODER_A 22
|
||||
#define ENCODER_B 21
|
||||
#define ENCODER_SW 35
|
||||
|
||||
|
||||
#endif
|
||||
////////////////////////////////////////////////////////////
|
||||
// ***** END OF USER DEFINED HARDWARE *****
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// ***** END OF USER OPTIONS *****
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#if (CYD_HW_VERSION == CYD_TFT_28)
|
||||
#define USE_CYD_28 1 // Cheap Yellow Display 2.8" (2432S028R)
|
||||
#endif
|
||||
#if (CYD_HW_VERSION == CYD_TFT_24)
|
||||
#define USE_CYD_24 1 // Cheap Yellow Display 2.4" (2432S024R)
|
||||
#endif
|
||||
#if (CYD_HW_VERSION == CYD_TFT_32)
|
||||
#define USE_CYD_24 1 // Cheap Yellow Display 3.2" (2432S032R)
|
||||
#endif
|
||||
#if (CYD_HW_VERSION == CYD_USER_DEFINED)
|
||||
#if (XPT_MODE == MODE_SPI) // Cheap Yellow Display other type
|
||||
#define USE_XPT2046_SPI
|
||||
#endif
|
||||
#if (XPT_MODE == MODE_BITBANG)
|
||||
#define USE_XPT2046_BITBANG
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(USE_CYD_28) && defined(USE_CYD_24)
|
||||
#error Seleccione solo un tipo de CYD (Cheap Yellow Display) - Select only one type of CYD (Cheap Yellow Display)
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#define USER_MIN_BL 64 // User min backlight
|
||||
#define SYS_MIN_BL 32 // System inactivity backlight
|
||||
|
||||
#ifdef USE_CYD_28
|
||||
// Touchscreen pins
|
||||
#define XPT2046_IRQ 36 // T_IRQ
|
||||
#define XPT2046_MOSI 32 // T_DIN
|
||||
#define XPT2046_MISO 39 // T_OUT
|
||||
#define XPT2046_CLK 25 // T_CLK
|
||||
#define XPT2046_CS 33 // T_CS
|
||||
|
||||
#define USE_XPT2046_BITBANG
|
||||
|
||||
#define XPT_ROTATION 0
|
||||
|
||||
/*
|
||||
// I2C pins
|
||||
#define I2C_SDA 27
|
||||
#define I2C_SCL 22
|
||||
*/
|
||||
//RGB LED
|
||||
#define RGB_LED_R 4
|
||||
#define RGB_LED_G 16
|
||||
#define RGB_LED_B 17
|
||||
|
||||
#define USE_RGB_LED PRESENT
|
||||
|
||||
//SD Pins
|
||||
#define SD_CS 5
|
||||
|
||||
// Encoder
|
||||
#define ENCODER_A 22
|
||||
#define ENCODER_B 27
|
||||
#define ENCODER_SW 35
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef USE_CYD_24
|
||||
// Touchscreen pins
|
||||
#define XPT2046_IRQ 36 // T_IRQ
|
||||
#define XPT2046_MOSI 13 // T_DIN
|
||||
#define XPT2046_MISO 12 // T_OUT
|
||||
#define XPT2046_CLK 14 // T_CLK
|
||||
#define XPT2046_CS 33 // T_CS
|
||||
|
||||
#define USE_XPT2046_SPI
|
||||
|
||||
#define XPT_ROTATION 0
|
||||
/*
|
||||
// I2C pins
|
||||
#define I2C_SDA 21
|
||||
#define I2C_SCL 22
|
||||
*/
|
||||
//RGB LED
|
||||
#define RGB_LED_R 4
|
||||
#define RGB_LED_G 17
|
||||
#define RGB_LED_B 16
|
||||
|
||||
#define USE_RGB_LED PRESENT
|
||||
|
||||
//SD Pins
|
||||
#define SD_CS 5
|
||||
|
||||
// Encoder
|
||||
#define ENCODER_A 22
|
||||
#define ENCODER_B 21
|
||||
#define ENCODER_SW 35
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
956
PacoMouseCYD/src/PacoMouseCYD/ecos.ino
Normal file
@@ -0,0 +1,956 @@
|
||||
/* PacoMouseCYD throttle -- F. Cañada 2025-2026 -- https://usuaris.tinet.cat/fmco/
|
||||
|
||||
This software and associated files are a DIY project that is not intended for commercial use.
|
||||
This software uses libraries with different licenses, follow all their different terms included.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED.
|
||||
|
||||
Sources are only provided for building and uploading to the device.
|
||||
You are not allowed to modify the source code or fork/publish this project.
|
||||
Commercial use is forbidden.
|
||||
*/
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// ***** ECoS SOPORTE *****
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
void sendMsgECOS (char *buf) {
|
||||
bool recvAnswer;
|
||||
uint32_t timeoutECoS;
|
||||
Client.write(buf);
|
||||
#ifdef DEBUG
|
||||
Serial.print(F("Send: "));
|
||||
Serial.println(buf);
|
||||
#endif
|
||||
timeoutECoS = millis();
|
||||
recvAnswer = false;
|
||||
while ((millis() - timeoutECoS < 50) && (!recvAnswer)) // wait answer for 50ms
|
||||
recvAnswer = ECoSProcess();
|
||||
}
|
||||
|
||||
|
||||
void requestViews () {
|
||||
snprintf(cmd, 64, "get(%d, info)\n", ID_ECOS); // ECoS info
|
||||
sendMsgECOS(cmd);
|
||||
snprintf(cmd, 64, "request(%d, view)\n", ID_ECOS); // ECoS manager (power)
|
||||
sendMsgECOS(cmd);
|
||||
snprintf(cmd, 64, "request(%d, view)\n", ID_LOKMANAGER); // Lok manager
|
||||
sendMsgECOS(cmd);
|
||||
snprintf(cmd, 64, "request(%d, view)\n", ID_S88FEEDBACK); // S88 feedback
|
||||
sendMsgECOS(cmd);
|
||||
getStatusECoS();
|
||||
}
|
||||
|
||||
void getStatusECoS() {
|
||||
snprintf(cmd, 64, "get(%d, status)\n", ID_ECOS); // Power status
|
||||
sendMsgECOS(cmd);
|
||||
}
|
||||
|
||||
void requestLocoList() {
|
||||
snprintf(cmd, 64, "queryObjects(%d, addr, name)\n", ID_LOKMANAGER); // only address and name, protocol not needed at the moment
|
||||
sendMsgECOS(cmd);
|
||||
}
|
||||
|
||||
|
||||
void infoLocomotoraECoS (unsigned int ID) {
|
||||
byte n;
|
||||
if (ID > 999) {
|
||||
bitClear(locoData[myLocoData].mySteps, 3);
|
||||
snprintf(cmd, 64, "request(%d, view, control[events])\n", ID); // View Locomotive data updates
|
||||
sendMsgECOS(cmd);
|
||||
snprintf(cmd, 64, "get(%d, speed, dir, speedstep)\n", ID); // Speed, dir & steps
|
||||
sendMsgECOS(cmd);
|
||||
for (n = 0; n < 29; n++) {
|
||||
snprintf(cmd, 64, "get(%d, func[%d])\n", ID, n); // Functions
|
||||
sendMsgECOS(cmd);
|
||||
if (appVer > 2)
|
||||
snprintf(cmd, 64, "get(%d, funcicon[%d])\n", ID, n); // Icon functions
|
||||
else
|
||||
snprintf(cmd, 64, "get(%d, funcsymbol[%d])\n", ID, n); // Icon functions
|
||||
sendMsgECOS(cmd);
|
||||
}
|
||||
setTimer (TMR_FNC_ECOS, 10, TMR_ONESHOT);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void releaseLocoECoS() {
|
||||
if (locoData[myLocoData].myLocoID) {
|
||||
snprintf(cmd, 64, "release(%d, control)\n", locoData[myLocoData].myLocoID); // release control
|
||||
sendMsgECOS(cmd);
|
||||
snprintf(cmd, 64, "release(%d, view)\n", locoData[myLocoData].myLocoID); // release updates
|
||||
sendMsgECOS(cmd);
|
||||
}
|
||||
}
|
||||
|
||||
void checkControlLoco() {
|
||||
if (bitRead(locoData[myLocoData].mySteps, 3)) {
|
||||
bitClear(locoData[myLocoData].mySteps, 3);
|
||||
snprintf(cmd, 64, "request(%d, control[events], force)\n", locoData[myLocoData].myLocoID); // force control
|
||||
sendMsgECOS(cmd);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void changeDirectionECoS() {
|
||||
checkControlLoco();
|
||||
snprintf(cmd, 64, "set(%d, dir[%d])\n", locoData[myLocoData].myLocoID, (locoData[myLocoData].myDir & 0x80) ? 0 : 1); // direction (1=rückwärts).
|
||||
sendMsgECOS(cmd);
|
||||
}
|
||||
|
||||
|
||||
void locoOperationSpeedECoS() {
|
||||
checkControlLoco();
|
||||
snprintf(cmd, 64, "set(%d, speed[%d])\n", locoData[myLocoData].myLocoID, locoData[myLocoData].mySpeed); // Speed
|
||||
sendMsgECOS(cmd);
|
||||
}
|
||||
|
||||
byte getCurrentStepECoS() {
|
||||
return (mySpeedStep);
|
||||
}
|
||||
|
||||
void funcOperationsECoS (byte fnc) {
|
||||
byte stat;
|
||||
checkControlLoco();
|
||||
stat = (bitRead(locoData[myLocoData].myFunc.Bits, fnc)) ? 1 : 0;
|
||||
snprintf(cmd, 64, "set(%d, func[%d,%d])\n", locoData[myLocoData].myLocoID, fnc, stat); // Function
|
||||
sendMsgECOS(cmd);
|
||||
}
|
||||
|
||||
|
||||
void setAccessoryECoS(unsigned int FAdr, int pair, bool activate) {
|
||||
char pos;
|
||||
if (activate) {
|
||||
pos = (pair > 0) ? 'g' : 'r';
|
||||
snprintf(cmd, 64, "set(%d, switch[%d%c])\n", ID_SWMANAGER, FAdr, pos); // Directly setting a port.
|
||||
sendMsgECOS(cmd);
|
||||
}
|
||||
}
|
||||
|
||||
void resumeOperationsECoS () {
|
||||
snprintf(cmd, 64, "set(%d, go)\n", ID_ECOS); // Track on
|
||||
sendMsgECOS(cmd);
|
||||
}
|
||||
|
||||
|
||||
void emergencyOffECoS() {
|
||||
snprintf(cmd, 64, "set(%d, stop)\n", ID_ECOS); // Track off
|
||||
sendMsgECOS(cmd);
|
||||
}
|
||||
|
||||
void showTrkECoS() {
|
||||
if (csStatus > 0) {
|
||||
stopTimer (TMR_POWER);
|
||||
iconData[ICON_POWER].color = COLOR_GREEN;
|
||||
if ((isWindow(WIN_THROTTLE)) || (isWindow(WIN_STEAM)))
|
||||
newEvent(OBJ_ICON, ICON_POWER, EVNT_DRAW);
|
||||
if (isWindow(WIN_STA_PLAY)) {
|
||||
fncData[FNC_STA_RAYO].state = false;
|
||||
newEvent(OBJ_FNC, FNC_STA_RAYO, EVNT_DRAW);
|
||||
}
|
||||
if (isWindow(WIN_ALERT)) {
|
||||
switch (errType) {
|
||||
case ERR_SERV:
|
||||
case ERR_STOP:
|
||||
case ERR_CV:
|
||||
closeWindow(WIN_ALERT);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
iconData[ICON_POWER].color = COLOR_RED; // Power off
|
||||
setTimer (TMR_POWER, 5, TMR_PERIODIC); // Flash power icon
|
||||
if ((isWindow(WIN_THROTTLE)) || (isWindow(WIN_STEAM)))
|
||||
newEvent(OBJ_ICON, ICON_POWER, EVNT_DRAW);
|
||||
if (isWindow(WIN_STA_PLAY)) {
|
||||
fncData[FNC_STA_RAYO].state = true;
|
||||
newEvent(OBJ_FNC, FNC_STA_RAYO, EVNT_DRAW);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void readCVECoS (unsigned int adr, byte stepPrg) {
|
||||
if (!modeProg) { // Read only in Direct mode
|
||||
snprintf(cmd, 64, "request(%d, view)\n", ID_PRGMANAGER); // Programming manager
|
||||
sendMsgECOS(cmd);
|
||||
requestedCV = true;
|
||||
snprintf(cmd, 64, "set(%d, mode[readdccdirect], cv[%d])\n", ID_PRGMANAGER, adr);
|
||||
sendMsgECOS(cmd);
|
||||
}
|
||||
progStepCV = stepPrg;
|
||||
}
|
||||
|
||||
|
||||
void writeCVECoS (unsigned int adr, unsigned int data, byte stepPrg) {
|
||||
if (modeProg) {
|
||||
snprintf(cmd, 64, "request(%d, view)\n", ID_POMMANAGER); // PoM Programming manager
|
||||
sendMsgECOS(cmd);
|
||||
snprintf(cmd, 64, "set(%d, mode[writedccpomloco], addr[%d], cv[%d,%d])\n", ID_POMMANAGER, locoData[myLocoData].myAddr.address, adr, data); // Operations Mode Programming byte mode write request
|
||||
}
|
||||
else {
|
||||
snprintf(cmd, 64, "request(%d,view)\n", ID_PRGMANAGER); // Programming manager
|
||||
sendMsgECOS(cmd);
|
||||
snprintf(cmd, 64, "set(%d, mode[writedccdirect], cv[%d,%d])\n", ID_PRGMANAGER, adr, data);
|
||||
}
|
||||
requestedCV = true;
|
||||
sendMsgECOS(cmd);
|
||||
progStepCV = stepPrg;
|
||||
DEBUG_MSG("Write CV%d = %d", adr, data);
|
||||
}
|
||||
|
||||
|
||||
void exitProgrammingECoS() {
|
||||
if (requestedCV) {
|
||||
snprintf(cmd, 64, "release(%d,view)\n", ID_PRGMANAGER); // Programming manager
|
||||
sendMsgECOS(cmd);
|
||||
snprintf(cmd, 64, "release(%d, view)\n", ID_POMMANAGER); // PoM Programming manager
|
||||
sendMsgECOS(cmd);
|
||||
requestedCV = false;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// ***** ECoS DECODE *****
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
bool ECoSProcess() {
|
||||
char chr;
|
||||
bool rcvMsg;
|
||||
rcvMsg = false;
|
||||
while (Client.available()) {
|
||||
chr = Client.read();
|
||||
if (chr == '\n') {
|
||||
if (inputLength > 0) {
|
||||
inputBuffer[inputLength] = 0;
|
||||
rcvMsg = ECoSDecode();
|
||||
}
|
||||
inputLength = 0;
|
||||
}
|
||||
else {
|
||||
inputBuffer[inputLength++] = chr;
|
||||
if (inputLength >= BUF_LNG) // line too long, discard
|
||||
inputLength = 0;
|
||||
}
|
||||
}
|
||||
yield();
|
||||
if (progFinished) { // fin de lectura/programacion CV
|
||||
progFinished = false;
|
||||
endProg();
|
||||
}
|
||||
return rcvMsg;
|
||||
}
|
||||
|
||||
|
||||
//============= Scanning ==================
|
||||
|
||||
// Simplified scanning based on C compiler method. https://github.com/DoctorWkt/acwj
|
||||
|
||||
char getChar () { // get a chr form input buffer
|
||||
return inputBuffer[posFile++];
|
||||
}
|
||||
|
||||
|
||||
void putBack(char c) { // Put back an unwanted character
|
||||
putBackChr = c;
|
||||
posFile--; // set reading position back
|
||||
}
|
||||
|
||||
|
||||
char next() { // Get the next character from the input stream.
|
||||
char c;
|
||||
if (putBackChr) { // Use the character put back if there is one
|
||||
c = putBackChr;
|
||||
putBackChr = 0;
|
||||
posFile++;
|
||||
}
|
||||
else
|
||||
c = getChar(); // Read from input stream
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
char skip() { // Skip past input that we don't need to deal with, i.e. whitespace, newlines. Return the first character we do need to deal with.
|
||||
char c;
|
||||
c = next();
|
||||
while (' ' == c || '\t' == c || '\n' == c || '\r' == c) {
|
||||
c = next();
|
||||
}
|
||||
return (c);
|
||||
}
|
||||
|
||||
|
||||
void discardLine() { // ignore rest of the line
|
||||
putBackChr = 0;
|
||||
inputBuffer[posFile] = 0;
|
||||
}
|
||||
|
||||
|
||||
int scanInt(char c) { // Scan and return an integer literal value from the input stream.
|
||||
int val;
|
||||
val = 0;
|
||||
while (isDigit(c)) { // Convert each character into an int value
|
||||
val = val * 10 + (c - '0');
|
||||
c = next();
|
||||
}
|
||||
putBack(c); // We hit a non-integer character, put it back.
|
||||
return val;
|
||||
}
|
||||
|
||||
|
||||
int scanIdent(int c, char *buf, int lim) { // Scan an identifier from the input file and store it in buf[]. Return the identifier's length
|
||||
int i = 0;
|
||||
|
||||
while (isalpha(c) || isdigit(c) || (c == '-') || (c == '_')) { // Allow digits, alpha and underscore -
|
||||
if (lim - 1 == i) { // Error if we hit the identifier length limit, else append to buf[] and get next character
|
||||
return (0);
|
||||
} else if (i < lim - 1) {
|
||||
buf[i++] = c;
|
||||
}
|
||||
c = next();
|
||||
}
|
||||
putBack(c); // We hit a non-valid character, put it back. NUL-terminate the buf[] and return the length
|
||||
buf[i] = '\0';
|
||||
return (i);
|
||||
}
|
||||
|
||||
|
||||
int scanStr (char *buf) { // Scan in a string literal from the input file, and store it in buf[]. Return the length of the string.
|
||||
int i, c;
|
||||
for (i = 0; i < TEXTLEN - 1; i++) { // Loop while we have enough buffer space
|
||||
// Get the next char and append to buf
|
||||
// Return when we hit the ending double quote
|
||||
if ((c = next()) == '"') {
|
||||
buf[i] = 0;
|
||||
return (i);
|
||||
}
|
||||
buf[i] = c;
|
||||
}
|
||||
// Ran out of buf[] space
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
int ident2HEX (char *buf, int *value) { // convert an idetifier (xNNNN) to hex value
|
||||
int val, n;
|
||||
char c;
|
||||
val = 0;
|
||||
n = 1;
|
||||
if (buf[0] == 'x') {
|
||||
while (buf[n]) {
|
||||
c = buf[n++];
|
||||
val *= 16;
|
||||
if (isDigit(c)) {
|
||||
val += (c - '0');
|
||||
}
|
||||
else {
|
||||
c &= 0xDF;
|
||||
val += ((c - 'A') + 10);
|
||||
}
|
||||
}
|
||||
*value = val;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// Given a word from the input, return the matching keyword token number or 0 if it's not a keyword.
|
||||
// Switch on the first letter so that we don't have to waste time strcmp()ing against all the keywords.
|
||||
int keyword(char *s) {
|
||||
switch (*s) {
|
||||
case 'R':
|
||||
if (!strcmp(s, "REPLY"))
|
||||
return (T_REPLY);
|
||||
break;
|
||||
case 'E':
|
||||
if (!strcmp(s, "END"))
|
||||
return (T_END);
|
||||
if (!strcmp(s, "EVENT"))
|
||||
return (T_EVENT);
|
||||
if (!strcmp(s, "ECoS2"))
|
||||
return (T_ECOS2);
|
||||
if (!strcmp(s, "ECoS"))
|
||||
return (T_ECOS);
|
||||
break;
|
||||
case 'O':
|
||||
if (!strcmp(s, "OK"))
|
||||
return (T_OK);
|
||||
break;
|
||||
case 'C':
|
||||
if (!strcmp(s, "CONTROL_LOST"))
|
||||
return (T_LOST);
|
||||
if (!strcmp(s, "CentralStation"))
|
||||
return (T_CS1);
|
||||
break;
|
||||
case 'G':
|
||||
if (!strcmp(s, "GO"))
|
||||
return (T_GO);
|
||||
break;
|
||||
case 'S':
|
||||
if (!strcmp(s, "STOP"))
|
||||
return (T_STOP);
|
||||
if (!strcmp(s, "SHUTDOWN"))
|
||||
return (T_SHUTDWN);
|
||||
break;
|
||||
case 'A':
|
||||
if (!strcmp(s, "ApplicationVersion"))
|
||||
return (T_APPV);
|
||||
break;
|
||||
case 'a':
|
||||
if (!strcmp(s, "addr"))
|
||||
return (T_ADDR);
|
||||
break;
|
||||
case 'c':
|
||||
if (!strcmp(s, "control"))
|
||||
return (T_CONTROL);
|
||||
if (!strcmp(s, "cv"))
|
||||
return (T_CV);
|
||||
break;
|
||||
case 'd':
|
||||
if (!strcmp(s, "dir"))
|
||||
return (T_DIR);
|
||||
break;
|
||||
case 'e':
|
||||
if (!strcmp(s, "error"))
|
||||
return (T_ERROR);
|
||||
break;
|
||||
case 'f':
|
||||
if (!strcmp(s, "funcsymbol")) // ECoS replies 'funcsymbol'
|
||||
return (T_FSYMBOL);
|
||||
if (!strcmp(s, "funcsymb")) // CS1 replies 'funcsymb'
|
||||
return (T_FSYMB);
|
||||
if (!strcmp(s, "funcicon"))
|
||||
return (T_FICON);
|
||||
if (!strcmp(s, "func"))
|
||||
return (T_FUNC);
|
||||
if (!strcmp(s, "force"))
|
||||
return (T_FORCE);
|
||||
break;
|
||||
case 'g':
|
||||
if (!strcmp(s, "get"))
|
||||
return (T_GET);
|
||||
break;
|
||||
case 'm':
|
||||
if (!strcmp(s, "msg"))
|
||||
return (T_MSG);
|
||||
break;
|
||||
case 'n':
|
||||
if (!strcmp(s, "name"))
|
||||
return (T_NAME);
|
||||
break;
|
||||
case 'o':
|
||||
if (!strcmp(s, "ok"))
|
||||
return (T_CVOK);
|
||||
if (!strcmp(s, "other"))
|
||||
return (T_OTHER);
|
||||
break;
|
||||
case 'p':
|
||||
if (!strcmp(s, "protocol"))
|
||||
return (T_PROT);
|
||||
break;
|
||||
case 'q':
|
||||
if (!strcmp(s, "queryObjects"))
|
||||
return (T_QOBJ);
|
||||
break;
|
||||
case 'r':
|
||||
if (!strcmp(s, "request"))
|
||||
return (T_REQ);
|
||||
if (!strcmp(s, "release"))
|
||||
return (T_RELEASE);
|
||||
break;
|
||||
case 's':
|
||||
if (!strcmp(s, "status2"))
|
||||
return (T_STATUS2);
|
||||
if (!strcmp(s, "status"))
|
||||
return (T_STATUS);
|
||||
if (!strcmp(s, "state"))
|
||||
return (T_STATE);
|
||||
if (!strcmp(s, "speedstep"))
|
||||
return (T_STEPS);
|
||||
if (!strcmp(s, "speed"))
|
||||
return (T_SPEED);
|
||||
if (!strcmp(s, "set"))
|
||||
return (T_SET);
|
||||
if (!strcmp(s, "switch"))
|
||||
return (T_SWITCH);
|
||||
break;
|
||||
case 'v':
|
||||
if (!strcmp(s, "view"))
|
||||
return (T_VIEW);
|
||||
break;
|
||||
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
//=========== Lexical ===============
|
||||
|
||||
int scan(struct token *t) { // Scan and return the next token found in the input. Return 1 if token valid, 0 if no tokens left.
|
||||
char c;
|
||||
|
||||
c = skip(); // Skip whitespace
|
||||
switch (c) { // Determine the token based on the input character
|
||||
case 0: // EOF
|
||||
return (0);
|
||||
case '(':
|
||||
t->token = T_LPARENT;
|
||||
t->intvalue = posFile;
|
||||
break;
|
||||
case ')':
|
||||
t->token = T_RPARENT;
|
||||
t->intvalue = posFile;
|
||||
break;
|
||||
case '[':
|
||||
t->token = T_LBRACKET;
|
||||
t->intvalue = posFile;
|
||||
break;
|
||||
case ']':
|
||||
t->token = T_RBRACKET;
|
||||
t->intvalue = posFile;
|
||||
break;
|
||||
case '<':
|
||||
t->token = T_START;
|
||||
t->intvalue = posFile;
|
||||
break;
|
||||
case '>':
|
||||
t->token = T_ENDB;
|
||||
t->intvalue = posFile;
|
||||
break;
|
||||
case ',':
|
||||
t->token = T_COMMA;
|
||||
t->intvalue = posFile;
|
||||
break;
|
||||
case '#':
|
||||
t->token = T_NULL;
|
||||
t->intvalue = posFile;
|
||||
discardLine();
|
||||
break;
|
||||
case '"':
|
||||
scanStr(Text);
|
||||
t->token = T_STRLIT;
|
||||
break;
|
||||
default:
|
||||
if (isDigit(c)) { // If it's a digit, scan the literal integer value in
|
||||
t->intvalue = scanInt(c);
|
||||
t->token = T_INTLIT;
|
||||
break;
|
||||
}
|
||||
if (isAlpha(c)) {
|
||||
scanIdent(c, Text, TEXTLEN);
|
||||
tokenType = keyword(Text);
|
||||
if (tokenType) {
|
||||
t->token = tokenType;
|
||||
break;
|
||||
}
|
||||
t->token = T_IDENT; // Not a recognised keyword, so it must be an identifier
|
||||
t->intvalue = Text[0];
|
||||
break;
|
||||
}
|
||||
return (0);
|
||||
break;
|
||||
}
|
||||
//DEBUG_MSG("Token found: %s", tokstr[T.token]);
|
||||
return (1); // We found a token
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
|
||||
bool ECoSDecode() {
|
||||
bool endMsg;
|
||||
#ifdef DEBUG
|
||||
Serial.print(F("Recv: "));
|
||||
Serial.println(inputBuffer);
|
||||
#endif
|
||||
posFile = 0;
|
||||
putBackChr = 0;
|
||||
endMsg = false;
|
||||
while (scan(&T)) {
|
||||
switch (msgDecodePhase) {
|
||||
case MSG_WAIT: // wait '<' for start of msg
|
||||
if (T.token == T_START)
|
||||
msgDecodePhase = MSG_START;
|
||||
break;
|
||||
case MSG_START:
|
||||
switch (T.token) {
|
||||
case T_REPLY: // receiving a REPLY
|
||||
msgDecodePhase = MSG_REPLY;
|
||||
break;
|
||||
case T_EVENT: // receiving an EVENT
|
||||
msgDecodePhase = MSG_EVENT;
|
||||
break;
|
||||
case T_END: // receiving END
|
||||
msgDecodePhase = MSG_END;
|
||||
break;
|
||||
default:
|
||||
msgDecodePhase = MSG_WAIT; // others not supported
|
||||
break;
|
||||
}
|
||||
idManager = 0;
|
||||
break;
|
||||
case MSG_END:
|
||||
if (T.token == T_INTLIT) { // get the error code
|
||||
errCode = T.intvalue;
|
||||
discardLine();
|
||||
msgDecodePhase = MSG_WAIT; // discard rest of message
|
||||
switch (errCode) {
|
||||
case 25: // NERROR_NOCONTROL
|
||||
bitSet(locoData[myLocoData].mySteps, 3);
|
||||
break;
|
||||
case 15: // NERROR_UNKNOWNID
|
||||
if (requestedCV) {
|
||||
if (progStepCV != PRG_IDLE) {
|
||||
CVdata = 0x0600;
|
||||
progFinished = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
DEBUG_MSG("END Error code: %d", errCode);
|
||||
}
|
||||
endMsg = true;
|
||||
break;
|
||||
case MSG_EVENT:
|
||||
if (T.token == T_INTLIT) // get the event manager
|
||||
idManager = T.intvalue;
|
||||
discardLine();
|
||||
msgDecodePhase = MSG_EVENTBODY; // discard rest of line
|
||||
DEBUG_MSG("Manager ID: %d", idManager);
|
||||
if ((idManager == ID_PRGMANAGER) || (idManager == ID_POMMANAGER)) {
|
||||
lastNumValue = 0x0600;
|
||||
}
|
||||
break;
|
||||
case MSG_REPLY: // <REPLY get(1,status)>
|
||||
idCommand = T.token; // get ...
|
||||
scan(&T); // (
|
||||
scan(&T); // id manager
|
||||
if (T.token == T_INTLIT) {
|
||||
idManager = T.intvalue;
|
||||
//DEBUG_MSG("Reply: %s id: %d", tokstr[idCommand], idManager);
|
||||
if ((idManager == ID_LOKMANAGER) && (idCommand == T_QOBJ)) { // list of loks
|
||||
numLoks = 0;
|
||||
initLocos();
|
||||
DEBUG_MSG("Roster list cleared");
|
||||
}
|
||||
|
||||
/*
|
||||
if ((idManager == ID_SWMANAGER) && (idCommand == T_GET)) { // info of turnout <REPLY get(11, switch[12g])>
|
||||
//DEBUG_MSG("Switch manager get");
|
||||
scan(&T); // ,
|
||||
scan(&T); // switch
|
||||
if (T.token == T_SWITCH) {
|
||||
//DEBUG_MSG("Get turnout");
|
||||
scan(&T); // [
|
||||
scan(&T); // 12g
|
||||
if (T.token == T_INTLIT) // 12
|
||||
scan(&T);
|
||||
if (T.token == T_IDENT) { // Text is "g" or could be "DCC12g"
|
||||
lastTxtChar = Text[strlen(Text) - 1];
|
||||
DEBUG_MSG("Info turnout pos: %s - %c", Text, lastTxtChar);
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
discardLine();
|
||||
msgDecodePhase = MSG_REPLYBODY;
|
||||
break;
|
||||
case MSG_EVENTBODY:
|
||||
switch (T.token) {
|
||||
case T_START:
|
||||
msgDecodePhase = MSG_START; // End of body
|
||||
break;
|
||||
case T_INTLIT:
|
||||
switch (idManager) { // id
|
||||
case ID_ECOS: // ECoS events
|
||||
decodeEventECoS();
|
||||
break;
|
||||
case ID_PRGMANAGER: // Programming events
|
||||
case ID_POMMANAGER:
|
||||
decodeEventCV(); // decodes CV answer
|
||||
break;
|
||||
default:
|
||||
if (idManager == locoData[myLocoData].myLocoID) { // current loco events
|
||||
if (T.intvalue == locoData[myLocoData].myLocoID)
|
||||
decodeReplyLoco();
|
||||
}
|
||||
else {
|
||||
/*
|
||||
if ((idManager >= ID_S88FEEDBACK) && (idManager < (ID_S88FEEDBACK + 32))) // S88 events
|
||||
decodeEventS88Feedback();
|
||||
else
|
||||
*/
|
||||
discardLine();
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default: // other types of start of line not supported
|
||||
discardLine();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case MSG_REPLYBODY:
|
||||
switch (T.token) {
|
||||
case T_START:
|
||||
msgDecodePhase = MSG_START; // End of body
|
||||
break;
|
||||
case T_INTLIT:
|
||||
switch (idManager) { // id
|
||||
case ID_ECOS: // decodes answer to: get(1,...) / request
|
||||
if (idCommand == T_GET) {
|
||||
decodeEventECoS();
|
||||
}
|
||||
else
|
||||
discardLine();
|
||||
break;
|
||||
case ID_LOKMANAGER: // decodes answer to: queryObjects(10,...)
|
||||
decodeLokManager();
|
||||
break;
|
||||
case ID_SWMANAGER:
|
||||
if (idCommand == T_GET) { // decodes answer to: get(11,..)
|
||||
//decodeSwitchManager();
|
||||
}
|
||||
else
|
||||
discardLine();
|
||||
break;
|
||||
default:
|
||||
/*
|
||||
if ((idManager >= ID_S88FEEDBACK) && (idManager < (ID_S88FEEDBACK + 32)))
|
||||
decodeEventS88Feedback();
|
||||
*/
|
||||
if (idManager == locoData[myLocoData].myLocoID)
|
||||
decodeReplyLoco(); // decodes answer to: get(1xxx,...) / set..
|
||||
else
|
||||
discardLine();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default: // other types of start of line not supported
|
||||
discardLine();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return endMsg;
|
||||
}
|
||||
|
||||
|
||||
void decodeEventECoS () {
|
||||
if (T.intvalue == ID_ECOS) {
|
||||
scan(&T);
|
||||
switch (T.token) {
|
||||
case T_STATUS: // 1 status[GO]
|
||||
scan(&T); // [
|
||||
scan(&T); // GO / STOP / SHUTDOWN
|
||||
if (T.token == T_GO) {
|
||||
csStatus = 1;
|
||||
showTrkECoS();
|
||||
DEBUG_MSG("Power On");
|
||||
}
|
||||
else {
|
||||
csStatus = 0;
|
||||
showTrkECoS();
|
||||
DEBUG_MSG("Power Off");
|
||||
}
|
||||
break;
|
||||
case T_APPV: // 1 ApplicationVersion[2.0.4]
|
||||
scan(&T);
|
||||
scan(&T);
|
||||
if (T.token == T_INTLIT) {
|
||||
appVer = T.intvalue;
|
||||
DEBUG_MSG("Version: %d", appVer)
|
||||
}
|
||||
break;
|
||||
/*
|
||||
case T_CS1: // 1 CentralStation
|
||||
case T_ECOS: // 1 ECoS
|
||||
case T_ECOS2: // 1 ECoS2
|
||||
typeCmdStation = T.token;
|
||||
DEBUG_MSG("CS Type: %s", tokstr[typeCmdStation]);
|
||||
break;
|
||||
*/
|
||||
}
|
||||
discardLine();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void decodeEventCV() {
|
||||
while (scan(&T)) {
|
||||
switch (T.token) {
|
||||
case T_INTLIT:
|
||||
lastNumValue = T.intvalue;
|
||||
break;
|
||||
case T_CVOK:
|
||||
CVdata = lastNumValue;
|
||||
progFinished = true;
|
||||
discardLine();
|
||||
break;
|
||||
case T_ERROR:
|
||||
CVdata = 0x0600;
|
||||
progFinished = true;
|
||||
discardLine();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void parseLokAddrName(int pos) {
|
||||
scan(&T); // 1003 addr[78] name["W. K"]
|
||||
switch (T.token) {
|
||||
case T_ADDR:
|
||||
scan(&T);
|
||||
scan(&T);
|
||||
if (T.token == T_INTLIT)
|
||||
locoData[pos].myAddr.address = T.intvalue;
|
||||
scan(&T);
|
||||
DEBUG_MSG("Addr: %d", locoData[pos].myAddr.address);
|
||||
break;
|
||||
case T_NAME:
|
||||
scan(&T);
|
||||
scan(&T);
|
||||
if (T.token == T_STRLIT)
|
||||
snprintf(locoData[pos].myName, NAME_LNG + 1, "%s", Text);
|
||||
scan(&T);
|
||||
DEBUG_MSG("Name: %s", locoData[pos].myName);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void decodeLokManager () {
|
||||
int id, fnc, num;
|
||||
switch (idCommand) {
|
||||
case T_QOBJ:
|
||||
if (numLoks < LOCOS_IN_STACK) {
|
||||
locoData[numLoks].myLocoID = T.intvalue; // 1003 addr[78] name["W. K"]
|
||||
DEBUG_MSG("ID: %d", locoData[numLoks].myLocoID);
|
||||
parseLokAddrName(numLoks); // addr
|
||||
parseLokAddrName(numLoks); // name
|
||||
pushLoco(locoData[numLoks].myLocoID); //.myAddr.address);
|
||||
numLoks++;
|
||||
}
|
||||
discardLine();
|
||||
break;
|
||||
default:
|
||||
discardLine();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void decodeReplyLoco() {
|
||||
int numFunc;
|
||||
scan(&T);
|
||||
switch (T.token) { // <REPLY get(1xxx,... )> / <EVENT 1xxx>
|
||||
case T_MSG: // 1018 msg[CONTROL_LOST]
|
||||
scan(&T);
|
||||
scan(&T);
|
||||
if (T.token == T_LOST) {
|
||||
bitSet(locoData[myLocoData].mySteps, 3);
|
||||
DEBUG_MSG("Lost control of %d", locoData[myLocoData].myLocoID);
|
||||
}
|
||||
break;
|
||||
case T_CONTROL: // 1000 control[other]
|
||||
scan(&T);
|
||||
scan(&T);
|
||||
if (T.token == T_OTHER) {
|
||||
bitSet(locoData[myLocoData].mySteps, 3);
|
||||
DEBUG_MSG("Control %d by other", locoData[myLocoData].myLocoID);
|
||||
}
|
||||
break;
|
||||
case T_SPEED: // 1000 speed[6]
|
||||
scan(&T);
|
||||
scan(&T);
|
||||
if (T.token == T_INTLIT) {
|
||||
locoData[myLocoData].mySpeed = T.intvalue;
|
||||
updateSpeedHID();
|
||||
DEBUG_MSG("Speed: %d", T.intvalue);
|
||||
}
|
||||
break;
|
||||
case T_STEPS: // 1000 speedstep[2]
|
||||
scan(&T);
|
||||
scan(&T);
|
||||
if (T.token == T_INTLIT) {
|
||||
mySpeedStep = T.intvalue;
|
||||
DEBUG_MSG("Steps: %d", T.intvalue);
|
||||
}
|
||||
break;
|
||||
case T_DIR: // 1000 dir[0]
|
||||
scan(&T);
|
||||
scan(&T);
|
||||
if (T.token == T_INTLIT) {
|
||||
locoData[myLocoData].myDir = (T.intvalue > 0) ? 0 : 0x80;
|
||||
updateSpeedDir();
|
||||
DEBUG_MSG("Dir: %d", T.intvalue);
|
||||
}
|
||||
break;
|
||||
case T_FUNC: // 1015 func[0, 0]
|
||||
scan(&T);
|
||||
scan(&T);
|
||||
if (T.token == T_INTLIT) {
|
||||
numFunc = T.intvalue;
|
||||
scan(&T);
|
||||
scan(&T);
|
||||
if (T.token == T_INTLIT) {
|
||||
if (T.intvalue > 0)
|
||||
bitSet(locoData[myLocoData].myFunc.Bits, numFunc);
|
||||
else
|
||||
bitClear(locoData[myLocoData].myFunc.Bits, numFunc);
|
||||
DEBUG_MSG("Func%d: %d", numFunc, T.intvalue);
|
||||
updateFuncState(isWindow(WIN_THROTTLE));
|
||||
}
|
||||
}
|
||||
break;
|
||||
/*
|
||||
case T_FSYMBOL: // 1015 funcsymbol[0,2]
|
||||
scan(&T);
|
||||
scan(&T);
|
||||
if (T.token == T_INTLIT) {
|
||||
numFunc = T.intvalue;
|
||||
scan(&T);
|
||||
scan(&T);
|
||||
if (T.token == T_INTLIT) {
|
||||
locoData[myLocoData].myFuncIcon[numFunc] = FunktionsTastenSymbole[T.intvalue & 0x7F] << 1;
|
||||
DEBUG_MSG("Func: %d, Icon: %d", numFunc, T.intvalue)
|
||||
}
|
||||
}
|
||||
break;
|
||||
*/
|
||||
case T_FSYMB: // 1015 funcsymb[0,2]
|
||||
scan(&T);
|
||||
scan(&T);
|
||||
if (T.token == T_INTLIT) {
|
||||
numFunc = T.intvalue;
|
||||
scan(&T);
|
||||
scan(&T);
|
||||
if (T.token == T_INTLIT) {
|
||||
locoData[myLocoData].myFuncIcon[numFunc] = FunktionsTastenSymboleCS1[T.intvalue & 0x3F] << 1;
|
||||
DEBUG_MSG("Func: %d, Icon: %d", numFunc, T.intvalue)
|
||||
}
|
||||
}
|
||||
break;
|
||||
case T_FICON: // 1000 funcicon[0,3,light]
|
||||
scan(&T);
|
||||
scan(&T);
|
||||
if (T.token == T_INTLIT) {
|
||||
numFunc = T.intvalue;
|
||||
scan(&T);
|
||||
scan(&T);
|
||||
if (T.token == T_INTLIT) {
|
||||
locoData[myLocoData].myFuncIcon[numFunc] = FunktionsTastenSymbole[T.intvalue & 0x7F] << 1;
|
||||
DEBUG_MSG("Func: %d, Icon: %d", numFunc, T.intvalue)
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
discardLine();
|
||||
}
|
||||
197
PacoMouseCYD/src/PacoMouseCYD/encoder.ino
Normal file
@@ -0,0 +1,197 @@
|
||||
/* PacoMouseCYD throttle -- F. Cañada 2025-2026 -- https://usuaris.tinet.cat/fmco/
|
||||
*/
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// ***** ENCODER *****
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
IRAM_ATTR void encoderISR () { // Encoder interrupt
|
||||
encoderNeedService = true;
|
||||
}
|
||||
|
||||
|
||||
void encoderService () { // Encoder interrupt service
|
||||
encoderNeedService = false;
|
||||
lastTimeEncoder = millis();
|
||||
outA = digitalRead (ENCODER_A);
|
||||
outB = digitalRead (ENCODER_B);
|
||||
if (outA != copyOutA) { // evitamos rebotes
|
||||
copyOutA = outA;
|
||||
if (copyOutB == 0x80) {
|
||||
copyOutB = outB;
|
||||
}
|
||||
else {
|
||||
if ( outB != copyOutB) {
|
||||
copyOutB = 0x80;
|
||||
if (outA == outB) // comprueba sentido de giro
|
||||
encoderValue = (encoderValue < encoderMax) ? ++encoderValue : encoderMax ; // CW, hasta maximo
|
||||
else
|
||||
encoderValue = (encoderValue > 0) ? --encoderValue : 0; // CCW, hasta 0
|
||||
encoderChange = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void readButtons () {
|
||||
byte inputButton;
|
||||
|
||||
timeButtons = millis(); // lee cada cierto tiempo
|
||||
inputButton = digitalRead (ENCODER_SW); // comprueba cambio en boton del encoder
|
||||
if (statusSwitch != inputButton) {
|
||||
statusSwitch = inputButton;
|
||||
if (statusSwitch == LOW)
|
||||
switchOn = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void controlEncoder() { // encoder movement
|
||||
encoderChange = false;
|
||||
aliveAndKicking();
|
||||
DEBUG_MSG("Encoder: %d", encoderValue);
|
||||
switch (objStack[lastWinStack].objID) {
|
||||
case WIN_SSID:
|
||||
scrSSID = encoderValue;
|
||||
scanWiFiFill();
|
||||
drawObject(OBJ_TXT, TXT_SSID1);
|
||||
drawObject(OBJ_TXT, TXT_SSID2);
|
||||
drawObject(OBJ_TXT, TXT_SSID3);
|
||||
drawObject(OBJ_TXT, TXT_SSID4);
|
||||
drawObject(OBJ_TXT, TXT_SSID5);
|
||||
drawObject(OBJ_TXT, TXT_SSID6);
|
||||
break;
|
||||
case WIN_THROTTLE:
|
||||
case WIN_SPEEDO:
|
||||
case WIN_STA_PLAY:
|
||||
updateMySpeed();
|
||||
break;
|
||||
case WIN_CHG_FUNC:
|
||||
fncData[FNC_CHG].idIcon = encoderValue * 2;
|
||||
drawObject(OBJ_FNC, FNC_CHG);
|
||||
break;
|
||||
case WIN_SEL_LOCO:
|
||||
populateLocoList();
|
||||
drawObject(OBJ_TXT, TXT_SEL_ADDR1);
|
||||
drawObject(OBJ_TXT, TXT_SEL_NAME1);
|
||||
drawObject(OBJ_TXT, TXT_SEL_ADDR2);
|
||||
drawObject(OBJ_TXT, TXT_SEL_NAME2);
|
||||
drawObject(OBJ_TXT, TXT_SEL_ADDR3);
|
||||
drawObject(OBJ_TXT, TXT_SEL_NAME3);
|
||||
drawObject(OBJ_TXT, TXT_SEL_ADDR4);
|
||||
drawObject(OBJ_TXT, TXT_SEL_NAME4);
|
||||
drawObject(OBJ_TXT, TXT_SEL_ADDR5);
|
||||
drawObject(OBJ_TXT, TXT_SEL_NAME5);
|
||||
drawObject(OBJ_TXT, TXT_SEL_ADDR6);
|
||||
drawObject(OBJ_TXT, TXT_SEL_NAME6);
|
||||
break;
|
||||
case WIN_STEAM:
|
||||
showSpeedSteam((encoderValue << 1) + 240);
|
||||
break;
|
||||
case WIN_ACC_TYPE:
|
||||
fncData[FNC_ACC_TYPE].num = accDef[encoderValue].num;
|
||||
fncData[FNC_ACC_TYPE].idIcon = accDef[encoderValue].icon[0].fncIcon;
|
||||
fncData[FNC_ACC_TYPE].color = accDef[encoderValue].icon[0].color;
|
||||
fncData[FNC_ACC_TYPE].colorOn = accDef[encoderValue].icon[0].colorOn;
|
||||
drawObject(OBJ_FNC, FNC_ACC_TYPE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void controlSwitch() { // encoder switch
|
||||
uint16_t value, value2, txtID;
|
||||
uint32_t delta, dist;
|
||||
char msg[NAME_LNG + 1];
|
||||
switchOn = false;
|
||||
aliveAndKicking();
|
||||
DEBUG_MSG("Encoder Switch");
|
||||
switch (objStack[lastWinStack].objID) {
|
||||
case WIN_SSID:
|
||||
snprintf (wifiSetting.ssid, 32, WiFi.SSID(scrSSID).c_str()); //saveSSID(scrSSID);
|
||||
DEBUG_MSG("New SSID: %s", wifiSetting.ssid);
|
||||
eepromChanged = true;
|
||||
closeWindow(WIN_SSID);
|
||||
openWindow(WIN_WIFI);
|
||||
break;
|
||||
case WIN_THROTTLE:
|
||||
case WIN_STA_PLAY:
|
||||
if (encoderValue > 0) {
|
||||
encoderValue = 0;
|
||||
if (stopMode > 0)
|
||||
locoData[myLocoData].mySpeed = 1;
|
||||
else
|
||||
locoData[myLocoData].mySpeed = 0;
|
||||
locoOperationSpeed();
|
||||
}
|
||||
else {
|
||||
locoData[myLocoData].myDir ^= 0x80;
|
||||
changeDirection();
|
||||
}
|
||||
updateSpeedDir();
|
||||
break;
|
||||
case WIN_CHG_FUNC:
|
||||
fncData[FNC_F0 + paramChild].idIcon = fncData[FNC_CHG].idIcon;
|
||||
closeWindow(WIN_CHG_FUNC);
|
||||
break;
|
||||
case WIN_SEL_LOCO:
|
||||
releaseLoco();
|
||||
txtID = (encoderValue > 5) ? 5 : encoderValue;
|
||||
if (useID) {
|
||||
value2 = (encoderValue > 5) ? encoderValue - 5 : 0;
|
||||
value = sortedLocoStack[value2 + txtID];
|
||||
}
|
||||
else {
|
||||
value = atoi(txtData[TXT_SEL_ADDR1 + txtID].buf);
|
||||
}
|
||||
//value = atoi(txtData[TXT_SEL_ADDR1 + txtID].buf);
|
||||
DEBUG_MSG("Selected Loco %d", value);
|
||||
closeWindow(WIN_SEL_LOCO);
|
||||
getNewLoco(value);
|
||||
break;
|
||||
case WIN_SPEEDO:
|
||||
switch (speedoPhase) { //enum speedo {SPD_WAIT, SPD_BEGIN, SPD_COUNT, SPD_ARRIVE, SPD_END};
|
||||
case SPD_WAIT:
|
||||
if (getCurrentStep() > 0) {
|
||||
speedoStartTime = millis();
|
||||
setSpeedoPhase(SPD_BEGIN);
|
||||
getLabelTxt(LBL_MEASURE, msg);
|
||||
snprintf(spdSpeedBuf, NAME_LNG + 1, "%s", msg);
|
||||
drawObject(OBJ_TXT, TXT_SPEEDO_SPD);
|
||||
setTimer(TMR_SPEEDO, 5, TMR_ONESHOT);
|
||||
}
|
||||
else {
|
||||
locoData[myLocoData].myDir ^= 0x80;
|
||||
changeDirection();
|
||||
updateSpeedDir();
|
||||
}
|
||||
break;
|
||||
case SPD_BEGIN:
|
||||
case SPD_COUNT:
|
||||
speedoEndTime = millis();
|
||||
setSpeedoPhase(SPD_ARRIVE);
|
||||
setTimer(TMR_SPEEDO, 5, TMR_ONESHOT);
|
||||
dist = speedoLength * 36 * speedoScale;
|
||||
delta = (speedoEndTime - speedoStartTime) * 10;
|
||||
speedoSpeed = dist / delta;
|
||||
snprintf(spdSpeedBuf, NAME_LNG + 1, "%d km/h", speedoSpeed);
|
||||
drawObject(OBJ_TXT, TXT_SPEEDO_SPD);
|
||||
break;
|
||||
case SPD_ARRIVE:
|
||||
break;
|
||||
case SPD_END:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case WIN_STEAM:
|
||||
steamThrottleStop();
|
||||
currentSteamSpeed = 0;
|
||||
locoData[myLocoData].mySpeed = 0;
|
||||
locoOperationSpeed();
|
||||
break;
|
||||
case WIN_ACC_TYPE:
|
||||
accTypeClick();
|
||||
break;
|
||||
}
|
||||
}
|
||||
1615
PacoMouseCYD/src/PacoMouseCYD/events.ino
Normal file
416
PacoMouseCYD/src/PacoMouseCYD/file.ino
Normal file
@@ -0,0 +1,416 @@
|
||||
/* PacoMouseCYD throttle -- F. Cañada 2025-2026 -- https://usuaris.tinet.cat/fmco/
|
||||
*/
|
||||
|
||||
|
||||
bool checkName(char *fileName) {
|
||||
bool result;
|
||||
uint16_t lng;
|
||||
result = false;
|
||||
lng = strlen(fileName);
|
||||
if (lng > 4) {
|
||||
if ((fileName[lng - 4] == '.') && (fileName[lng - 3] == 'c') && (fileName[lng - 2] == 's') && (fileName[lng - 1] == 'v'))
|
||||
return true;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool saveLocoData(fs::FS &fs, uint16_t pos) { // save loco data in .csv file
|
||||
char field[30];
|
||||
uint16_t cnt;
|
||||
bool dataOK, isDir;
|
||||
File myFile;
|
||||
dataOK = false;
|
||||
myFile = fs.open("/loco");
|
||||
if (myFile) {
|
||||
isDir = myFile.isDirectory();
|
||||
myFile.close();
|
||||
if (!isDir)
|
||||
return dataOK;
|
||||
DEBUG_MSG("/loco is a directory");
|
||||
}
|
||||
else {
|
||||
DEBUG_MSG("Directory /loco not found. Creating...")
|
||||
fs.mkdir("/loco");
|
||||
}
|
||||
sprintf (field, "/loco/%d.csv", locoData[pos].myAddr.address);
|
||||
myFile = fs.open(field, FILE_WRITE);
|
||||
if (myFile) {
|
||||
DEBUG_MSG("File %s opened for writting", field);
|
||||
getLabelTxt(LBL_NAME, field); // Header
|
||||
myFile.print(field);
|
||||
myFile.print(CSV_FILE_DELIMITER);
|
||||
getLabelTxt(LBL_IMAGE, field);
|
||||
myFile.print(field);
|
||||
myFile.print(CSV_FILE_DELIMITER);
|
||||
getLabelTxt(LBL_VMAX, field);
|
||||
myFile.print(field);
|
||||
for (cnt = 0; cnt < 29; cnt++) {
|
||||
myFile.print(CSV_FILE_DELIMITER);
|
||||
myFile.print('F');
|
||||
myFile.print(cnt);
|
||||
}
|
||||
myFile.print("\r\n");
|
||||
myFile.print(locoData[pos].myName); // Loco data
|
||||
myFile.print(CSV_FILE_DELIMITER);
|
||||
myFile.print(locoData[pos].myLocoID);
|
||||
myFile.print(CSV_FILE_DELIMITER);
|
||||
myFile.print(locoData[pos].myVmax);
|
||||
for (cnt = 0; cnt < 29; cnt++) {
|
||||
myFile.print(CSV_FILE_DELIMITER);
|
||||
myFile.print(locoData[pos].myFuncIcon[cnt] >> 1);
|
||||
}
|
||||
myFile.print("\r\n");
|
||||
myFile.close();
|
||||
dataOK = true;
|
||||
}
|
||||
return dataOK;
|
||||
}
|
||||
|
||||
|
||||
void deleteLocoData (fs::FS &fs, uint16_t num) {
|
||||
char line[200];
|
||||
sprintf (line, "/loco/%d.csv", num);
|
||||
if (fs.remove(line)) {
|
||||
DEBUG_MSG("File %s deleted", line);
|
||||
}
|
||||
else {
|
||||
DEBUG_MSG("File %s delete failed", line);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool readLocoData(fs::FS &fs, uint16_t num, uint16_t pos) { // read loco data from .csv file
|
||||
char line[200];
|
||||
bool dataOK;
|
||||
uint16_t n;
|
||||
File myFile;
|
||||
dataOK = false;
|
||||
sprintf (line, "/loco/%d.csv", num);
|
||||
myFile = fs.open(line);
|
||||
if (myFile) {
|
||||
if (readCSV(myFile, line, sizeof(line), false)) { // skip header line
|
||||
if (readCSV(myFile, locoData[pos].myName, sizeof(locoData[pos].myName), true)) { // read data field: Name
|
||||
if (readCSV(myFile, line, sizeof(line), true)) { // read data field: Picture
|
||||
locoData[pos].myLocoID = atoi(line);
|
||||
if (readCSV(myFile, line, sizeof(line), true)) {
|
||||
locoData[pos].myVmax = atoi(line);
|
||||
DEBUG_MSG("%d %s %d %d", num, locoData[pos].myName, locoData[pos].myLocoID, locoData[pos].myVmax)
|
||||
for (n = 0; n < 29; n++) {
|
||||
if (!readCSV(myFile, line, sizeof(line), true)) { // read data field: Functions
|
||||
myFile.close();
|
||||
return false;
|
||||
}
|
||||
locoData[pos].myFuncIcon[n] = (uint8_t)(atoi(line) << 1);
|
||||
//DEBUG_MSG("Func: %d - %d", n, locoData[pos].myFuncIcon[n])
|
||||
}
|
||||
locoData[pos].myAddr.address = num;
|
||||
dataOK = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
myFile.close();
|
||||
}
|
||||
return dataOK;
|
||||
}
|
||||
|
||||
|
||||
bool readCSV(File & f, char* line, uint16_t maxLen, bool getField) {
|
||||
uint16_t n; // read field or line from CSV file
|
||||
char chr;
|
||||
n = 0;
|
||||
yield();
|
||||
while (n < maxLen) {
|
||||
chr = f.read();
|
||||
switch (chr) {
|
||||
case 0:
|
||||
line[n] = '\0';
|
||||
return false; // EOF
|
||||
break;
|
||||
case '\r':
|
||||
line[n] = '\0';
|
||||
break;
|
||||
case '\n':
|
||||
line[n] = '\0';
|
||||
return true;
|
||||
break;
|
||||
case ',':
|
||||
case ';':
|
||||
if (getField) {
|
||||
line[n] = '\0';
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
line[n++] = chr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false; // too long
|
||||
}
|
||||
|
||||
|
||||
void loadLocoFiles(fs::FS &fs, const char * dirname) {
|
||||
uint16_t pos, adr;
|
||||
char nameFile[50];
|
||||
File myFile;
|
||||
if (wifiSetting.protocol == CLIENT_ECOS)
|
||||
return;
|
||||
File root = fs.open(dirname);
|
||||
if (!root) {
|
||||
//DEBUG_MSG("Failed to open directory %s", dirname);
|
||||
return;
|
||||
}
|
||||
if (!root.isDirectory()) {
|
||||
//DEBUG_MSG("%s Not a directory", dirname);
|
||||
return;
|
||||
}
|
||||
pos = 0;
|
||||
File file = root.openNextFile();
|
||||
while (file) {
|
||||
if (! file.isDirectory()) {
|
||||
if (pos < LOCOS_IN_STACK) {
|
||||
sprintf(nameFile, "%s", file.name());
|
||||
adr = atoi(nameFile);
|
||||
//DEBUG_MSG("%d %s", adr, nameFile);
|
||||
if (readLocoData(fs, adr, pos++))
|
||||
pushLoco(adr);
|
||||
}
|
||||
}
|
||||
file = root.openNextFile();
|
||||
}
|
||||
}
|
||||
|
||||
void initImageList() {
|
||||
uint16_t n, maxImg;
|
||||
uint16_t pos, id;
|
||||
char nameFile[50];
|
||||
File myFile;
|
||||
|
||||
for (n = 0; n < MAX_LOCO_IMAGE; n++) // add to list system images
|
||||
locoImages[n] = (n < (MAX_SYS_LPIC - 1)) ? n + 1 : 0;
|
||||
if (wifiSetting.protocol != CLIENT_ECOS) {
|
||||
if (sdDetected) { // add to list user images from SD
|
||||
File root = SD.open("/image");
|
||||
if (root) {
|
||||
if (root.isDirectory()) {
|
||||
pos = MAX_SYS_LPIC - 1;
|
||||
File file = root.openNextFile();
|
||||
while (file) {
|
||||
if (! file.isDirectory()) {
|
||||
if (pos < MAX_LOCO_IMAGE) {
|
||||
sprintf(nameFile, "%s", file.name());
|
||||
id = atoi(nameFile);
|
||||
if (id >= 1000) {
|
||||
locoImages[pos++] = id;
|
||||
}
|
||||
}
|
||||
}
|
||||
file = root.openNextFile();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
locoImageIndex = 0;
|
||||
}
|
||||
|
||||
|
||||
void populateImageList() {
|
||||
uint16_t n;
|
||||
for (n = 0; n < 6; n++)
|
||||
lpicData[LPIC_SEL_IMG1 + n].id = locoImages[locoImageIndex + n];
|
||||
}
|
||||
|
||||
|
||||
bool saveCurrAccPanel(fs::FS &fs) {
|
||||
char field[30];
|
||||
uint16_t cnt;
|
||||
bool dataOK, isDir;
|
||||
File myFile;
|
||||
dataOK = false;
|
||||
myFile = fs.open("/acc");
|
||||
if (myFile) {
|
||||
isDir = myFile.isDirectory();
|
||||
myFile.close();
|
||||
if (!isDir)
|
||||
return dataOK;
|
||||
DEBUG_MSG("/acc is a directory");
|
||||
}
|
||||
else {
|
||||
DEBUG_MSG("Directory /acc not found. Creating...")
|
||||
fs.mkdir("/acc");
|
||||
}
|
||||
sprintf (field, "/acc/%d.csv", currPanel);
|
||||
myFile = fs.open(field, FILE_WRITE);
|
||||
if (myFile) {
|
||||
DEBUG_MSG("File %s opened for writting", field);
|
||||
getLabelTxt(LBL_ACC_TYPE, field); // Header
|
||||
myFile.print(field);
|
||||
myFile.print(CSV_FILE_DELIMITER);
|
||||
getLabelTxt(LBL_ACC_ADDR, field);
|
||||
myFile.print(field);
|
||||
myFile.print(CSV_FILE_DELIMITER);
|
||||
getLabelTxt(LBL_ACC_ADDR, field);
|
||||
myFile.print(field);
|
||||
myFile.print(CSV_FILE_DELIMITER);
|
||||
getLabelTxt(LBL_ACC_NAME, field);
|
||||
myFile.print(field);
|
||||
myFile.print(CSV_FILE_DELIMITER);
|
||||
getLabelTxt(LBL_BITS, field);
|
||||
myFile.print(field);
|
||||
myFile.print(CSV_FILE_DELIMITER);
|
||||
myFile.print("\r\n");
|
||||
for (cnt = 0; cnt < 16; cnt++) {
|
||||
myFile.print(accPanel[cnt].type); // Acc data
|
||||
myFile.print(CSV_FILE_DELIMITER);
|
||||
myFile.print(accPanel[cnt].addr);
|
||||
myFile.print(CSV_FILE_DELIMITER);
|
||||
myFile.print(accPanel[cnt].addr2);
|
||||
myFile.print(CSV_FILE_DELIMITER);
|
||||
myFile.print(accPanel[cnt].accName);
|
||||
myFile.print(CSV_FILE_DELIMITER);
|
||||
myFile.print(accPanel[cnt].activeOutput);
|
||||
myFile.print(CSV_FILE_DELIMITER);
|
||||
myFile.print("\r\n");
|
||||
}
|
||||
myFile.close();
|
||||
dataOK = true;
|
||||
}
|
||||
return dataOK;
|
||||
}
|
||||
|
||||
|
||||
bool loadAccPanel(fs::FS & fs) {
|
||||
char line[200];
|
||||
bool dataOK;
|
||||
uint16_t cnt = 0;
|
||||
File myFile;
|
||||
dataOK = false;
|
||||
sprintf (line, "/acc/%d.csv", currPanel);
|
||||
myFile = fs.open(line);
|
||||
if (myFile) {
|
||||
if (readCSV(myFile, line, sizeof(line), false)) { // skip header line
|
||||
for (cnt = 0; cnt < 16; cnt++) {
|
||||
readCSV(myFile, line, sizeof(line), true);
|
||||
accPanel[cnt].type = (accType)atoi(line);
|
||||
readCSV(myFile, line, sizeof(line), true);
|
||||
accPanel[cnt].addr = atoi(line);
|
||||
readCSV(myFile, line, sizeof(line), true);
|
||||
accPanel[cnt].addr2 = atoi(line);
|
||||
readCSV(myFile, line, sizeof(line), true);
|
||||
snprintf(accPanel[cnt].accName, ACC_LNG + 1, line);
|
||||
readCSV(myFile, line, sizeof(line), false);
|
||||
accPanel[cnt].activeOutput = atoi(line);
|
||||
DEBUG_MSG("Line %d: %d, %d, %d, \"%s\", %d", cnt, accPanel[cnt].type, accPanel[cnt].addr, accPanel[cnt].addr2, accPanel[cnt].accName, accPanel[cnt].activeOutput)
|
||||
}
|
||||
}
|
||||
myFile.close();
|
||||
dataOK = true;
|
||||
}
|
||||
return dataOK;
|
||||
}
|
||||
|
||||
|
||||
bool saveAccPanelNames(fs::FS & fs) {
|
||||
char field[30];
|
||||
uint16_t cnt;
|
||||
bool dataOK, isDir;
|
||||
File myFile;
|
||||
dataOK = false;
|
||||
myFile = fs.open("/acc");
|
||||
if (myFile) {
|
||||
isDir = myFile.isDirectory();
|
||||
myFile.close();
|
||||
if (!isDir)
|
||||
return dataOK;
|
||||
DEBUG_MSG("/acc is a directory");
|
||||
}
|
||||
else {
|
||||
DEBUG_MSG("Directory /acc not found. Creating...")
|
||||
fs.mkdir("/acc");
|
||||
}
|
||||
sprintf (field, "/acc/panel.csv");
|
||||
myFile = fs.open(field, FILE_WRITE);
|
||||
if (myFile) {
|
||||
DEBUG_MSG("File %s opened for writting", field);
|
||||
getLabelTxt(LBL_NAME, field); // Header
|
||||
myFile.print(field);
|
||||
myFile.print("\r\n");
|
||||
for (cnt = 0; cnt < 16; cnt++) {
|
||||
myFile.print(panelNamesBuf[cnt]); // Panel names
|
||||
myFile.print("\r\n");
|
||||
}
|
||||
myFile.close();
|
||||
dataOK = true;
|
||||
}
|
||||
return dataOK;
|
||||
}
|
||||
|
||||
|
||||
bool loadAccPanelNames(fs::FS & fs) {
|
||||
char line[200];
|
||||
bool dataOK;
|
||||
uint16_t n;
|
||||
File myFile;
|
||||
dataOK = false;
|
||||
sprintf (line, "/acc/panel.csv");
|
||||
myFile = fs.open(line);
|
||||
if (myFile) {
|
||||
if (readCSV(myFile, line, sizeof(line), false)) { // skip header line
|
||||
for (n = 0; n < 16; n++) {
|
||||
if (readCSV(myFile, line, sizeof(line), true)) { // read data field
|
||||
snprintf(panelNamesBuf[n], PANEL_LNG + 1, line);
|
||||
DEBUG_MSG("%s", panelNamesBuf[n])
|
||||
}
|
||||
}
|
||||
}
|
||||
myFile.close();
|
||||
}
|
||||
else {
|
||||
for (n = 0; n < 16; n++) // default names
|
||||
snprintf(panelNamesBuf[n], PANEL_LNG + 1, "Panel %d", n);
|
||||
}
|
||||
return dataOK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
void listDir(fs::FS &fs, const char * dirname, uint8_t levels) {
|
||||
Serial.printf("Listing directory: %s\n", dirname);
|
||||
|
||||
File root = fs.open(dirname);
|
||||
if (!root) {
|
||||
Serial.println("Failed to open directory");
|
||||
return;
|
||||
}
|
||||
if (!root.isDirectory()) {
|
||||
Serial.println("Not a directory");
|
||||
return;
|
||||
}
|
||||
|
||||
File file = root.openNextFile();
|
||||
while (file) {
|
||||
if (file.isDirectory()) {
|
||||
Serial.print(" DIR : ");
|
||||
Serial.println(file.name());
|
||||
if (levels) {
|
||||
listDir(fs, file.path(), levels - 1);
|
||||
}
|
||||
} else {
|
||||
Serial.print(" FILE: ");
|
||||
Serial.print(file.name());
|
||||
Serial.print(" SIZE: ");
|
||||
Serial.println(file.size());
|
||||
}
|
||||
file = root.openNextFile();
|
||||
}
|
||||
}
|
||||
*/
|
||||
151
PacoMouseCYD/src/PacoMouseCYD/gui.h
Normal file
@@ -0,0 +1,151 @@
|
||||
/* PacoMouseCYD throttle -- F. Cañada 2025-2026 -- https://usuaris.tinet.cat/fmco/
|
||||
Very basic Graphical User Interface (GUI) for PacoMouseCYD
|
||||
All data in absolute coordinates
|
||||
*/
|
||||
|
||||
#include <TFT_eSPI.h> // Graphics and font library for ILI9341 driver chip v2.5.43
|
||||
#include "FreeSans7pt7b.h"
|
||||
#include "FreeSansBold6pt7b.h"
|
||||
|
||||
|
||||
#define MAX_OBJ_STACK 100
|
||||
#define MAX_LABEL_LNG 150
|
||||
#define TMR_RESOLUTION 100
|
||||
|
||||
#define NOT_USED 0xFF
|
||||
#define OBJ_NOT_FOUND 0xFFFF
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// ***** FONTS *****
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef LOAD_GFXFF
|
||||
ERROR_Please_enable_LOAD_GFXFF_in_User_Setup!
|
||||
#endif
|
||||
|
||||
#define GFXFF 1
|
||||
#define FSS7 &FreeSans7pt7b
|
||||
#define FSS9 &FreeSans9pt7b
|
||||
#define FSSB6 &FreeSansBold6pt7b
|
||||
#define FSSB9 &FreeSansBold9pt7b
|
||||
#define FSSB12 &FreeSansBold12pt7b
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// ***** COLORS *****
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
// Colour definitions for 64K colour mode (RGB565)
|
||||
// Bits 0..4 -> Blue 0..4
|
||||
// Bits 5..10 -> Green 0..5
|
||||
// Bits 11..15 -> Red 0..4
|
||||
// Assign human-readable names to some common 16-bit color values: http://rinkydinkelectronics.com/calc_rgb565.php
|
||||
// Examples: https://github.com/newdigate/rgb565_colors
|
||||
|
||||
#define COLOR_WHITE 0xFFFF
|
||||
#define COLOR_BLACK 0x0000
|
||||
#define COLOR_BLUE 0x001F
|
||||
#define COLOR_NAVY 0x000F
|
||||
#define COLOR_AQUA 0x5D1C
|
||||
#define COLOR_SKYBLUE 0x867D
|
||||
#define COLOR_RED 0xF882
|
||||
#define COLOR_DARKRED 0x8800
|
||||
#define COLOR_PINK 0xF97F
|
||||
#define COLOR_MAGENTA 0xF81F
|
||||
#define COLOR_GREEN 0x0780
|
||||
#define COLOR_GREENYELLOW 0xAFE5
|
||||
#define COLOR_DARKGREEN 0x03E0
|
||||
#define COLOR_CYAN 0x07FF
|
||||
#define COLOR_DARKCYAN 0x03EF
|
||||
#define COLOR_YELLOW 0xFFE0
|
||||
#define COLOR_GOLD 0xDD24
|
||||
#define COLOR_LIGHTGREY 0xC618
|
||||
#define COLOR_DARKGREY 0x7BEF
|
||||
#define COLOR_LIGHTBLACK 0x4A49
|
||||
#define COLOR_SMOKYBLACK 0x1061
|
||||
#define COLOR_CHARCOAL 0x3A2A
|
||||
#define COLOR_VIOLET 0x9199
|
||||
#define COLOR_BROWN 0x8200
|
||||
#define COLOR_ORANGE 0xFD20
|
||||
#define COLOR_LIME 0x87E0
|
||||
#define COLOR_MAROON 0x7800
|
||||
#define COLOR_PURPLE 0x780F
|
||||
#define COLOR_OLIVE 0x7BE0
|
||||
#define COLOR_SILVER 0xA510
|
||||
#define COLOR_CREAM 0xFFF9
|
||||
#define COLOR_GHOST_WHITE 0xF7BF
|
||||
|
||||
#define COLOR_BACKGROUND 0xB5B6 // 0xB6B6B6
|
||||
#define COLOR_TRANSPARENT TFT_TRANSPARENT
|
||||
|
||||
const uint16_t colorDraw[] = {COLOR_BLACK, COLOR_BLUE, COLOR_RED, COLOR_MAGENTA, COLOR_GREEN, COLOR_CYAN, COLOR_YELLOW, COLOR_WHITE,
|
||||
COLOR_BACKGROUND, COLOR_TRANSPARENT, COLOR_GHOST_WHITE, COLOR_AQUA, COLOR_CREAM, COLOR_SMOKYBLACK, COLOR_SKYBLUE,
|
||||
COLOR_GOLD,
|
||||
};
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// ***** OBJECT *****
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
enum objTypeGUI {OBJ_UNDEF, OBJ_TIMER, OBJ_WIN, OBJ_BUTTON, OBJ_LABEL, OBJ_TXT, OBJ_BAR, OBJ_DRAWSTR, OBJ_ICON, OBJ_KEYBOARD, OBJ_SWITCH,
|
||||
OBJ_GAUGE, OBJ_LPIC, OBJ_FNC, OBJ_SLIDER, OBJ_RADIO, OBJ_CHAR,
|
||||
};
|
||||
|
||||
struct wObj { // Graphic objects
|
||||
uint16_t objType;
|
||||
uint16_t objID;
|
||||
};
|
||||
|
||||
struct wObj objStack[MAX_OBJ_STACK]; // Object stack
|
||||
uint16_t endObjStack;
|
||||
uint16_t lastWinStack;
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// ***** EVENT *****
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
enum EventGUI {EVNT_CLICK, EVNT_DRAW, EVNT_WOPEN, EVNT_WCLOSE, EVNT_TIMER, EVNT_BOOT};
|
||||
|
||||
typedef struct { // Events
|
||||
uint16_t objType;
|
||||
uint16_t objID;
|
||||
uint16_t eventID;
|
||||
} wEvent;
|
||||
|
||||
wEvent eventStack[32]; // stack for events (size 32, hardcoded in functions. Don't change!)
|
||||
uint16_t eventIn;
|
||||
uint16_t eventOut;
|
||||
uint16_t eventsPending;
|
||||
uint16_t lastClickX;
|
||||
uint16_t lastClickY;
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// ***** TIMER *****
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
enum timers {TMR_BLIGHT, TMR_END_LOGO, TMR_POWER, TMR_SPEEDO, TMR_INFO, TMR_WAIT, TMR_STEAM, TMR_ACCESSORY, TMR_SCAN, TMR_FNC_ECOS,
|
||||
TMR_STA_RUN,
|
||||
MAX_SYS_TIMER
|
||||
};
|
||||
|
||||
enum timerType {TMR_STOP, TMR_ONESHOT, TMR_PERIODIC};
|
||||
|
||||
typedef struct {
|
||||
uint16_t tmrDelay;
|
||||
uint16_t tmrCount;
|
||||
uint16_t type;
|
||||
} wTimer;
|
||||
|
||||
wTimer wTimerStack[MAX_SYS_TIMER];
|
||||
uint32_t timerSys;
|
||||
|
||||
#if (TFT_WIDTH == 240)
|
||||
#include "gui240x320.h"
|
||||
#endif
|
||||
#if (TFT_WIDTH == 320)
|
||||
#include "gui320x480.h"
|
||||
#endif
|
||||
1116
PacoMouseCYD/src/PacoMouseCYD/gui.ino
Normal file
1412
PacoMouseCYD/src/PacoMouseCYD/gui240x320.h
Normal file
1412
PacoMouseCYD/src/PacoMouseCYD/gui320x480.h
Normal file
2814
PacoMouseCYD/src/PacoMouseCYD/icon.h
Normal file
298
PacoMouseCYD/src/PacoMouseCYD/lnet.h
Normal file
@@ -0,0 +1,298 @@
|
||||
/* PacoMouseCYD throttle -- F. Cañada 2025-2026 -- https://usuaris.tinet.cat/fmco/
|
||||
|
||||
This software and associated files are a DIY project that is not intended for commercial use.
|
||||
This software uses libraries with different licenses, follow all their different terms included.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED.
|
||||
|
||||
Sources are only provided for building and uploading to the device.
|
||||
You are not allowed to modify the source code or fork/publish this project.
|
||||
Commercial use is forbidden.
|
||||
*/
|
||||
|
||||
// OPCODES
|
||||
#define OPC_GPOFF 0x82 // GLOBAL power OFF request
|
||||
#define OPC_GPON 0x83 // GLOBAL power ON request
|
||||
|
||||
#define OPC_LOCO_SPD 0xA0 // SET SLOT speed
|
||||
#define OPC_LOCO_DIRF 0xA1 // SET SLOT dir,F0-4 state
|
||||
#define OPC_LOCO_SND 0xA2 // SET SLOT sound functions
|
||||
#define OPC_LOCO_F9F12 0xA3 // Uhlenbrock
|
||||
|
||||
#define OPC_SW_REQ 0xB0 // REQ SWITCH function
|
||||
#define OPC_SW_REP 0xB1 // Turnout SENSOR state REPORT
|
||||
#define OPC_INPUT_REP 0xB2 // General SENSOR Input codes
|
||||
|
||||
#define OPC_LONG_ACK 0xB4 // Long acknowledge
|
||||
#define OPC_SLOT_STAT1 0xB5 // WRITE slot stat1
|
||||
|
||||
#define OPC_MOVE_SLOTS 0xBA // MOVE slot SRC to DEST
|
||||
#define OPC_RQ_SL_DATA 0xBB // Request SLOT DATA/status block
|
||||
#define OPC_SW_STATE 0xBC // REQ state of SWITCH
|
||||
#define OPC_LOCO_ADR_UHLI 0xBE // REQ loco ADR Uhlenbrock
|
||||
#define OPC_LOCO_ADR 0xBF // REQ loco ADR
|
||||
|
||||
#define OPC_UHLI_FUN 0xD4 // Uhlenbrock
|
||||
|
||||
#define OPC_PEER_XFER 0xE5 // move 8 bytes PEER to PEER, SRC->DST
|
||||
#define OPC_SL_RD_UHLI 0xE6 // SLOT DATA return, 21 bytes Uhlenbrock
|
||||
#define OPC_SL_RD_DATA 0xE7 // SLOT DATA return, 10 bytes
|
||||
#define OPC_IMM_PACKET 0xED // SEND n-byte packet immediate
|
||||
#define OPC_WR_SL_UHLI 0xEE // WRITE SLOT DATA, 21 bytes Uhlenbrock
|
||||
#define OPC_WR_SL_DATA 0xEF // WRITE SLOT DATA, 10 bytes
|
||||
|
||||
|
||||
// BIT MASK
|
||||
#define OPC_SW_REP_INPUTS 0x40 // sensor inputs, outputs otherwise
|
||||
#define OPC_SW_REP_SW 0x20 // switch input, aux input otherwise
|
||||
#define OPC_SW_REP_HI 0x10 // input is HI, LO otherwise
|
||||
#define OPC_SW_REP_CLOSED 0x20 // 'Closed' line is ON, OFF otherwise
|
||||
#define OPC_SW_REP_THROWN 0x10 // 'Thrown' line is ON, OFF otherwise
|
||||
|
||||
#define OPC_SW_REQ_DIR 0x20 // switch direction - closed/thrown
|
||||
#define OPC_SW_REQ_OUT 0x10 // output On/Off
|
||||
|
||||
#define OPC_INPUT_REP_SW 0x20 // input is switch input, aux otherwise
|
||||
#define OPC_INPUT_REP_HI 0x10 // input is HI, LO otherwise
|
||||
|
||||
#define STAT1_SL_BUSY 0x20 // BUSY/ACTIVE: bit encoding for SLOT activity
|
||||
#define STAT1_SL_ACTIVE 0x10
|
||||
|
||||
#define GTRK_PROG_BUSY 0x08 // programming track is Busy
|
||||
#define GTRK_IDLE 0x02 // 0 = Track paused, B'cast EMERG STOP, 1 = Power On
|
||||
#define GTRK_POWER 0x01 // DCC packets are on and global power is up
|
||||
|
||||
// VALUES
|
||||
#define SLOT_0 0x00 // Slot 0. Identifies command station type if implemented
|
||||
#define SLOT_FC 0x7B // Fast clock slot
|
||||
#define SLOT_PRG 0x7C // This slot communicates with the programming track
|
||||
|
||||
#define UHLI_PRG_START 0x41 // Intellibox II program task
|
||||
#define UHLI_PRG_END 0x40
|
||||
|
||||
#define LNCV_REQID_CFGREAD 0x1F // LNCV task
|
||||
#define LNCV_REQID_CFGWRITE 0x20
|
||||
#define LNCV_REQID_CFGREQUEST 0x21
|
||||
#define LNCV_FLAG_PRON 0x80
|
||||
#define LNCV_FLAG_PROFF 0x40
|
||||
|
||||
|
||||
// Message structure to determine the size of a message
|
||||
typedef struct {
|
||||
uint8_t command; /* LocoNet Op Code */
|
||||
uint8_t mesg_size; /* size of the message in bytes */
|
||||
} szMsg;
|
||||
|
||||
/* Turnout sensor state report */
|
||||
typedef struct swrep_t {
|
||||
uint8_t command;
|
||||
uint8_t sn1; /* first byte of report */
|
||||
uint8_t sn2; /* second byte of report */
|
||||
uint8_t chksum; /* exclusive-or checksum for the message */
|
||||
} swRepMsg;
|
||||
|
||||
/* Request Switch function */
|
||||
typedef struct swreq_t {
|
||||
uint8_t command;
|
||||
uint8_t sw1; /* first byte of request */
|
||||
uint8_t sw2; /* second byte of request */
|
||||
uint8_t chksum; /* exclusive-or checksum for the message */
|
||||
} swReqMsg;
|
||||
|
||||
/* Sensor input report */
|
||||
typedef struct inputrep_t {
|
||||
uint8_t command;
|
||||
uint8_t in1; /* first byte of report */
|
||||
uint8_t in2; /* second byte of report */
|
||||
uint8_t chksum; /* exclusive-or checksum for the message */
|
||||
} inputRepMsg;
|
||||
|
||||
/* Slot data request */
|
||||
typedef struct slotreq_t {
|
||||
uint8_t command;
|
||||
uint8_t slot; /* slot number for this request */
|
||||
uint8_t pad; /* should be zero */
|
||||
uint8_t chksum; /* exclusive-or checksum for the message */
|
||||
} slotReqMsg;
|
||||
|
||||
/* Read/Write Slot data messages */
|
||||
typedef struct rwslotdata_t {
|
||||
uint8_t command;
|
||||
uint8_t mesg_size; /* ummmmm, size of the message in bytes? */
|
||||
uint8_t slot; /* slot number for this request */
|
||||
uint8_t stat; /* slot status */
|
||||
uint8_t adr; /* loco address */
|
||||
uint8_t spd; /* command speed */
|
||||
uint8_t dirf; /* direction and F0-F4 bits */
|
||||
uint8_t trk; /* track status */
|
||||
uint8_t ss2; /* slot status 2 (tells how to use ID1/ID2 & ADV Consist*/
|
||||
uint8_t adr2; /* loco address high */
|
||||
uint8_t snd; /* Sound 1-4 / F5-F8 */
|
||||
uint8_t id1; /* ls 7 bits of ID code */
|
||||
uint8_t id2; /* ms 7 bits of ID code */
|
||||
uint8_t chksum; /* exclusive-or checksum for the message */
|
||||
} rwSlotDataMsg;
|
||||
|
||||
/* Fast Clock Message */
|
||||
typedef struct fastclock_t {
|
||||
uint8_t command;
|
||||
uint8_t mesg_size; /* ummmmm, size of the message in bytes? */
|
||||
uint8_t slot; /* slot number for this request */
|
||||
uint8_t clk_rate; /* 0 = Freeze clock, 1 = normal, 10 = 10:1 etc. Max is 0x7f */
|
||||
uint8_t frac_minsl; /* fractional minutes. not for external use. */
|
||||
uint8_t frac_minsh;
|
||||
uint8_t mins_60; /* 256 - minutes */
|
||||
uint8_t track_stat; /* track status */
|
||||
uint8_t hours_24; /* 256 - hours */
|
||||
uint8_t days; /* clock rollovers */
|
||||
uint8_t clk_cntrl; /* bit 6 = 1; data is valid clock info */
|
||||
/* " " 0; ignore this reply */
|
||||
uint8_t id1; /* id1/id2 is device id of last device to set the clock */
|
||||
uint8_t id2; /* " " = zero shows not set has happened */
|
||||
uint8_t chksum; /* exclusive-or checksum for the message */
|
||||
} fastClockMsg;
|
||||
|
||||
/* Programmer Task Message (used in Start and Final Reply, both )*/
|
||||
typedef struct progtask_t {
|
||||
uint8_t command;
|
||||
uint8_t mesg_size; /* ummmmm, size of the message in bytes? */
|
||||
uint8_t slot; /* slot number for this request - slot 124 is programmer */
|
||||
uint8_t pcmd; /* programmer command */
|
||||
uint8_t pstat; /* programmer status error flags in reply message */
|
||||
uint8_t hopsa; /* Ops mode - 7 high address bits of loco to program */
|
||||
uint8_t lopsa; /* Ops mode - 7 low address bits of loco to program */
|
||||
uint8_t trk; /* track status. Note: bit 3 shows if prog track is busy */
|
||||
uint8_t cvh; /* hi 3 bits of CV# and msb of data7 */
|
||||
uint8_t cvl; /* lo 7 bits of CV# */
|
||||
uint8_t data7; /* 7 bits of data to program, msb is in cvh above */
|
||||
uint8_t pad2;
|
||||
uint8_t pad3;
|
||||
uint8_t chksum; /* exclusive-or checksum for the message */
|
||||
} progTaskMsg;
|
||||
|
||||
/* Set slot sound functions */
|
||||
typedef struct locosnd_t {
|
||||
uint8_t command;
|
||||
uint8_t slot; /* slot number for this request */
|
||||
uint8_t snd; /* sound/function request */
|
||||
uint8_t chksum; /* exclusive-or checksum for the message */
|
||||
} locoSndMsg;
|
||||
|
||||
/* Set slot direction and F0-F4 functions */
|
||||
typedef struct locodirf_t {
|
||||
uint8_t command;
|
||||
uint8_t slot; /* slot number for this request */
|
||||
uint8_t dirf; /* direction & function request */
|
||||
uint8_t chksum; /* exclusive-or checksum for the message */
|
||||
} locoDirfMsg;
|
||||
|
||||
/* Set slot speed functions */
|
||||
typedef struct locospd_t {
|
||||
uint8_t command;
|
||||
uint8_t slot; /* slot number for this request */
|
||||
uint8_t spd; /* speed request */
|
||||
uint8_t chksum; /* exclusive-or checksum for the message */
|
||||
} locoSpdMsg;
|
||||
|
||||
/* send packet immediate message */
|
||||
typedef struct sendpkt_t {
|
||||
uint8_t command;
|
||||
uint8_t mesg_size; /* ummmmm, size of the message in bytes? */
|
||||
uint8_t val7f; /* fixed value of 0x7f */
|
||||
uint8_t reps; /* repeat count */
|
||||
uint8_t dhi; /* high bits of data bytes */
|
||||
uint8_t im1;
|
||||
uint8_t im2;
|
||||
uint8_t im3;
|
||||
uint8_t im4;
|
||||
uint8_t im5;
|
||||
uint8_t chksum; /* exclusive-or checksum for the message */
|
||||
} sendPktMsg;
|
||||
|
||||
/* Long ACK message */
|
||||
typedef struct longack_t {
|
||||
uint8_t command;
|
||||
uint8_t opcode; /* op-code of message getting the response (msb=0) */
|
||||
uint8_t ack1; /* response code */
|
||||
uint8_t chksum; /* exclusive-or checksum for the message */
|
||||
} longAckMsg;
|
||||
|
||||
/* Write slot status message */
|
||||
typedef struct slotstat_t {
|
||||
uint8_t command;
|
||||
uint8_t slot; /* slot number for this request */
|
||||
uint8_t stat; /* status to be written */
|
||||
uint8_t chksum; /* exclusive-or checksum for the message */
|
||||
} slotStatusMsg;
|
||||
|
||||
/* Move/Link Slot Message */
|
||||
typedef struct slotmove_t {
|
||||
uint8_t command;
|
||||
uint8_t src; /* source slot number for the move/link */
|
||||
uint8_t dest; /* destination slot for the move/link */
|
||||
uint8_t chksum; /* exclusive-or checksum for the message */
|
||||
} slotMoveMsg;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t command; // OPC_PEER_XFER for replies, OPC_IMM_PACKET for commands
|
||||
uint8_t mesg_size; // 15 bytes
|
||||
uint8_t SRC; // source
|
||||
uint8_t DSTL; // destination, low byte
|
||||
uint8_t DSTH; // destination, high byte
|
||||
uint8_t ReqId; // Request ID, distinguishes commands
|
||||
uint8_t PXCT1; // MSBs of following data
|
||||
uint8_t D0; // Data Bytes
|
||||
uint8_t D1;
|
||||
uint8_t D2;
|
||||
uint8_t D3;
|
||||
uint8_t D4;
|
||||
uint8_t D5;
|
||||
uint8_t D6;
|
||||
} UhlenbrockMsg;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t command; // OPC_SL_RD_UHLI for replies, OPC_WR_SL_UHLI for commands
|
||||
uint8_t mesg_size; // 21 bytes
|
||||
uint8_t unk0;
|
||||
uint8_t slot; // slot number
|
||||
uint8_t stat; // slot status
|
||||
uint8_t adr; // loco address
|
||||
uint8_t adr2; // loco address high
|
||||
uint8_t trk; // track status
|
||||
uint8_t spd; // command speed
|
||||
uint8_t fhi; // function high bits: F12,F20,F28
|
||||
uint8_t dirf; // direction and F0-F4 bits
|
||||
uint8_t snd2; // F5..F11
|
||||
uint8_t snd3; // F13..F19
|
||||
uint8_t snd4; // F21..F27
|
||||
uint8_t unk1; // steps???
|
||||
uint8_t unk2;
|
||||
uint8_t unk3;
|
||||
uint8_t unk4;
|
||||
uint8_t unk5;
|
||||
uint8_t unk6;
|
||||
} UhliSlotMsg;
|
||||
|
||||
|
||||
typedef union {
|
||||
szMsg sz ;
|
||||
swRepMsg srp ;
|
||||
swReqMsg srq ;
|
||||
inputRepMsg ir ;
|
||||
slotReqMsg sr ;
|
||||
rwSlotDataMsg sd ;
|
||||
fastClockMsg fc ;
|
||||
progTaskMsg pt ;
|
||||
locoSndMsg ls ;
|
||||
locoDirfMsg ldf ;
|
||||
locoSpdMsg lsp ;
|
||||
sendPktMsg sp ;
|
||||
longAckMsg lack ;
|
||||
slotStatusMsg ss ;
|
||||
slotMoveMsg sm ;
|
||||
UhlenbrockMsg ub;
|
||||
UhliSlotMsg usd;
|
||||
uint8_t data[32] ;
|
||||
} lnMsg ;
|
||||
1260
PacoMouseCYD/src/PacoMouseCYD/lnet.ino
Normal file
104
PacoMouseCYD/src/PacoMouseCYD/play.ino
Normal file
@@ -0,0 +1,104 @@
|
||||
/* PacoMouseCYD throttle -- F. Cañada 2025-2026 -- https://usuaris.tinet.cat/fmco/
|
||||
*/
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// ***** STATION RUN - MODEL TRAIN GAME FOR KIDS *****
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
void updateStationTime (uint16_t seconds) {
|
||||
snprintf(staTimeBuf, ACC_LNG + 1, "%d:%02d", seconds / 60, seconds % 60);
|
||||
}
|
||||
|
||||
void updateStationTarget() {
|
||||
staStations = staLevel + 4;
|
||||
if (staStartTime < 10)
|
||||
staStartTime = 10;
|
||||
staTime = staStartTime + ((staLevel - 1) * 10);
|
||||
}
|
||||
|
||||
void newStationCounters (bool ini) {
|
||||
if (ini) {
|
||||
staStars = 0;
|
||||
staLevel = 1;
|
||||
randomSeed(millis());
|
||||
}
|
||||
staCurrStation = 0;
|
||||
updateStationTarget();
|
||||
}
|
||||
|
||||
uint8_t newStation(byte last) {
|
||||
uint8_t station; // genera numero estacion sin repetir la ultima
|
||||
do {
|
||||
station = random (0, staMaxStations);
|
||||
} while (station == last);
|
||||
return (station);
|
||||
}
|
||||
|
||||
void updateTargetStations() {
|
||||
snprintf(staStationsBuf, ACC_LNG + 1, "%d", staStations);
|
||||
}
|
||||
|
||||
void updateCountStations() {
|
||||
snprintf(staStationsBuf, ACC_LNG + 1, "%d/%d", staCurrStation, staStations);
|
||||
}
|
||||
|
||||
void updateStationLevel() {
|
||||
snprintf(staLevelBuf, ADDR_LNG + 1, "%d", staLevel);
|
||||
}
|
||||
|
||||
void updateStationStars() {
|
||||
snprintf(staStarsBuf, ADDR_LNG + 1, "%d", staStars);
|
||||
}
|
||||
|
||||
void setNewTarget() {
|
||||
uint16_t pos;
|
||||
staLastStation = newStation(staLastStation);
|
||||
iconData[ICON_STA_TARGET].color = staColors[staLastStation];
|
||||
pos = iconData[ICON_STA_TRAIN].x;
|
||||
iconData[ICON_STA_TRAIN].x = iconData[ICON_STA_TARGET].x;
|
||||
iconData[ICON_STA_TARGET].x = pos;
|
||||
iconData[ICON_STA_PIN].x = pos + 8;
|
||||
}
|
||||
|
||||
void clickTargetStation() {
|
||||
encoderValue = 0;
|
||||
locoData[myLocoData].mySpeed = 0;
|
||||
locoOperationSpeed();
|
||||
updateSpeedDir();
|
||||
staCurrStation++;
|
||||
if (staCurrStation == staStations) {
|
||||
stopTimer(TMR_STA_RUN);
|
||||
staLevel++;
|
||||
updateStationLevel();
|
||||
newStationCounters(false);
|
||||
updateTargetStations();
|
||||
updateStationTime(staTime);
|
||||
closeWindow(WIN_STA_PLAY);
|
||||
openWindow(WIN_STA_STARS); // well done!
|
||||
}
|
||||
else {
|
||||
updateCountStations();
|
||||
setNewTarget();
|
||||
newEvent(OBJ_WIN, WIN_STA_PLAY, EVNT_DRAW);
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t staGetTurnoutAdr(uint16_t eeAdr, uint16_t defAdr) {
|
||||
uint16_t adr;
|
||||
adr = (EEPROM.read(eeAdr) << 8) + EEPROM.read(eeAdr + 1);
|
||||
if (adr > 2048)
|
||||
adr = defAdr;
|
||||
return adr;
|
||||
}
|
||||
|
||||
void updateTurnoutButtons() {
|
||||
uint16_t n, icon;
|
||||
for (n = 0; n < 4; n++) {
|
||||
if (staTurnoutPos[n])
|
||||
fncData[FNC_STA_ACC0 + n].idIcon = bitRead(staTurnoutDef, n) ? FNC_TURNRD_OFF : FNC_TURNLD_OFF;
|
||||
else
|
||||
fncData[FNC_STA_ACC0 + n].idIcon = bitRead(staTurnoutDef, n) ? FNC_TURNRS_OFF : FNC_TURNLS_OFF;
|
||||
fncData[FNC_STA_ACC0 + n].colorOn = staTurnoutPos[n] ? COLOR_RED : COLOR_GREEN;
|
||||
}
|
||||
}
|
||||
399
PacoMouseCYD/src/PacoMouseCYD/steam.ino
Normal file
@@ -0,0 +1,399 @@
|
||||
/* PacoMouseCYD throttle -- F. Cañada 2025-2026 -- https://usuaris.tinet.cat/fmco/
|
||||
*/
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// ***** STEAM THROTTLE *****
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
void initSteamThrottle () {
|
||||
uint16_t n;
|
||||
if (oldSteamLoco != locoData[myLocoData].myAddr.address) {
|
||||
oldSteamLoco = locoData[myLocoData].myAddr.address;
|
||||
steamPressure = 80;
|
||||
waterLevelBoiler = 80;
|
||||
waterLevelTender = 350;
|
||||
oldPressure = 0;
|
||||
oldLevelBoiler = 0;
|
||||
oldLevelTender = 0;
|
||||
barData[BAR_JOHNSON].value = STEAM_JOHNSON_NEUTRAL; // neutral position
|
||||
barData[BAR_BRAKE].value = 0;
|
||||
steamDir = locoData[myLocoData].myDir;
|
||||
for (n = 0; n < MAX_LIMIT; n++)
|
||||
steamSpeedLimit[n] = LIMIT_NONE;
|
||||
}
|
||||
currentSteamTime = millis();
|
||||
steamTimeSpeed = currentSteamTime;
|
||||
steamTimeSteam = currentSteamTime;
|
||||
steamTimeWater = currentSteamTime;
|
||||
steamTimeLoad = currentSteamTime;
|
||||
steamTimeSmoke = currentSteamTime;
|
||||
shovelCoal = false;
|
||||
setFirebox();
|
||||
endWaterInjection();
|
||||
endTenderFill();
|
||||
setTimer(TMR_STEAM, 5, TMR_ONESHOT);
|
||||
changeSmoke = STEAM_SMOKE_FAST;
|
||||
oldPressure = 0;
|
||||
oldSpeedSteam = 305;
|
||||
encoderMax = 31; // set throttle to current speed
|
||||
updateSteamThrottle();
|
||||
if (steamDir != locoData[myLocoData].myDir) { // check Johnson bar position
|
||||
steamDir = locoData[myLocoData].myDir;
|
||||
barData[BAR_JOHNSON].value = 6 - barData[BAR_JOHNSON].value;
|
||||
}
|
||||
}
|
||||
|
||||
void updateSteamThrottle() {
|
||||
switch (wifiSetting.protocol) {
|
||||
case CLIENT_Z21:
|
||||
case CLIENT_XNET:
|
||||
if (bitRead(locoData[myLocoData].mySteps, 2)) { // 0..127
|
||||
currentSteamSpeed = locoData[myLocoData].mySpeed;
|
||||
encoderValue = currentSteamSpeed >> 2;
|
||||
}
|
||||
else {
|
||||
if (bitRead(locoData[myLocoData].mySteps, 1)) { // 0..31
|
||||
encoderValue = (locoData[myLocoData].mySpeed & 0x0F) << 1;
|
||||
if (bitRead(locoData[myLocoData].mySpeed, 4))
|
||||
bitSet(encoderValue, 0);
|
||||
currentSteamSpeed = (encoderValue > 3) ? (encoderValue << 2) + (encoderValue >> 3) : 0;
|
||||
}
|
||||
else { // 0..15
|
||||
encoderValue = locoData[myLocoData].mySpeed & 0x0F;
|
||||
encoderValue = (encoderValue > 1) ? encoderValue << 1 : 0;
|
||||
currentSteamSpeed = (encoderValue << 2) + (encoderValue >> 3);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CLIENT_LNET:
|
||||
case CLIENT_ECOS:
|
||||
currentSteamSpeed = locoData[myLocoData].mySpeed;
|
||||
encoderValue = currentSteamSpeed >> 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void steamProcess() {
|
||||
uint16_t value, newSpeed, mappedThrottle, jFactor;
|
||||
|
||||
steamSpeedLimit[LIMIT_THROTTLE] = (encoderValue << 2) + (encoderValue >> 3); // Read Throtle Speed (0..31 -> 0..127)
|
||||
|
||||
steamSpeedLimit[LIMIT_JOHNSON] = LIMIT_NONE;
|
||||
switch (barData[BAR_JOHNSON].value) { // Read Johnson Bar
|
||||
case 0: // full reverse
|
||||
jFactor = 3;
|
||||
changeSpeed = 80;
|
||||
steamDir = 0x00;
|
||||
break;
|
||||
case 1:
|
||||
jFactor = 2;
|
||||
changeSpeed = 200;
|
||||
steamDir = 0x00;
|
||||
break;
|
||||
case 2:
|
||||
jFactor = 1;
|
||||
changeSpeed = 500;
|
||||
steamDir = 0x00;
|
||||
break;
|
||||
case STEAM_JOHNSON_NEUTRAL: // Neutral position of Johnson Bar
|
||||
jFactor = 1;
|
||||
changeSpeed = 1000;
|
||||
steamSpeedLimit[LIMIT_JOHNSON] = 0;
|
||||
break;
|
||||
case 4:
|
||||
jFactor = 1;
|
||||
changeSpeed = 500;
|
||||
steamDir = 0x80;
|
||||
break;
|
||||
case 5:
|
||||
jFactor = 2;
|
||||
changeSpeed = 200;
|
||||
steamDir = 0x80;
|
||||
break;
|
||||
case 6: // full forward
|
||||
jFactor = 3;
|
||||
changeSpeed = 80;
|
||||
steamDir = 0x80;
|
||||
break;
|
||||
}
|
||||
|
||||
if (steamDir != locoData[myLocoData].myDir) { // Check direction
|
||||
locoData[myLocoData].myDir = steamDir;
|
||||
changeDirection();
|
||||
DEBUG_MSG("STEAM: Change direction")
|
||||
}
|
||||
|
||||
value = steamSpeedLimit[LIMIT_THROTTLE];
|
||||
changeSteam = 10000 - ((value * 9) * jFactor); // Steam timeout: 6571 to 10000
|
||||
changeWater = 14000 - ((value * 27) * jFactor); // Water timeout: 3713 to 14000
|
||||
if (barData[BAR_BRAKE].value > 0) { // Brake bar: 300, 150, 100
|
||||
changeSpeed = 300 / barData[BAR_BRAKE].value;
|
||||
}
|
||||
currentSteamTime = millis();
|
||||
|
||||
if (currentSteamTime > (steamTimeWater + changeWater)) { // Water consumption
|
||||
steamTimeWater = currentSteamTime;
|
||||
if (waterLevelBoiler > 0) {
|
||||
waterLevelBoiler--;
|
||||
DEBUG_MSG("Boiler Level: %d", waterLevelBoiler)
|
||||
}
|
||||
}
|
||||
if (waterLevelBoiler < 10) { // Stop loco if not enough water
|
||||
steamSpeedLimit[LIMIT_WATER] = 0;
|
||||
steamThrottleStop();
|
||||
}
|
||||
else {
|
||||
steamSpeedLimit[LIMIT_WATER] = LIMIT_NONE;
|
||||
}
|
||||
|
||||
if (currentSteamTime > (steamTimeSteam + changeSteam)) { // Steam consumption
|
||||
steamTimeSteam = currentSteamTime;
|
||||
if (steamPressure > 0)
|
||||
steamPressure--;
|
||||
}
|
||||
|
||||
if (steamPressure < 50) { // Limit speed based on steam level
|
||||
value = (steamPressure < 20) ? 0 : map(steamPressure, 20, 50, 20, 120);
|
||||
steamSpeedLimit[LIMIT_PRESSURE] = value;
|
||||
}
|
||||
else {
|
||||
steamSpeedLimit[LIMIT_PRESSURE] = LIMIT_NONE;
|
||||
}
|
||||
|
||||
if (currentSteamTime > (steamTimeLoad + STEAM_LOAD_TIME)) { // Load coal and water
|
||||
steamTimeLoad = currentSteamTime;
|
||||
if (shovelCoal) { // Fire open for shoveling coal
|
||||
if (steamPressure > 96) {
|
||||
shovelCoal = false;
|
||||
setFirebox();
|
||||
newEvent(OBJ_FNC, FNC_ST_FIRE, EVNT_DRAW);
|
||||
}
|
||||
else {
|
||||
if (steamPressure < 20) // slowly pressure up at beginning
|
||||
steamPressure += 1;
|
||||
else
|
||||
steamPressure += 2;
|
||||
}
|
||||
}
|
||||
if (waterInjection) { // Water injector open
|
||||
if (waterLevelTender > 0) { // Inject water with water from tender
|
||||
if (waterLevelBoiler > 95) {
|
||||
endWaterInjection();
|
||||
}
|
||||
else {
|
||||
waterLevelBoiler += 2;
|
||||
waterLevelTender--;
|
||||
}
|
||||
steamSpeedLimit[LIMIT_TENDER] = LIMIT_NONE;
|
||||
}
|
||||
else {
|
||||
endWaterInjection(); // Stop locomotive if tender empty
|
||||
steamSpeedLimit[LIMIT_TENDER] = 0;
|
||||
steamThrottleStop();
|
||||
}
|
||||
}
|
||||
if (fillTender) {
|
||||
if ((waterLevelTender > 495) || (currentSteamSpeed != 0)) { // Only fill tender when stopped
|
||||
endTenderFill();
|
||||
}
|
||||
else {
|
||||
waterLevelTender++;
|
||||
if (waterLevelTender > 6) // Minimum level to run again
|
||||
steamSpeedLimit[LIMIT_TENDER] = LIMIT_NONE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (currentSteamTime > (steamTimeSmoke + changeSmoke)) { // Chimney smoke
|
||||
steamTimeSmoke = currentSteamTime;
|
||||
if (currentSteamSpeed > 0) {
|
||||
fncData[FNC_ST_SMOKE].state = !fncData[FNC_ST_SMOKE].state;
|
||||
changeSmoke = map(currentSteamSpeed, 0, 127, STEAM_SMOKE_SLOW, STEAM_SMOKE_FAST);
|
||||
}
|
||||
else {
|
||||
fncData[FNC_ST_SMOKE].state = false;
|
||||
changeSmoke = STEAM_SMOKE_SLOW + STEAM_SMOKE_SLOW;
|
||||
}
|
||||
newEvent(OBJ_FNC, FNC_ST_SMOKE, EVNT_DRAW);
|
||||
}
|
||||
|
||||
if (barData[BAR_BRAKE].value > 0) { // Braking
|
||||
value = barData[BAR_BRAKE].value * 8;
|
||||
value = (currentSteamSpeed > value) ? (currentSteamSpeed - value) : 0;
|
||||
steamSpeedLimit[LIMIT_BRAKE] = value;
|
||||
}
|
||||
else {
|
||||
steamSpeedLimit[LIMIT_BRAKE] = LIMIT_NONE;
|
||||
}
|
||||
|
||||
targetSpeedSteam = LIMIT_NONE; // Find lower limit
|
||||
for (value = 0; value < MAX_LIMIT; value++) {
|
||||
if (steamSpeedLimit[value] < targetSpeedSteam)
|
||||
targetSpeedSteam = steamSpeedLimit[value];
|
||||
}
|
||||
|
||||
newSpeed = currentSteamSpeed;
|
||||
if (currentSteamTime > (steamTimeSpeed + changeSpeed)) { // Speed acceleration
|
||||
steamTimeSpeed = currentSteamTime;
|
||||
//DEBUG_MSG("Target: %d Current: %d New: %d", targetSpeedSteam, currentSteamSpeed, newSpeed)
|
||||
if (targetSpeedSteam > currentSteamSpeed) {
|
||||
newSpeed = currentSteamSpeed + 1;
|
||||
DEBUG_MSG("Inc New: %d", newSpeed)
|
||||
}
|
||||
if (targetSpeedSteam < currentSteamSpeed) {
|
||||
newSpeed = currentSteamSpeed - 1;
|
||||
DEBUG_MSG("Dec New: %d", newSpeed)
|
||||
}
|
||||
//DEBUG_MSG("New acc: %d", newSpeed)
|
||||
}
|
||||
|
||||
|
||||
if (currentSteamSpeed != newSpeed) { // changes in speed
|
||||
DEBUG_MSG("Step: %d - New: %d LIMITS ", currentSteamSpeed, newSpeed)
|
||||
#ifdef DEBUG
|
||||
for (value = 0; value < MAX_LIMIT; value++) {
|
||||
Serial.print(steamSpeedLimit[value]);
|
||||
Serial.print(" ");
|
||||
}
|
||||
Serial.println();
|
||||
#endif
|
||||
currentSteamSpeed = newSpeed;
|
||||
switch (wifiSetting.protocol) {
|
||||
case CLIENT_Z21:
|
||||
case CLIENT_XNET:
|
||||
if (bitRead(locoData[myLocoData].mySteps, 2)) { // 128 steps
|
||||
mappedThrottle = (currentSteamSpeed > 1) ? currentSteamSpeed : 0;
|
||||
}
|
||||
else {
|
||||
if (bitRead(locoData[myLocoData].mySteps, 1)) { // 28 steps
|
||||
if (currentSteamSpeed > 15) {
|
||||
mappedThrottle = currentSteamSpeed >> 3;
|
||||
bitWrite(mappedThrottle, 4, bitRead(currentSteamSpeed, 2));
|
||||
}
|
||||
else {
|
||||
mappedThrottle = 0;
|
||||
}
|
||||
}
|
||||
else { // 14 steps
|
||||
mappedThrottle = (currentSteamSpeed > 15) ? currentSteamSpeed >> 3 : 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CLIENT_LNET:
|
||||
case CLIENT_ECOS:
|
||||
mappedThrottle = (currentSteamSpeed > 1) ? currentSteamSpeed : 0;
|
||||
break;
|
||||
}
|
||||
locoData[myLocoData].mySpeed = mappedThrottle;
|
||||
locoOperationSpeed();
|
||||
DEBUG_MSG("Steam step: %d", currentSteamSpeed)
|
||||
if ((currentSteamSpeed > 0) && (changeSmoke > STEAM_SMOKE_SLOW)) { // initial chuff
|
||||
changeSmoke = 0;
|
||||
fncData[FNC_ST_SMOKE].state = false;
|
||||
}
|
||||
}
|
||||
|
||||
if ((oldLevelTender / 10) != (waterLevelTender / 10)) {
|
||||
oldLevelTender = waterLevelTender;
|
||||
barData[BAR_TENDER].value = waterLevelTender;
|
||||
newEvent(OBJ_BAR, BAR_TENDER, EVNT_DRAW);
|
||||
}
|
||||
|
||||
value = waterLevelBoiler / 2;
|
||||
if (oldLevelBoiler != value ) {
|
||||
oldLevelBoiler = value;
|
||||
barData[BAR_WATER].value = value;
|
||||
newEvent(OBJ_BAR, BAR_WATER, EVNT_DRAW);
|
||||
}
|
||||
|
||||
value = steamPressure * 270 / 100;
|
||||
if (oldPressure != value) {
|
||||
showPressure(value);
|
||||
DEBUG_MSG("Pressure: %d", steamPressure)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void startWaterInjection () {
|
||||
waterInjection = true;
|
||||
fncData[FNC_ST_WATER].colorOn = COLOR_DARKGREEN;
|
||||
drawObject(OBJ_FNC, FNC_ST_WATER);
|
||||
}
|
||||
|
||||
|
||||
void endWaterInjection () {
|
||||
waterInjection = false;
|
||||
fncData[FNC_ST_WATER].colorOn = COLOR_RED;
|
||||
drawObject(OBJ_FNC, FNC_ST_WATER);
|
||||
}
|
||||
|
||||
|
||||
void startTenderFill() {
|
||||
fillTender = true;
|
||||
//fncData[FNC_ST_TENDER].color = COLOR_RED;
|
||||
fncData[FNC_ST_TENDER].colorOn = COLOR_DARKGREEN;
|
||||
drawObject(OBJ_FNC, FNC_ST_TENDER);
|
||||
}
|
||||
|
||||
|
||||
void endTenderFill() {
|
||||
fillTender = false;
|
||||
//fncData[FNC_ST_TENDER].color = COLOR_WHITE;
|
||||
fncData[FNC_ST_TENDER].colorOn = COLOR_RED;
|
||||
drawObject(OBJ_FNC, FNC_ST_TENDER);
|
||||
}
|
||||
|
||||
|
||||
void setFirebox() {
|
||||
if (shovelCoal) {
|
||||
fncData[FNC_ST_FIRE].idIcon = FNC_FIRE_OP_OFF;
|
||||
fncData[FNC_ST_FIRE].color = COLOR_ORANGE;
|
||||
fncData[FNC_ST_FIRE].colorOn = COLOR_YELLOW;
|
||||
}
|
||||
else {
|
||||
fncData[FNC_ST_FIRE].idIcon = FNC_FIRE_CL_OFF;
|
||||
fncData[FNC_ST_FIRE].color = COLOR_SILVER;
|
||||
fncData[FNC_ST_FIRE].colorOn = COLOR_RED;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void steamThrottleStop() { // set controls for stop
|
||||
if (encoderValue > 0) {
|
||||
encoderValue = 0;
|
||||
showSpeedSteam(240);
|
||||
}
|
||||
if (barData[BAR_JOHNSON].value != STEAM_JOHNSON_NEUTRAL) {
|
||||
barData[BAR_JOHNSON].value = STEAM_JOHNSON_NEUTRAL; // Neutral
|
||||
drawObject(OBJ_BAR, BAR_JOHNSON);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void showPressure(uint16_t angle) {
|
||||
tft.setPivot(140, 105); // Set pivot to center of manometer in TFT screen
|
||||
sprite.setColorDepth(8); // Create an 8bpp Sprite
|
||||
sprite.createSprite(19, 19); // 8bpp requires 19 * 19 = 361 bytes
|
||||
sprite.setPivot(9, 9); // Set pivot relative to top left corner of Sprite
|
||||
sprite.fillSprite(COLOR_WHITE); // Fill the Sprite with background
|
||||
sprite.pushRotated(oldPressure);
|
||||
oldPressure = angle;
|
||||
sprite.drawBitmap(0, 0, needle_bar, 19, 19, COLOR_BLUE);
|
||||
sprite.pushRotated(angle);
|
||||
sprite.deleteSprite();
|
||||
}
|
||||
|
||||
void showSpeedSteam(uint16_t angle) {
|
||||
tft.setPivot(120, 170); // Set pivot to center of bar in TFT screen
|
||||
sprite.setColorDepth(8); // Create an 8bpp Sprite
|
||||
sprite.createSprite(83, 15); // 8bpp requires 83 * 15 = 1245 bytes
|
||||
sprite.setPivot(76, 7); // Set pivot relative to top left corner of Sprite
|
||||
sprite.fillSprite(COLOR_BLACK); // Fill the Sprite with background
|
||||
sprite.pushRotated(oldSpeedSteam);
|
||||
oldSpeedSteam = angle;
|
||||
sprite.drawBitmap(0, 0, speed_steam, 83, 15, COLOR_RED);
|
||||
sprite.pushRotated(angle);
|
||||
tft.drawArc(120, 170, 27, 22, 315, 45, COLOR_RED, COLOR_BLACK, false);
|
||||
sprite.deleteSprite();
|
||||
}
|
||||
842
PacoMouseCYD/src/PacoMouseCYD/system.ino
Normal file
@@ -0,0 +1,842 @@
|
||||
/* PacoMouseCYD throttle -- F. Cañada 2025-2026 -- https://usuaris.tinet.cat/fmco/
|
||||
*/
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// ***** SYSTEM SUPPORT *****
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
void initPins() {
|
||||
// Set all chip selects high to avoid bus contention during initialisation of each peripheral
|
||||
digitalWrite(TFT_CS, HIGH); // TFT screen chip select
|
||||
digitalWrite(SD_CS, HIGH); // SD card chips select
|
||||
digitalWrite(XPT2046_CS, HIGH); // Touch screen chips select
|
||||
pinMode (SW_BOOT, INPUT); // Button BOOT
|
||||
pinMode (ENCODER_A, INPUT); // Encoder
|
||||
pinMode (ENCODER_B, INPUT);
|
||||
pinMode (ENCODER_SW, INPUT);
|
||||
#if (USE_RGB_LED == PRESENT)
|
||||
pinMode(RGB_LED_R, OUTPUT); // RGB LED
|
||||
pinMode(RGB_LED_G, OUTPUT);
|
||||
pinMode(RGB_LED_B, OUTPUT);
|
||||
setColorRGB(0); // turn off RGB LED
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void setBacklight (uint8_t value) { // set PWM backlight
|
||||
#if (ESP_ARDUINO_VERSION_MAJOR > 2)
|
||||
// Code for version 3.x
|
||||
ledcWrite(TFT_BL, value);
|
||||
#else
|
||||
// Code for version 2.x
|
||||
ledcWrite(LEDC_CHANNEL_0, value);
|
||||
#endif
|
||||
currBacklight = value;
|
||||
}
|
||||
|
||||
void setRotationDisplay(uint8_t pos) { // Rotate display and touchscreen
|
||||
tft.setRotation(pos);
|
||||
touchscreen.setRotation((pos + XPT_ROTATION) & 0x03);
|
||||
}
|
||||
|
||||
void aliveAndKicking() {
|
||||
setTimer (TMR_BLIGHT, INACT_TIME, TMR_ONESHOT); // reset timeout and restore backlight
|
||||
if (currBacklight != backlight)
|
||||
setBacklight(backlight);
|
||||
}
|
||||
|
||||
#if (USE_RGB_LED == PRESENT)
|
||||
void setColorRGB (uint16_t color) { // set color of RGB LED
|
||||
int state;
|
||||
state = (color & 0x04) ? LOW : HIGH;
|
||||
digitalWrite(RGB_LED_G, state);
|
||||
state = (color & 0x02) ? LOW : HIGH;
|
||||
digitalWrite(RGB_LED_R, state);
|
||||
state = (color & 0x01) ? LOW : HIGH;
|
||||
digitalWrite(RGB_LED_B, state);
|
||||
DEBUG_MSG("Color: %d", color & 0x07)
|
||||
}
|
||||
#endif
|
||||
|
||||
initResult initSequence() { // Performs init sequence
|
||||
char label[MAX_LABEL_LNG];
|
||||
char chr;
|
||||
int n;
|
||||
initResult result;
|
||||
result = INIT_OK;
|
||||
delay(500);
|
||||
drawObject(OBJ_ICON, ICON_SDCARD); // detecting SD card
|
||||
if (sdDetected) {
|
||||
sprintf (FileName, "/image/logo.bmp");
|
||||
if (tft.width() == 240)
|
||||
drawBmp (FileName, 0, 180);
|
||||
else
|
||||
drawBmp (FileName, 40, 260);
|
||||
loadLocoFiles(SD, "/loco"); // load loco data & panel names from SD file
|
||||
loadAccPanelNames(SD);
|
||||
}
|
||||
else {
|
||||
if (LittleFS.begin(false)) {
|
||||
loadLocoFiles(LittleFS, "/loco"); // load loco data & panel names from FS file
|
||||
loadAccPanelNames(LittleFS);
|
||||
}
|
||||
else {
|
||||
DEBUG_MSG("LittleFS Mount Failed. Formating....");
|
||||
LittleFS.format();
|
||||
}
|
||||
drawObject(OBJ_ICON, ICON_NO_SD);
|
||||
result = INIT_NO_SD;
|
||||
DEBUG_MSG("Total: %ul Used: %ul", LittleFS.totalBytes(), LittleFS.usedBytes())
|
||||
}
|
||||
populateAccPanel(); // load first accessory panel
|
||||
barData[BAR_INIT].value = 10;
|
||||
drawObject(OBJ_BAR, BAR_INIT);
|
||||
drawObject(OBJ_ICON, ICON_WIFI); // connecting to WiFi network
|
||||
drawObject(OBJ_DRAWSTR, DSTR_INIT_STAT);
|
||||
drawObject(OBJ_LABEL, LBL_CONNECT);
|
||||
WiFi.mode(WIFI_STA);
|
||||
WiFi.begin(wifiSetting.ssid, wifiSetting.password);
|
||||
n = 0;
|
||||
while ((WiFi.status() != WL_CONNECTED) && n < 80) { // tries to connect to router in 20 seconds
|
||||
n += 2;
|
||||
barData[BAR_INIT].value = 10 + n;
|
||||
drawObject(OBJ_BAR, BAR_INIT);
|
||||
delay(500);
|
||||
DEBUG_MSG(".");
|
||||
}
|
||||
barData[BAR_INIT].value = 90;
|
||||
drawObject(OBJ_BAR, BAR_INIT);
|
||||
if (WiFi.status() == WL_CONNECTED) { // Connect to server with current protocol
|
||||
drawObject(OBJ_DRAWSTR, DSTR_INIT_STAT); // show Protocol
|
||||
getLabelTxt(LBL_SEL_Z21 + wifiSetting.protocol, label);
|
||||
tft.drawString(label, 20, 120, GFXFF);
|
||||
DEBUG_MSG("Channel: %d", WiFi.channel());
|
||||
DEBUG_MSG("IP address: %u.%u.%u.%u", WiFi.localIP().operator[](0), WiFi.localIP().operator[](1), WiFi.localIP().operator[](2), WiFi.localIP().operator[](3));
|
||||
DEBUG_MSG("%s", WiFi.macAddress().c_str())
|
||||
useID = false;
|
||||
switch (wifiSetting.protocol) {
|
||||
case CLIENT_Z21:
|
||||
WiFi.setSleep(false);
|
||||
Udp.begin(z21Port);
|
||||
//wifiSetting.port = z21Port;
|
||||
DEBUG_MSG("Now listening UDP port %d", z21Port);
|
||||
getStatusZ21(); // every x seconds
|
||||
getSerialNumber();
|
||||
delay(500);
|
||||
setBroadcastFlags (0x00000013); // Broadcasts and info messages concerning driving and switching, report changes on feedback bus & fast clock
|
||||
getStatusZ21();
|
||||
//askZ21begin (LAN_GET_BROADCASTFLAGS);
|
||||
//sendUDP (0x04);
|
||||
break;
|
||||
case CLIENT_LNET:
|
||||
if (!Client.connect(wifiSetting.CS_IP, wifiSetting.port)) {
|
||||
DEBUG_MSG("Connection to Loconet over TCP/IP failed");
|
||||
result = INIT_NO_CONNECT;
|
||||
}
|
||||
else {
|
||||
Client.setNoDelay(true);
|
||||
rcvStrPhase = WAIT_TOKEN;
|
||||
getTypeCS();
|
||||
}
|
||||
break;
|
||||
case CLIENT_XNET:
|
||||
if (!Client.connect(wifiSetting.CS_IP, XnetPort)) {
|
||||
DEBUG_MSG("Connection to Xpressnet failed");
|
||||
result = INIT_NO_CONNECT;
|
||||
}
|
||||
else {
|
||||
wifiSetting.port = XnetPort;
|
||||
Client.setNoDelay(true);
|
||||
rxIndice = FRAME1;
|
||||
getVersionXnet(); // pide la version del Xpressnet
|
||||
getStatusXnet(); // pide estado de la central
|
||||
}
|
||||
break;
|
||||
case CLIENT_ECOS:
|
||||
useID = true;
|
||||
if (!Client.connect(wifiSetting.CS_IP, ECoSPort)) {
|
||||
DEBUG_MSG("Connection to ECoS failed");
|
||||
result = INIT_NO_CONNECT;
|
||||
}
|
||||
else {
|
||||
wifiSetting.port = ECoSPort;
|
||||
Client.setNoDelay(true);
|
||||
requestViews();
|
||||
requestLocoList();
|
||||
waitWifiData(500);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
drawObject(OBJ_ICON, ICON_NO_WIFI);
|
||||
result = INIT_NO_WIFI;
|
||||
}
|
||||
barData[BAR_INIT].value = 95;
|
||||
drawObject(OBJ_BAR, BAR_INIT);
|
||||
drawObject(OBJ_ICON, ICON_INIT_LOCO); // fill image list
|
||||
initImageList();
|
||||
barData[BAR_INIT].value = 100;
|
||||
drawObject(OBJ_BAR, BAR_INIT);
|
||||
setTimer (TMR_END_LOGO, 7, TMR_ONESHOT); // Wait for answer
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
bool notLocked () { // check if not locked
|
||||
if (lockOptions & ((1 << LOCK_SEL_LOCO) | (1 << LOCK_TURNOUT) | (1 << LOCK_PROG)))
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool notLockedOption (byte opt) { // check if option not locked
|
||||
if (lockOptions & (1 << opt))
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// ***** TOUCHSCREEN *****
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
void calibrateTouchscreen(uint16_t colorIn, uint16_t colorOut, uint16_t bg) {
|
||||
uint16_t TS_TOP, TS_BOT, TS_LEFT, TS_RT;
|
||||
uint16_t x, y, z;
|
||||
TSPoint p;
|
||||
TS_TOP = 4095;
|
||||
TS_BOT = 0;
|
||||
TS_LEFT = 4095;
|
||||
TS_RT = 0;
|
||||
tft.fillScreen(bg);
|
||||
for (int i = 0; i < 4; i++) {
|
||||
tft.fillCircle(0, 0, 15, bg); // delete touch corners points
|
||||
tft.fillCircle(tft.width(), 0, 15, bg);
|
||||
tft.fillCircle(0, tft.height(), 15, bg);
|
||||
tft.fillCircle(tft.width(), tft.height(), 15, bg);
|
||||
DEBUG_MSG("Calibrate step: %d", i)
|
||||
switch (i) { // show current touch corner point
|
||||
case 0:
|
||||
tft.fillCircle(0, 0, 15, colorOut);
|
||||
tft.fillCircle(0, 0, 7, colorIn);
|
||||
break;
|
||||
case 1:
|
||||
tft.fillCircle(tft.width(), 0, 15, colorOut);
|
||||
tft.fillCircle(tft.width(), 0, 7, colorIn);
|
||||
break;
|
||||
case 2:
|
||||
tft.fillCircle(0, tft.height(), 15, colorOut);
|
||||
tft.fillCircle(0, tft.height(), 7, colorIn);
|
||||
break;
|
||||
case 3:
|
||||
tft.fillCircle(tft.width(), tft.height(), 15, colorOut);
|
||||
tft.fillCircle(tft.width(), tft.height(), 7, colorIn);
|
||||
break;
|
||||
}
|
||||
while (touchscreen.touched()) // wait to release
|
||||
delay(0);
|
||||
DEBUG_MSG("Pen released")
|
||||
while (!touchscreen.touched()) // wait to touch
|
||||
delay(0);
|
||||
DEBUG_MSG("Pen touched")
|
||||
touchscreen.readData(&x, &y, &z);
|
||||
if (x < TS_LEFT) {
|
||||
TS_LEFT = x;
|
||||
}
|
||||
if (y < TS_TOP) {
|
||||
TS_TOP = y;
|
||||
}
|
||||
if (x > TS_RT) {
|
||||
TS_RT = x;
|
||||
}
|
||||
if (y > TS_BOT) {
|
||||
TS_BOT = y;
|
||||
}
|
||||
}
|
||||
tft.fillCircle(tft.width(), tft.height(), 15, bg); // delete last touch corner point
|
||||
touchscreen.setCalibration(TS_LEFT, TS_RT, TS_TOP, TS_BOT);
|
||||
DEBUG_MSG("xMin: %d, xMax: %d, yMin: %d, yMax: %d", TS_LEFT, TS_RT, TS_TOP, TS_BOT);
|
||||
}
|
||||
|
||||
|
||||
void showClockData(uint16_t txtFocus) {
|
||||
uint16_t n;
|
||||
for (n = 0; n < 3; n++)
|
||||
txtData[TXT_HOUR + n].backgnd = COLOR_BACKGROUND;
|
||||
txtData[txtFocus].backgnd = COLOR_YELLOW; // select focus on selected field
|
||||
keybData[KEYB_CLOCK].idTextbox = txtFocus;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// ***** WIFI *****
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
void scanWiFi() {
|
||||
networks = 0;
|
||||
while (networks == 0) {
|
||||
WiFi.disconnect(true); //DISCONNECT WITH TRUE (SHUOLD TURN OFF THE RADIO)
|
||||
delay(1000);
|
||||
WiFi.mode(WIFI_STA); //CALLING THE WIFI MODE AS STATION
|
||||
WiFi.scanDelete();
|
||||
networks = WiFi.scanNetworks();
|
||||
DEBUG_MSG("Networks: %d", networks);
|
||||
if ((networks > 0) && (networks < 32768)) {
|
||||
encoderMax = networks - 1;
|
||||
encoderValue = 0;
|
||||
scrSSID = 0;
|
||||
}
|
||||
else
|
||||
networks = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void scanWiFiFill() {
|
||||
uint16_t n, line;
|
||||
n = (scrSSID > 5) ? scrSSID - 5 : 0;
|
||||
snprintf (ssidName1, SSID_LNG, WiFi.SSID(n).c_str());
|
||||
snprintf (ssidName2, SSID_LNG, WiFi.SSID(n + 1).c_str());
|
||||
snprintf (ssidName3, SSID_LNG, WiFi.SSID(n + 2).c_str());
|
||||
snprintf (ssidName4, SSID_LNG, WiFi.SSID(n + 3).c_str());
|
||||
snprintf (ssidName5, SSID_LNG, WiFi.SSID(n + 4).c_str());
|
||||
snprintf (ssidName6, SSID_LNG, WiFi.SSID(n + 5).c_str());
|
||||
line = (scrSSID > 5) ? 5 : scrSSID;
|
||||
for (n = 0; n < 6; n++) {
|
||||
txtData[TXT_SSID1 + n].backgnd = (n == line) ? COLOR_BLUE : COLOR_BLACK;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void wifiAnalyzer() {
|
||||
int16_t n, i;
|
||||
char txt[10];
|
||||
for (n = 0; n < 14; n++) {
|
||||
ap_count[n] = 0;
|
||||
max_rssi[n] = RSSI_FLOOR;
|
||||
}
|
||||
n = WiFi.scanNetworks();
|
||||
drawObject(OBJ_DRAWSTR, DSTR_WIFI_SCAN);
|
||||
drawObject(OBJ_LABEL, LBL_SSID_SCAN);
|
||||
drawObject(OBJ_FNC, FNC_SCAN_RESET);
|
||||
tft.setFreeFont(FSSB6);
|
||||
if ((n > 0) && (n < 32768)) {
|
||||
for (i = 0; i < n; i++) {
|
||||
int32_t channel = WiFi.channel(i);
|
||||
int32_t rssi = WiFi.RSSI(i);
|
||||
uint16_t color = channel_color[channel - 1];
|
||||
int height = constrain(map(rssi, RSSI_FLOOR, RSSI_CEILING, 1, GRAPH_HEIGHT), 1, GRAPH_HEIGHT);
|
||||
// channel stat
|
||||
ap_count[channel - 1]++;
|
||||
if (rssi > max_rssi[channel - 1]) {
|
||||
max_rssi[channel - 1] = rssi;
|
||||
}
|
||||
tft.drawLine((channel * CHANNEL_WIDTH) + GRAPH_OFFSET, GRAPH_BASELINE - height, ((channel - 1) * CHANNEL_WIDTH) + GRAPH_OFFSET, GRAPH_BASELINE + 1, color);
|
||||
tft.drawLine((channel * CHANNEL_WIDTH) + GRAPH_OFFSET, GRAPH_BASELINE - height, ((channel + 1) * CHANNEL_WIDTH) + GRAPH_OFFSET, GRAPH_BASELINE + 1, color);
|
||||
// Print SSID, signal strengh and if not encrypted
|
||||
tft.setTextColor(color);
|
||||
tft.setTextDatum(MC_DATUM);
|
||||
tft.drawString(WiFi.SSID(i), (channel * CHANNEL_WIDTH) + GRAPH_OFFSET, GRAPH_BASELINE - 10 - height, GFXFF);
|
||||
// rest for WiFi routine?
|
||||
delay(10);
|
||||
}
|
||||
}
|
||||
else {
|
||||
tft.setFreeFont(FSSB9);
|
||||
tft.setTextColor(COLOR_WHITE);
|
||||
tft.drawString("SSID = 0", 120 + GRAPH_OFFSET, 120, GFXFF);
|
||||
}
|
||||
tft.setFreeFont(FSSB6);
|
||||
tft.setTextDatum(TC_DATUM);
|
||||
for (i = 1; i < 15; i++) {
|
||||
tft.setTextColor(channel_color[i - 1]);
|
||||
snprintf(txt, 10, "%d", i);
|
||||
tft.drawString(txt, (i * CHANNEL_WIDTH) + GRAPH_OFFSET, GRAPH_BASELINE + 12, GFXFF);
|
||||
if (ap_count[i - 1] > 0) {
|
||||
snprintf(txt, 10, "(%d)", ap_count[i - 1]);
|
||||
tft.drawString(txt, (i * CHANNEL_WIDTH) + GRAPH_OFFSET, GRAPH_BASELINE + 24, GFXFF);
|
||||
}
|
||||
}
|
||||
setTimer(TMR_SCAN, 50, TMR_ONESHOT);
|
||||
}
|
||||
|
||||
|
||||
void wifiProcess() {
|
||||
switch (wifiSetting.protocol) {
|
||||
case CLIENT_Z21:
|
||||
processZ21();
|
||||
break;
|
||||
case CLIENT_XNET:
|
||||
processXnet();
|
||||
break;
|
||||
case CLIENT_LNET:
|
||||
processLnet();
|
||||
break;
|
||||
case CLIENT_ECOS:
|
||||
ECoSProcess();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void waitWifiData(uint32_t ms) {
|
||||
uint32_t now;
|
||||
now = millis();
|
||||
while ((millis() - now) < ms)
|
||||
wifiProcess();
|
||||
}
|
||||
|
||||
|
||||
void setProtocolData() {
|
||||
uint16_t n;
|
||||
useID = false;
|
||||
switch (wifiSetting.protocol) {
|
||||
case CLIENT_Z21:
|
||||
snprintf(keybProtoBuf, PWD_LNG, "Z21");
|
||||
snprintf(keybPortBuf, 6, "%d", z21Port);
|
||||
break;
|
||||
case CLIENT_LNET:
|
||||
if (wifiSetting.serverType)
|
||||
snprintf(keybProtoBuf, PWD_LNG, "LBServer");
|
||||
else
|
||||
snprintf(keybProtoBuf, PWD_LNG, "Loconet Binary");
|
||||
snprintf(keybPortBuf, 6, "%d", wifiSetting.port);
|
||||
break;
|
||||
case CLIENT_XNET:
|
||||
snprintf(keybProtoBuf, PWD_LNG, "Xpressnet LAN");
|
||||
snprintf(keybPortBuf, 6, "%d", XnetPort);
|
||||
break;
|
||||
case CLIENT_ECOS:
|
||||
useID = true;
|
||||
snprintf(keybProtoBuf, PWD_LNG, "ECoS");
|
||||
snprintf(keybPortBuf, 6, "%d", ECoSPort);
|
||||
break;
|
||||
}
|
||||
for (n = 0; n < 5; n++)
|
||||
txtData[TXT_IP1 + n].backgnd = COLOR_BACKGROUND;
|
||||
txtData[TXT_IP1].backgnd = COLOR_YELLOW; // select focus on first IP byte
|
||||
keybData[KEYB_IP].idTextbox = TXT_IP1;
|
||||
}
|
||||
|
||||
void setOptionsData() {
|
||||
switchData[SW_OPT_ADR].state = false; // show disable all as default
|
||||
switchData[SW_OPT_ADR].colorKnob = COLOR_BACKGROUND;
|
||||
radioData[RAD_CSTATION].value = radioData[RAD_CSTATION].num;
|
||||
switch (wifiSetting.protocol) {
|
||||
case CLIENT_Z21:
|
||||
switchData[SW_OPT_ADR].colorKnob = COLOR_WHITE;
|
||||
switchData[SW_OPT_ADR].state = (shortAddress == 99) ? true : false;
|
||||
break;
|
||||
case CLIENT_XNET:
|
||||
break;
|
||||
case CLIENT_LNET:
|
||||
radioData[RAD_CSTATION].value = typeCmdStation;
|
||||
break;
|
||||
case CLIENT_ECOS:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// ***** PROTOCOL COMMON *****
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
void infoLocomotora (unsigned int loco) {
|
||||
DEBUG_MSG("Info Loco % d", loco)
|
||||
switch (wifiSetting.protocol) {
|
||||
case CLIENT_Z21:
|
||||
infoLocomotoraZ21 (loco);
|
||||
break;
|
||||
case CLIENT_XNET:
|
||||
infoLocomotoraXnet (loco);
|
||||
break;
|
||||
case CLIENT_LNET:
|
||||
infoLocomotoraLnet (loco);
|
||||
break;
|
||||
case CLIENT_ECOS:
|
||||
infoLocomotoraECoS (loco); // ID
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void locoOperationSpeed() {
|
||||
switch (wifiSetting.protocol) {
|
||||
case CLIENT_Z21:
|
||||
locoOperationSpeedZ21();
|
||||
break;
|
||||
case CLIENT_XNET:
|
||||
locoOperationSpeedXnet();
|
||||
break;
|
||||
case CLIENT_LNET:
|
||||
locoOperationSpeedLnet();
|
||||
break;
|
||||
case CLIENT_ECOS:
|
||||
locoOperationSpeedECoS();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void changeDirection() {
|
||||
switch (wifiSetting.protocol) {
|
||||
case CLIENT_Z21:
|
||||
locoOperationSpeedZ21();
|
||||
break;
|
||||
case CLIENT_XNET:
|
||||
locoOperationSpeedXnet();
|
||||
break;
|
||||
case CLIENT_LNET:
|
||||
changeDirectionF0F4Lnet();
|
||||
break;
|
||||
case CLIENT_ECOS:
|
||||
changeDirectionECoS();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void funcOperations (uint8_t fnc) {
|
||||
switch (wifiSetting.protocol) {
|
||||
case CLIENT_Z21:
|
||||
funcOperationsZ21 (fnc);
|
||||
break;
|
||||
case CLIENT_XNET:
|
||||
funcOperationsXnet (fnc);
|
||||
break;
|
||||
case CLIENT_LNET:
|
||||
funcOperationsLnet (fnc);
|
||||
break;
|
||||
case CLIENT_ECOS:
|
||||
funcOperationsECoS(fnc);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
byte getCurrentStep() {
|
||||
byte value;
|
||||
switch (wifiSetting.protocol) {
|
||||
case CLIENT_Z21:
|
||||
value = getCurrentStepZ21();
|
||||
break;
|
||||
case CLIENT_XNET:
|
||||
value = getCurrentStepXnet();
|
||||
break;
|
||||
case CLIENT_LNET:
|
||||
value = getCurrentStepLnet();
|
||||
break;
|
||||
case CLIENT_ECOS:
|
||||
value = getCurrentStepECoS();
|
||||
break;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
void releaseLoco() {
|
||||
switch (wifiSetting.protocol) {
|
||||
case CLIENT_LNET:
|
||||
doDispatchGet = false;
|
||||
doDispatchPut = false;
|
||||
liberaSlot(); // pasa slot actual a COMMON
|
||||
break;
|
||||
case CLIENT_ECOS:
|
||||
releaseLocoECoS();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void sendAccessory(unsigned int FAdr, int pair, bool activate) {
|
||||
switch (wifiSetting.protocol) {
|
||||
case CLIENT_Z21:
|
||||
setAccessoryZ21(FAdr, pair, activate);
|
||||
break;
|
||||
case CLIENT_XNET:
|
||||
setAccessoryXnet(FAdr, activate, pair);
|
||||
break;
|
||||
case CLIENT_LNET:
|
||||
lnetRequestSwitch (FAdr, activate, pair);
|
||||
break;
|
||||
case CLIENT_ECOS:
|
||||
setAccessoryECoS(FAdr, pair, activate);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void resumeOperations() {
|
||||
switch (wifiSetting.protocol) {
|
||||
case CLIENT_Z21:
|
||||
resumeOperationsZ21();
|
||||
break;
|
||||
case CLIENT_XNET:
|
||||
resumeOperationsXnet();
|
||||
break;
|
||||
case CLIENT_LNET:
|
||||
resumeOperationsLnet();
|
||||
break;
|
||||
case CLIENT_ECOS:
|
||||
resumeOperationsECoS();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void emergencyOff() {
|
||||
switch (wifiSetting.protocol) {
|
||||
case CLIENT_Z21:
|
||||
emergencyOffZ21();
|
||||
break;
|
||||
case CLIENT_XNET:
|
||||
emergencyOffXnet();
|
||||
break;
|
||||
case CLIENT_LNET:
|
||||
emergencyOffLnet();
|
||||
break;
|
||||
case CLIENT_ECOS:
|
||||
emergencyOffECoS();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void togglePower() {
|
||||
if (isTrackOff())
|
||||
resumeOperations(); // Track Power On
|
||||
else
|
||||
emergencyOff(); // Track Power Off
|
||||
}
|
||||
|
||||
|
||||
bool isTrackOff() {
|
||||
bool state;
|
||||
switch (wifiSetting.protocol) {
|
||||
case CLIENT_Z21:
|
||||
state = (csStatus & csTrackVoltageOff) ? true : false;
|
||||
break;
|
||||
case CLIENT_XNET:
|
||||
state = (csStatus & csEmergencyOff) ? true : false;
|
||||
break;
|
||||
case CLIENT_LNET:
|
||||
state = (bitRead(mySlot.trk, 0)) ? false : true;
|
||||
break;
|
||||
case CLIENT_ECOS:
|
||||
state = (csStatus > 0) ? false : true;
|
||||
break;
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
void getStatusCS() {
|
||||
switch (wifiSetting.protocol) {
|
||||
case CLIENT_Z21:
|
||||
getStatusZ21();
|
||||
break;
|
||||
case CLIENT_XNET:
|
||||
getStatusXnet();
|
||||
break;
|
||||
case CLIENT_LNET:
|
||||
getTypeCS(); // workaround, not defined for Lnet
|
||||
break;
|
||||
case CLIENT_ECOS:
|
||||
getStatusECoS();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void setTime(byte hh, byte mm, byte rate) {
|
||||
switch (wifiSetting.protocol) {
|
||||
case CLIENT_Z21:
|
||||
setTimeZ21(hh, mm, rate);
|
||||
break;
|
||||
case CLIENT_XNET:
|
||||
setTimeXnet(hh, mm, rate);
|
||||
break;
|
||||
case CLIENT_LNET:
|
||||
setTimeLnet(hh, mm, rate);
|
||||
break;
|
||||
// ECoS not supported
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void readCV (unsigned int adr, byte stepPrg) {
|
||||
switch (wifiSetting.protocol) {
|
||||
case CLIENT_Z21:
|
||||
readCVZ21(adr, stepPrg);
|
||||
break;
|
||||
case CLIENT_XNET:
|
||||
readCVXnet(adr, stepPrg);
|
||||
break;
|
||||
case CLIENT_LNET:
|
||||
readCVLnet(adr, stepPrg);
|
||||
break;
|
||||
case CLIENT_ECOS:
|
||||
readCVECoS(adr, stepPrg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void writeCV (unsigned int adr, unsigned int data, byte stepPrg) {
|
||||
switch (wifiSetting.protocol) {
|
||||
case CLIENT_Z21:
|
||||
writeCVZ21(adr, data, stepPrg);
|
||||
break;
|
||||
case CLIENT_XNET:
|
||||
writeCVXnet(adr, data, stepPrg);
|
||||
break;
|
||||
case CLIENT_LNET:
|
||||
writeCVLnet(adr, data, stepPrg);
|
||||
break;
|
||||
case CLIENT_ECOS:
|
||||
writeCVECoS(adr, data, stepPrg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void exitProgramming() {
|
||||
switch (wifiSetting.protocol) {
|
||||
case CLIENT_Z21:
|
||||
if (csStatus & csProgrammingModeActive)
|
||||
resumeOperationsZ21();
|
||||
break;
|
||||
case CLIENT_XNET:
|
||||
if (csStatus & csServiceMode)
|
||||
resumeOperationsXnet();
|
||||
break;
|
||||
case CLIENT_ECOS:
|
||||
exitProgrammingECoS();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// ***** CV PROGRAMMING *****
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
void endProg() { // Fin de programcion/lectura CV
|
||||
DEBUG_MSG("END PROG: CVData - % d Step: % d", CVdata, progStepCV);
|
||||
if (CVdata > 255) {
|
||||
if (progStepCV == PRG_RD_CV29) // Si buscaba direccion, muestra CV1 en lugar de CV29
|
||||
CVaddress = 1;
|
||||
showDataCV();
|
||||
}
|
||||
else {
|
||||
switch (progStepCV) {
|
||||
case PRG_CV:
|
||||
showDataCV();
|
||||
break;
|
||||
case PRG_RD_CV29:
|
||||
cv29 = (byte) CVdata;
|
||||
if (bitRead(cv29, 5)) {
|
||||
CVaddress = 17; // Long address
|
||||
readCV(CVaddress, PRG_RD_CV17);
|
||||
}
|
||||
else {
|
||||
CVaddress = 1; // Short address
|
||||
readCV(CVaddress, PRG_RD_CV1);
|
||||
}
|
||||
break;
|
||||
case PRG_RD_CV1:
|
||||
decoAddress = CVdata;
|
||||
showDirCV();
|
||||
break;
|
||||
case PRG_RD_CV17:
|
||||
cv17 = (byte) CVdata;
|
||||
CVaddress = 18;
|
||||
readCV(CVaddress, PRG_RD_CV18);
|
||||
break;
|
||||
case PRG_RD_CV18:
|
||||
cv18 = (byte) CVdata;
|
||||
decoAddress = ((cv17 & 0x3F) << 8) | cv18;
|
||||
showDirCV();
|
||||
break;
|
||||
case PRG_WR_CV17: // Long address
|
||||
CVaddress = 18;
|
||||
writeCV(CVaddress, lowByte(decoAddress), PRG_WR_CV18);
|
||||
break;
|
||||
case PRG_WR_CV18:
|
||||
bitSet(cv29, 5);
|
||||
CVaddress = 29;
|
||||
writeCV(CVaddress, cv29, PRG_WR_CV29);
|
||||
break;
|
||||
case PRG_WR_CV1: // short address
|
||||
bitClear(cv29, 5);
|
||||
CVaddress = 29;
|
||||
writeCV(CVaddress, cv29, PRG_WR_CV29);
|
||||
break;
|
||||
case PRG_WR_CV29:
|
||||
showDirCV();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void showDataCV() { // muestra valor de la CV
|
||||
progStepCV = PRG_IDLE;
|
||||
enterCVdata = (CVdata > 255) ? false : true;
|
||||
setStatusCV(); // show error / manufacturer / CV / pom
|
||||
setFieldsCV();
|
||||
setBitsCV();
|
||||
if (isWindow(WIN_ALERT))
|
||||
closeWindow(WIN_ALERT);
|
||||
if (isWindow(WIN_PROG_CV)) {
|
||||
showFieldsCV();
|
||||
newEvent(OBJ_TXT, TXT_CV_STATUS, EVNT_DRAW);
|
||||
}
|
||||
if (wifiSetting.protocol == CLIENT_LNET)
|
||||
progUhli(UHLI_PRG_END);
|
||||
}
|
||||
|
||||
|
||||
void showDirCV() { // muestra direccion de la locomotora segun sus CV
|
||||
progStepCV = PRG_IDLE;
|
||||
setStatusCV(); // show error / manufacturer / CV / pom
|
||||
setFieldsCV();
|
||||
setBitsCV();
|
||||
if (isWindow(WIN_ALERT))
|
||||
closeWindow(WIN_ALERT);
|
||||
sprintf(locoEditAddr, " % d", decoAddress);
|
||||
openWindow(WIN_PROG_ADDR);
|
||||
if (wifiSetting.protocol == CLIENT_LNET)
|
||||
progUhli(UHLI_PRG_END);
|
||||
if (wifiSetting.protocol != CLIENT_ECOS)
|
||||
pushLoco(decoAddress); // mete esta loco en el stack
|
||||
}
|
||||
|
||||
|
||||
void readBasicCV (uint16_t num) {
|
||||
closeWindow(WIN_READ_CV);
|
||||
if (num == 1) {
|
||||
readCV(29, PRG_RD_CV29);
|
||||
}
|
||||
else {
|
||||
CVaddress = num;
|
||||
readCV(num, PRG_CV);
|
||||
}
|
||||
alertWindow(ERR_CV);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// ***** EEPROM *****
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
void saveCalibrationValues() {
|
||||
TouchCalibration cal;
|
||||
cal = touchscreen.getCalibration();
|
||||
EEPROM.write (EE_XMIN_H, highByte(cal.xMin));
|
||||
EEPROM.write (EE_XMIN_L, lowByte(cal.xMin));
|
||||
EEPROM.write (EE_XMAX_H, highByte(cal.xMax));
|
||||
EEPROM.write (EE_XMAX_L, lowByte(cal.xMax));
|
||||
EEPROM.write (EE_YMIN_H, highByte(cal.yMin));
|
||||
EEPROM.write (EE_YMIN_L, lowByte(cal.yMin));
|
||||
EEPROM.write (EE_YMAX_H, highByte(cal.yMax));
|
||||
EEPROM.write (EE_YMAX_L, lowByte(cal.yMax));
|
||||
EEPROM.commit();
|
||||
}
|
||||
544
PacoMouseCYD/src/PacoMouseCYD/translations.h
Normal file
@@ -0,0 +1,544 @@
|
||||
/* PacoMouseCYD throttle -- F. Cañada 2025-2026 -- https://usuaris.tinet.cat/fmco/
|
||||
*/
|
||||
|
||||
enum language {LANG_ENGLISH, LANG_SPANISH, LANG_CATALAN, LANG_GERMAN, MAX_LANG};
|
||||
|
||||
static const char *translations[][MAX_LANG] = { // DON'T CHANGE ORDER: Same order defined in labelObj. If a complete translation is missing, must be English definition.
|
||||
{ // LBL_PACO_TXT
|
||||
[LANG_ENGLISH] = "PacoMouseCYD",
|
||||
},
|
||||
{ // LBL_INIT
|
||||
[LANG_ENGLISH] = "Welcome!",
|
||||
[LANG_SPANISH] = "Bienvenido!",
|
||||
[LANG_CATALAN] = "Benvingut!",
|
||||
[LANG_GERMAN] = "Willkommen!",
|
||||
},
|
||||
{ // LBL_CONNECT
|
||||
[LANG_ENGLISH] = "Connecting...",
|
||||
[LANG_SPANISH] = "Conectando...",
|
||||
[LANG_CATALAN] = "Connectant...",
|
||||
[LANG_GERMAN] = "Verbindung...",
|
||||
},
|
||||
{ // LBL_PRESS
|
||||
[LANG_ENGLISH] = "Touch to start...",
|
||||
[LANG_SPANISH] = "Toca para empezar...",
|
||||
[LANG_CATALAN] = "Toca per iniciar...",
|
||||
[LANG_GERMAN] = "Beruhren Sie den\nBildschirm, um \nzu beginnen...",
|
||||
},
|
||||
{ // LBL_CAL
|
||||
[LANG_ENGLISH] = "To calibrate the\ntouchscreen, touch the\ncorners that appear\nwith the pen.",
|
||||
[LANG_SPANISH] = "Para calibrar la pantalla,\ntoque las esquinas que\naparecen con el lapiz",
|
||||
[LANG_CATALAN] = "Per calibrar la pantalla,\ntoqueu les cantonades que\napareixen amb el llapis",
|
||||
[LANG_GERMAN] = "Um den Touchscreen\nzu kalibrieren, beruhren\nSie die angezeigten Ecken\nmit dem Stift.",
|
||||
},
|
||||
{ // LBL_CAL_DONE
|
||||
[LANG_ENGLISH] = "Calibration done.",
|
||||
[LANG_SPANISH] = "Calibracion realizada.",
|
||||
[LANG_CATALAN] = "Calibratge realitzat.",
|
||||
[LANG_GERMAN] = "Kalibrierung\nabgeschlossen.",
|
||||
},
|
||||
{ // LBL_SCAN
|
||||
[LANG_ENGLISH] = "SSID WiFi\nScanning...",
|
||||
[LANG_SPANISH] = "SSID WiFi\nBuscando......",
|
||||
[LANG_CATALAN] = "SSID WiFi\nEscanejant...",
|
||||
[LANG_GERMAN] = "SSID WiFi\nScannen...",
|
||||
},
|
||||
{ // LBL_SSID_SCAN
|
||||
[LANG_ENGLISH] = "SSID WiFi",
|
||||
},
|
||||
{ // LBL_SSID
|
||||
[LANG_ENGLISH] = "SSID",
|
||||
},
|
||||
{ // LBL_IP
|
||||
[LANG_ENGLISH] = "IP",
|
||||
},
|
||||
{ // LBL_PWD_HIDE
|
||||
[LANG_ENGLISH] = "Password",
|
||||
[LANG_SPANISH] = NULL,
|
||||
[LANG_CATALAN] = NULL,
|
||||
[LANG_GERMAN] = "Passwort",
|
||||
},
|
||||
{ // LBL_PORT
|
||||
[LANG_ENGLISH] = "Port",
|
||||
[LANG_SPANISH] = "Puerto",
|
||||
},
|
||||
{ // LBL_PROTOCOL
|
||||
[LANG_ENGLISH] = "Protocol",
|
||||
[LANG_SPANISH] = "Protocolo",
|
||||
[LANG_CATALAN] = NULL,
|
||||
[LANG_GERMAN] = "Protokoll",
|
||||
},
|
||||
{ // LBL_SEL_PROT
|
||||
[LANG_ENGLISH] = "Protocol",
|
||||
[LANG_SPANISH] = "Protocolo",
|
||||
[LANG_CATALAN] = NULL,
|
||||
[LANG_GERMAN] = "Protokoll",
|
||||
},
|
||||
{ // LBL_SEL_Z21
|
||||
[LANG_ENGLISH] = "Z21",
|
||||
},
|
||||
{ // LBL_SEL_XNET
|
||||
[LANG_ENGLISH] = "Xpressnet LAN",
|
||||
},
|
||||
{ // LBL_SEL_ECOS
|
||||
[LANG_ENGLISH] = "ECoS",
|
||||
},
|
||||
{ // LBL_SEL_LNET
|
||||
[LANG_ENGLISH] = "Loconet over TCP/IP",
|
||||
},
|
||||
{ // LBL_SEL_LBSERVER
|
||||
[LANG_ENGLISH] = "LBServer",
|
||||
},
|
||||
{ // LBL_SEL_BINARY
|
||||
[LANG_ENGLISH] = "Binary",
|
||||
},
|
||||
{ // LBL_OPTIONS
|
||||
[LANG_ENGLISH] = "Options",
|
||||
[LANG_SPANISH] = "Opciones",
|
||||
[LANG_CATALAN] = "Opcions",
|
||||
[LANG_GERMAN] = "Optionen",
|
||||
},
|
||||
{ // LBL_NAME
|
||||
[LANG_ENGLISH] = "Name",
|
||||
[LANG_SPANISH] = "Nombre",
|
||||
[LANG_CATALAN] = "Nom",
|
||||
[LANG_GERMAN] = NULL,
|
||||
},
|
||||
{ // LBL_ADDR
|
||||
[LANG_ENGLISH] = "Address",
|
||||
[LANG_SPANISH] = "Direccion",
|
||||
[LANG_CATALAN] = "Direccio",
|
||||
[LANG_GERMAN] = "Adresse",
|
||||
},
|
||||
{ // LBL_IMAGE
|
||||
[LANG_ENGLISH] = "Image",
|
||||
[LANG_SPANISH] = "Imagen",
|
||||
[LANG_CATALAN] = "Imatge",
|
||||
[LANG_GERMAN] = "Bild",
|
||||
},
|
||||
{ // LBL_VMAX
|
||||
[LANG_ENGLISH] = "Speed max.",
|
||||
[LANG_SPANISH] = "Vel. max.",
|
||||
[LANG_CATALAN] = "Vel. max.",
|
||||
[LANG_GERMAN] = "Geschw.max.",
|
||||
},
|
||||
{ // LBL_FUNC
|
||||
[LANG_ENGLISH] = "Functions",
|
||||
[LANG_SPANISH] = "Funciones",
|
||||
[LANG_CATALAN] = "Funcions",
|
||||
[LANG_GERMAN] = "Funktionen",
|
||||
},
|
||||
{ // LBL_SERVICE
|
||||
[LANG_ENGLISH] = "Service Mode",
|
||||
[LANG_SPANISH] = "Modo Servicio",
|
||||
[LANG_CATALAN] = "Mode Servei",
|
||||
[LANG_GERMAN] = "Servicemodus",
|
||||
},
|
||||
{ // LBL_KMH
|
||||
[LANG_ENGLISH] = "km/h",
|
||||
},
|
||||
{ // LBL_SHUNTING
|
||||
[LANG_ENGLISH] = "Shunting",
|
||||
[LANG_SPANISH] = "Maniobras",
|
||||
[LANG_CATALAN] = "Maniobres",
|
||||
[LANG_GERMAN] = "Rangieren",
|
||||
},
|
||||
{ // LBL_RATE
|
||||
[LANG_ENGLISH] = "Rate 1:",
|
||||
[LANG_SPANISH] = "Ratio 1:",
|
||||
[LANG_CATALAN] = "Ratio 1:",
|
||||
[LANG_GERMAN] = NULL,
|
||||
},
|
||||
{ // LBL_CHG_WIFI
|
||||
[LANG_ENGLISH] = "Reset to apply\nchanges",
|
||||
[LANG_SPANISH] = "Reinicie para\naplicar los\ncambios",
|
||||
[LANG_CATALAN] = "Reiniciar per \naplicar els\ncanvis",
|
||||
[LANG_GERMAN] = "Neustart, um die\nAnderungen zu\nübernehmen",
|
||||
},
|
||||
{ // LBL_EDIT_FUNC
|
||||
[LANG_ENGLISH] = "Functions",
|
||||
[LANG_SPANISH] = "Funciones",
|
||||
[LANG_CATALAN] = "Funcions",
|
||||
[LANG_GERMAN] = "Funktionen",
|
||||
},
|
||||
{ // LBL_STACK_FULL
|
||||
[LANG_ENGLISH] = "Locomotive stack\nfull!",
|
||||
[LANG_SPANISH] = "Almacen de\nlocomotoras\nlleno!",
|
||||
[LANG_CATALAN] = "Magatzem de\nlocomotores\nple!",
|
||||
[LANG_GERMAN] = "Lokomotivstapel\nvoll!",
|
||||
},
|
||||
{ // LBL_STOP_0
|
||||
[LANG_ENGLISH] = "Speed 0",
|
||||
[LANG_SPANISH] = "Velocidad 0",
|
||||
[LANG_CATALAN] = "Velocitat 0",
|
||||
[LANG_GERMAN] = "Geschw. 0",
|
||||
},
|
||||
{ // LBL_STOP_E
|
||||
[LANG_ENGLISH] = "Emerg. Stop",
|
||||
[LANG_SPANISH] = "Stop Emerg.",
|
||||
[LANG_CATALAN] = "Stop Emerg.",
|
||||
[LANG_GERMAN] = "Not-Halt",
|
||||
},
|
||||
{ // LBL_SEL_IMAGE
|
||||
[LANG_ENGLISH] = "Image",
|
||||
[LANG_SPANISH] = "Imagen",
|
||||
[LANG_CATALAN] = "Imatge",
|
||||
[LANG_GERMAN] = "Bild",
|
||||
},
|
||||
{ // LBL_MENU_DRIVE
|
||||
[LANG_ENGLISH] = "Drive",
|
||||
[LANG_SPANISH] = "Conducir",
|
||||
[LANG_CATALAN] = "Conduir",
|
||||
[LANG_GERMAN] = "Fahren",
|
||||
},
|
||||
{ // LBL_MENU_ACC
|
||||
[LANG_ENGLISH] = "Accesory",
|
||||
[LANG_SPANISH] = "Accesorios",
|
||||
[LANG_CATALAN] = "Accesoris",
|
||||
[LANG_GERMAN] = "Zubehorartikel",
|
||||
},
|
||||
{ // LBL_MENU_CV
|
||||
[LANG_ENGLISH] = "CV Programming",
|
||||
[LANG_SPANISH] = "Programar CV",
|
||||
[LANG_CATALAN] = "Programar CV",
|
||||
[LANG_GERMAN] = "CV-Programmierung",
|
||||
},
|
||||
{ // LBL_MENU_CFG
|
||||
[LANG_ENGLISH] = "Configure",
|
||||
[LANG_SPANISH] = "Configurar",
|
||||
[LANG_CATALAN] = "Configurar",
|
||||
[LANG_GERMAN] = "Einstellungen",
|
||||
},
|
||||
{ // LBL_MENU_UTILS
|
||||
[LANG_ENGLISH] = "Utilities",
|
||||
[LANG_SPANISH] = "Utilidades",
|
||||
[LANG_CATALAN] = "Utilitats",
|
||||
[LANG_GERMAN] = "Dienstprogramme",
|
||||
},
|
||||
{ // LBL_CFG_LANG
|
||||
[LANG_ENGLISH] = "Language",
|
||||
[LANG_SPANISH] = "Idioma",
|
||||
[LANG_CATALAN] = "Idioma",
|
||||
[LANG_GERMAN] = "Sprache",
|
||||
},
|
||||
{ // LBL_CFG_SCR
|
||||
[LANG_ENGLISH] = "Screen",
|
||||
[LANG_SPANISH] = "Pantalla",
|
||||
[LANG_CATALAN] = "Pantalla",
|
||||
[LANG_GERMAN] = "Bildschirm",
|
||||
},
|
||||
{ // LBL_CFG_SPD
|
||||
[LANG_ENGLISH] = "Speed",
|
||||
[LANG_SPANISH] = "Velocidad",
|
||||
[LANG_CATALAN] = "Velocitat",
|
||||
[LANG_GERMAN] = "Geschwindigkeit",
|
||||
},
|
||||
{ // LBL_CFG_WIFI
|
||||
[LANG_ENGLISH] = "WiFi",
|
||||
},
|
||||
{ // LBL_CFG_FCLK
|
||||
[LANG_ENGLISH] = "Fast Clock",
|
||||
[LANG_SPANISH] = "Reloj",
|
||||
[LANG_CATALAN] = "Rellotge",
|
||||
[LANG_GERMAN] = "Uhr",
|
||||
},
|
||||
{ // LBL_CFG_LOCK
|
||||
[LANG_ENGLISH] = "Lock",
|
||||
[LANG_SPANISH] = "Bloquear",
|
||||
[LANG_CATALAN] = "Bloquejar",
|
||||
[LANG_GERMAN] = "Sperre",
|
||||
},
|
||||
{ // LBL_CFG_ABOUT
|
||||
[LANG_ENGLISH] = "About...",
|
||||
[LANG_SPANISH] = "Acerca...",
|
||||
[LANG_CATALAN] = "Sobre...",
|
||||
[LANG_GERMAN] = "Info...",
|
||||
},
|
||||
{ // LBL_SCR_ROTATE
|
||||
[LANG_ENGLISH] = "Rotate",
|
||||
[LANG_SPANISH] = "Girar",
|
||||
[LANG_CATALAN] = "Girar",
|
||||
[LANG_GERMAN] = "Drehen",
|
||||
},
|
||||
{ // LBL_PACO_WEB
|
||||
[LANG_ENGLISH] = "https://usuaris.tinet.cat/fmco",
|
||||
},
|
||||
{ // LBL_LOCK_LOK
|
||||
[LANG_ENGLISH] = "Locomotives",
|
||||
[LANG_SPANISH] = "Locomotoras",
|
||||
[LANG_CATALAN] = "Locomotores",
|
||||
[LANG_GERMAN] = "Lokomotiven",
|
||||
},
|
||||
{ // LBL_LOCK_ACC
|
||||
[LANG_ENGLISH] = "Accesory",
|
||||
[LANG_SPANISH] = "Accesorios",
|
||||
[LANG_CATALAN] = "Accesoris",
|
||||
[LANG_GERMAN] = "Zubehorartikel",
|
||||
},
|
||||
{ // LBL_LOCK_PRG
|
||||
[LANG_ENGLISH] = "Programming",
|
||||
[LANG_SPANISH] = "Programar",
|
||||
[LANG_CATALAN] = "Programar",
|
||||
[LANG_GERMAN] = "Programmierung",
|
||||
},
|
||||
/*
|
||||
{ // LBL_OPT_ROCO
|
||||
[LANG_ENGLISH] = "Turntable offset",
|
||||
[LANG_SPANISH] = "Offset Plataforma",
|
||||
[LANG_CATALAN] = "Offset Plataforma",
|
||||
[LANG_GERMAN] = "Drehscheibe Versatz",
|
||||
},
|
||||
*/
|
||||
{ // LBL_OPT_ADR
|
||||
[LANG_ENGLISH] = "Short Addr. (1 to 99)",
|
||||
[LANG_SPANISH] = "Dir. corta (1 a 99)",
|
||||
[LANG_CATALAN] = "Dir. curta (1 a 99)",
|
||||
[LANG_GERMAN] = "Kurze Adr. (1 bis 99)",
|
||||
},
|
||||
{ // LBL_OPT_IB2
|
||||
[LANG_ENGLISH] = "IBII / DR5000",
|
||||
},
|
||||
{ // LBL_OPT_UHLI
|
||||
[LANG_ENGLISH] = "Uhlenbrock",
|
||||
},
|
||||
{ // LBL_OPT_DIG
|
||||
[LANG_ENGLISH] = "Digitrax",
|
||||
},
|
||||
{ // LBL_ESTOP
|
||||
[LANG_ENGLISH] = "Emergency Stop",
|
||||
[LANG_SPANISH] = "Stop Emergencia",
|
||||
[LANG_CATALAN] = "Stop Emergencia",
|
||||
[LANG_GERMAN] = "Nothalt",
|
||||
},
|
||||
{ // LBL_SCALE
|
||||
[LANG_ENGLISH] = "Scale",
|
||||
[LANG_SPANISH] = "Escala",
|
||||
[LANG_CATALAN] = "Escala",
|
||||
[LANG_GERMAN] = "Skala",
|
||||
},
|
||||
{ // LBL_MM
|
||||
[LANG_ENGLISH] = "mm",
|
||||
},
|
||||
{ // LBL_SCALE_H0
|
||||
[LANG_ENGLISH] = "H0",
|
||||
},
|
||||
{ // LBL_SCALE_N
|
||||
[LANG_ENGLISH] = "N",
|
||||
},
|
||||
{ // LBL_SCALE_TT
|
||||
[LANG_ENGLISH] = "TT",
|
||||
},
|
||||
{ // LBL_SCALE_Z
|
||||
[LANG_ENGLISH] = "Z",
|
||||
},
|
||||
{ // LBL_SCALE_0
|
||||
[LANG_ENGLISH] = "0",
|
||||
},
|
||||
{ // LBL_MEASURE
|
||||
[LANG_ENGLISH] = "Measuring",
|
||||
[LANG_SPANISH] = "Midiendo",
|
||||
[LANG_CATALAN] = "Mesurant",
|
||||
[LANG_GERMAN] = "Messung",
|
||||
},
|
||||
{ // LBL_CV_ADDR
|
||||
[LANG_ENGLISH] = "Loco Address",
|
||||
[LANG_SPANISH] = "Direcc. Loco",
|
||||
[LANG_CATALAN] = "Direcc. Loco",
|
||||
[LANG_GERMAN] = "Lokadresse",
|
||||
},
|
||||
{ // LBL_CV_SPD_L
|
||||
[LANG_ENGLISH] = "Speed min.",
|
||||
[LANG_SPANISH] = "Velocidad min.",
|
||||
[LANG_CATALAN] = "Velocitat min.",
|
||||
[LANG_GERMAN] = "Minimale Geschw.",
|
||||
},
|
||||
{ // LBL_CV_SPD_M
|
||||
[LANG_ENGLISH] = "Speed mid.",
|
||||
[LANG_SPANISH] = "Velocidad media",
|
||||
[LANG_CATALAN] = "Velocitat mitja",
|
||||
[LANG_GERMAN] = "Mittlere Geschw.",
|
||||
},
|
||||
{ // LBL_CV_SPD_H
|
||||
[LANG_ENGLISH] = "Speed max.",
|
||||
[LANG_SPANISH] = "Velocidad max.",
|
||||
[LANG_CATALAN] = "Velocitat max.",
|
||||
[LANG_GERMAN] = "Maximale Geschw.",
|
||||
},
|
||||
{ // LBL_CV_ACC
|
||||
[LANG_ENGLISH] = "Acceleration",
|
||||
[LANG_SPANISH] = "Aceleracion",
|
||||
[LANG_CATALAN] = "Acceleracio",
|
||||
[LANG_GERMAN] = "Beschleunig",
|
||||
},
|
||||
{ // LBL_CV_DEC
|
||||
[LANG_ENGLISH] = "Braking",
|
||||
[LANG_SPANISH] = "Frenado",
|
||||
[LANG_CATALAN] = "Frenada",
|
||||
[LANG_GERMAN] = "Bremsen",
|
||||
},
|
||||
{ // LBL_CV_CFG
|
||||
[LANG_ENGLISH] = "Configuration",
|
||||
[LANG_SPANISH] = "Configuracion",
|
||||
[LANG_CATALAN] = "Configuracio",
|
||||
[LANG_GERMAN] = "Konfiguration",
|
||||
},
|
||||
{ // LBL_CV_MAN
|
||||
[LANG_ENGLISH] = "Manufacturer",
|
||||
[LANG_SPANISH] = "Fabricante",
|
||||
[LANG_CATALAN] = "Fabricant",
|
||||
[LANG_GERMAN] = "Hersteller",
|
||||
},
|
||||
{ // LBL_CV
|
||||
[LANG_ENGLISH] = "CV",
|
||||
},
|
||||
{ // LBL_LNCV
|
||||
[LANG_ENGLISH] = "LNCV",
|
||||
},
|
||||
{ // LBL_POM
|
||||
[LANG_ENGLISH] = "PoM",
|
||||
},
|
||||
{ // LBL_BITS
|
||||
[LANG_ENGLISH] = "Bits",
|
||||
},
|
||||
{ // LBL_CV_ERROR
|
||||
[LANG_ENGLISH] = "CV ERROR",
|
||||
[LANG_SPANISH] = "ERROR CV",
|
||||
[LANG_CATALAN] = "ERROR CV",
|
||||
[LANG_GERMAN] = "CV-FEHLER",
|
||||
},
|
||||
{ // LBL_UTIL_SPEED
|
||||
[LANG_ENGLISH] = "Measure speed",
|
||||
[LANG_SPANISH] = "Medir velocidad",
|
||||
[LANG_CATALAN] = "Mesurar velocitat",
|
||||
[LANG_GERMAN] = "Geschw. messen",
|
||||
},
|
||||
{ // LBL_UTIL_STEAM
|
||||
[LANG_ENGLISH] = "Steam locomotive",
|
||||
[LANG_SPANISH] = "Locomotora de vapor",
|
||||
[LANG_CATALAN] = "Locomotora de vapor",
|
||||
[LANG_GERMAN] = "Dampflokomotive",
|
||||
},
|
||||
{ // LBL_UTIL_SCAN
|
||||
[LANG_ENGLISH] = "WiFi Analyzer",
|
||||
[LANG_SPANISH] = "Analizador de WiFi",
|
||||
[LANG_CATALAN] = "Analitzador de WiFi",
|
||||
[LANG_GERMAN] = "WLAN-Analysator",
|
||||
},
|
||||
{ // LBL_UTIL_STA
|
||||
[LANG_ENGLISH] = "Station Run",
|
||||
[LANG_SPANISH] = "Carrera de estaciones",
|
||||
[LANG_CATALAN] = "Carrera d'estacions",
|
||||
[LANG_GERMAN] = "Bahnhofsrennen",
|
||||
},
|
||||
{ // LBL_ASK_SURE
|
||||
[LANG_ENGLISH] = "Are you sure?",
|
||||
[LANG_SPANISH] = "Estas seguro?",
|
||||
[LANG_CATALAN] = "Segur?",
|
||||
[LANG_GERMAN] = "Bist du sicher?",
|
||||
},
|
||||
{ // LBL_OPT_DISCOVER
|
||||
[LANG_ENGLISH] = "Discover",
|
||||
[LANG_SPANISH] = "Descubrir",
|
||||
[LANG_CATALAN] = "Descobrir",
|
||||
[LANG_GERMAN] = "Entdecken",
|
||||
},
|
||||
{ // LBL_LNCV_ART
|
||||
[LANG_ENGLISH] = "Article",
|
||||
[LANG_SPANISH] = "Articulo",
|
||||
[LANG_CATALAN] = NULL,
|
||||
[LANG_GERMAN] = "Artikel",
|
||||
},
|
||||
{ // LBL_LNCV_MOD
|
||||
[LANG_ENGLISH] = "Module",
|
||||
[LANG_SPANISH] = "Modulo",
|
||||
[LANG_CATALAN] = "Modul",
|
||||
[LANG_GERMAN] = "Modul",
|
||||
},
|
||||
{ // LBL_LNCV_NUM
|
||||
[LANG_ENGLISH] = "LNCV",
|
||||
},
|
||||
{ // LBL_ACC_TYPE
|
||||
[LANG_ENGLISH] = "Accessory type",
|
||||
[LANG_SPANISH] = "Tipo accesorio",
|
||||
[LANG_CATALAN] = "Tipus accessori",
|
||||
[LANG_GERMAN] = "Zubehortyp",
|
||||
},
|
||||
{ // LBL_ACC_NAME
|
||||
[LANG_ENGLISH] = "Name",
|
||||
[LANG_SPANISH] = "Nombre",
|
||||
[LANG_CATALAN] = "Nom",
|
||||
[LANG_GERMAN] = NULL,
|
||||
},
|
||||
{ // LBL_ACC_ADDR
|
||||
[LANG_ENGLISH] = "Addr.",
|
||||
[LANG_SPANISH] = "Dir.",
|
||||
[LANG_CATALAN] = "Dir.",
|
||||
[LANG_GERMAN] = "Adr.",
|
||||
},
|
||||
{ // LBL_STA_RUN
|
||||
[LANG_ENGLISH] = "Station Run",
|
||||
[LANG_SPANISH] = "Carrera de estaciones",
|
||||
[LANG_CATALAN] = "Carrera d'estacions",
|
||||
[LANG_GERMAN] = "Bahnhofsrennen",
|
||||
},
|
||||
{ // LBL_STA_LEVEL
|
||||
[LANG_ENGLISH] = "Level:",
|
||||
[LANG_SPANISH] = "Nivel:",
|
||||
[LANG_CATALAN] = "Nivell:",
|
||||
[LANG_GERMAN] = NULL,
|
||||
},
|
||||
{ // LBL_STA_START
|
||||
[LANG_ENGLISH] = "Start",
|
||||
[LANG_SPANISH] = "Iniciar",
|
||||
[LANG_CATALAN] = "Iniciar",
|
||||
[LANG_GERMAN] = "Starten",
|
||||
},
|
||||
{ // LBL_STA_INSTR
|
||||
[LANG_ENGLISH] = "Go to the station of your\ndestination color.\nPress it when you arrive",
|
||||
[LANG_SPANISH] = "Ve a la estacion del color\nde tu destino.\nPulsala cuando llegues",
|
||||
[LANG_CATALAN] = "Ves a l'estacio del color\nde la teva destinacio.\nPrem-la quan arribis",
|
||||
[LANG_GERMAN] = "Gehen Sie sich zum Bahnhof\nIhrer Zielfarbe. Klicken Sie\ndas Symbol, wenn Sie ankommen",
|
||||
},
|
||||
{ // LBL_STA_EXCEL
|
||||
[LANG_ENGLISH] = "Excellent!",
|
||||
[LANG_SPANISH] = "Excelente!",
|
||||
[LANG_CATALAN] = "Excel.lent!",
|
||||
[LANG_GERMAN] = "Exzellent!",
|
||||
},
|
||||
{ // LBL_STA_GREAT
|
||||
[LANG_ENGLISH] = "Great!",
|
||||
[LANG_SPANISH] = "Muy bien!",
|
||||
[LANG_CATALAN] = "Molt be!",
|
||||
[LANG_GERMAN] = "Sehr gut!",
|
||||
},
|
||||
{ // LBL_STA_TIMEOUT
|
||||
[LANG_ENGLISH] = "TIME'S UP\nThanks for playing",
|
||||
[LANG_SPANISH] = "FIN DEL TIEMPO\nGracias por jugar",
|
||||
[LANG_CATALAN] = "FINAL DEL TEMPS\nGracies per jugar",
|
||||
[LANG_GERMAN] = "DIE ZEIT IST UM\nDanke furs Spielen",
|
||||
},
|
||||
{ // LBL_STA_STATIONS
|
||||
[LANG_ENGLISH] = "Stations",
|
||||
[LANG_SPANISH] = "Estaciones",
|
||||
[LANG_CATALAN] = "Estacions",
|
||||
[LANG_GERMAN] = "Bahnhofe",
|
||||
},
|
||||
{ // LBL_STA_TURNOUTS
|
||||
[LANG_ENGLISH] = "Turnouts",
|
||||
[LANG_SPANISH] = "Desvios",
|
||||
[LANG_CATALAN] = "Agulles",
|
||||
[LANG_GERMAN] = "Weichen",
|
||||
},
|
||||
{ // LBL_STA_TIME
|
||||
[LANG_ENGLISH] = "Time",
|
||||
[LANG_SPANISH] = "Tiempo",
|
||||
[LANG_CATALAN] = "Temps",
|
||||
[LANG_GERMAN] = "Zeit",
|
||||
},
|
||||
{ // LBL_STA_DESC
|
||||
[LANG_ENGLISH] = "Address Orientat. Inverted",
|
||||
[LANG_SPANISH] = "Direcc. Orientac. Invertido",
|
||||
[LANG_CATALAN] = "Direcc. Orientacio Invertit",
|
||||
[LANG_GERMAN] = "Adresse Ausricht. Invertiert",
|
||||
},
|
||||
};
|
||||
885
PacoMouseCYD/src/PacoMouseCYD/window.ino
Normal file
@@ -0,0 +1,885 @@
|
||||
/* PacoMouseCYD throttle -- F. Cañada 2025-2026 -- https://usuaris.tinet.cat/fmco/
|
||||
*/
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// ***** WINDOW OBJECTS *****
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
void openWindow(uint16_t id) {
|
||||
uint16_t n;
|
||||
char buf[MAX_LABEL_LNG];
|
||||
switch (id) {
|
||||
case WIN_LOGO:
|
||||
createObject(OBJ_WIN, WIN_LOGO);
|
||||
createObject(OBJ_DRAWSTR, DSTR_INIT);
|
||||
createObject(OBJ_LABEL, LBL_PACO_TXT);
|
||||
posObjStack1 = createObject(OBJ_LABEL, LBL_INIT);
|
||||
createObject(OBJ_ICON, ICON_PACO);
|
||||
createObject(OBJ_BAR, BAR_INIT);
|
||||
drawWindow(WIN_LOGO);
|
||||
break;
|
||||
case WIN_CALIBRATE:
|
||||
createObject(OBJ_WIN, WIN_CALIBRATE);
|
||||
posObjStack2 = createObject(OBJ_LABEL, LBL_CAL);
|
||||
posObjStack1 = createObject(OBJ_LABEL, LBL_PRESS);
|
||||
newEvent(OBJ_WIN, WIN_CALIBRATE, EVNT_DRAW);
|
||||
break;
|
||||
case WIN_SSID:
|
||||
createObject(OBJ_WIN, WIN_SSID);
|
||||
createObject(OBJ_ICON, ICON_WIFI_SSID);
|
||||
createObject(OBJ_BUTTON, BUT_SSID_CLOSE);
|
||||
posObjStack1 = createObject(OBJ_LABEL, LBL_SCAN);
|
||||
drawWindow(WIN_SSID);
|
||||
scanWiFi();
|
||||
objStack[posObjStack1].objID = LBL_SSID_SCAN;
|
||||
createObject(OBJ_TXT, TXT_SSID1);
|
||||
createObject(OBJ_TXT, TXT_SSID2);
|
||||
createObject(OBJ_TXT, TXT_SSID3);
|
||||
createObject(OBJ_TXT, TXT_SSID4);
|
||||
createObject(OBJ_TXT, TXT_SSID5);
|
||||
createObject(OBJ_TXT, TXT_SSID6);
|
||||
scanWiFiFill();
|
||||
newEvent(OBJ_WIN, WIN_SSID, EVNT_DRAW);
|
||||
break;
|
||||
case WIN_WIFI:
|
||||
snprintf(ssidName, SSID_LNG, "%s", wifiSetting.ssid);
|
||||
snprintf(keybPwdHideBuf, 9, "********");
|
||||
snprintf(keybIP1Buf, 4, "%d", wifiSetting.CS_IP[0]);
|
||||
snprintf(keybIP2Buf, 4, "%d", wifiSetting.CS_IP[1]);
|
||||
snprintf(keybIP3Buf, 4, "%d", wifiSetting.CS_IP[2]);
|
||||
snprintf(keybIP4Buf, 4, "%d", wifiSetting.CS_IP[3]);
|
||||
setProtocolData();
|
||||
createObject(OBJ_WIN, WIN_WIFI);
|
||||
createObject(OBJ_ICON, ICON_WIFI_CFG);
|
||||
createObject(OBJ_LABEL, LBL_SSID);
|
||||
createObject(OBJ_TXT, TXT_SSID);
|
||||
createObject(OBJ_LABEL, LBL_PWD_HIDE);
|
||||
createObject(OBJ_TXT, TXT_PWD_HIDE);
|
||||
createObject(OBJ_LABEL, LBL_IP);
|
||||
createObject(OBJ_TXT, TXT_IP1);
|
||||
createObject(OBJ_TXT, TXT_IP2);
|
||||
createObject(OBJ_TXT, TXT_IP3);
|
||||
createObject(OBJ_TXT, TXT_IP4);
|
||||
createObject(OBJ_LABEL, LBL_PORT);
|
||||
createObject(OBJ_TXT, TXT_PORT);
|
||||
createObject(OBJ_KEYBOARD, KEYB_IP);
|
||||
createObject(OBJ_LABEL, LBL_PROTOCOL);
|
||||
createObject(OBJ_TXT, TXT_PROTOCOL);
|
||||
createObject(OBJ_BUTTON, BUT_WIFI_OK);
|
||||
newEvent(OBJ_WIN, WIN_WIFI, EVNT_DRAW);
|
||||
break;
|
||||
case WIN_WIFI_PWD:
|
||||
snprintf(keybPwdBuf, PWD_LNG, wifiSetting.password);
|
||||
createObject(OBJ_WIN, WIN_WIFI_PWD);
|
||||
createObject(OBJ_TXT, TXT_PWD);
|
||||
createObject(OBJ_KEYBOARD, KEYB_PWD);
|
||||
createObject(OBJ_BUTTON, BUT_PWD_OK);
|
||||
createObject(OBJ_BUTTON, BUT_PWD_CNCL);
|
||||
newEvent(OBJ_WIN, WIN_WIFI_PWD, EVNT_DRAW);
|
||||
break;
|
||||
case WIN_PROTOCOL:
|
||||
radioData[RAD_PROTOCOL].value = wifiSetting.protocol - CLIENT_Z21;
|
||||
if (wifiSetting.protocol == CLIENT_LNET)
|
||||
radioData[RAD_PROTOCOL_LN].value = (wifiSetting.serverType) ? 0 : 1;
|
||||
else
|
||||
radioData[RAD_PROTOCOL_LN].value = radioData[RAD_PROTOCOL_LN].num;
|
||||
createObject(OBJ_WIN, WIN_PROTOCOL);
|
||||
createObject(OBJ_RADIO, RAD_PROTOCOL);
|
||||
createObject(OBJ_RADIO, RAD_PROTOCOL_LN);
|
||||
createObject(OBJ_LABEL, LBL_SEL_PROT);
|
||||
createObject(OBJ_LABEL, LBL_SEL_Z21);
|
||||
createObject(OBJ_LABEL, LBL_SEL_XNET);
|
||||
createObject(OBJ_LABEL, LBL_SEL_ECOS);
|
||||
createObject(OBJ_LABEL, LBL_SEL_LNET);
|
||||
createObject(OBJ_LABEL, LBL_SEL_LBSERVER);
|
||||
createObject(OBJ_LABEL, LBL_SEL_BINARY);
|
||||
createObject(OBJ_BUTTON, BUT_PROT_OK);
|
||||
createObject(OBJ_BUTTON, BUT_OPTIONS);
|
||||
newEvent(OBJ_WIN, WIN_PROTOCOL, EVNT_DRAW);
|
||||
break;
|
||||
case WIN_THROTTLE:
|
||||
iconData[ICON_LOK_EDIT].bitmap = (wifiSetting.protocol == CLIENT_ECOS) ? info24 : wrench;
|
||||
createObject(OBJ_WIN, WIN_THROTTLE);
|
||||
createObject(OBJ_ICON, ICON_MENU);
|
||||
createObject(OBJ_ICON, ICON_POWER);
|
||||
createObject(OBJ_ICON, ICON_FNEXT);
|
||||
createObject(OBJ_ICON, ICON_LOK_EDIT);
|
||||
createObject(OBJ_FNC, FNC_ACC_PANEL);
|
||||
//createObject(OBJ_ICON, ICON_FWD);
|
||||
//createObject(OBJ_ICON, ICON_REV);
|
||||
createObject(OBJ_TXT, TXT_CLOCK);
|
||||
createObject(OBJ_TXT, TXT_LOCO_NAME);
|
||||
createObject(OBJ_TXT, TXT_LOCO_ADDR);
|
||||
createObject(OBJ_LPIC, LPIC_MAIN);
|
||||
createObject(OBJ_GAUGE, GAUGE_SPEED);
|
||||
createObject(OBJ_LABEL, LBL_KMH);
|
||||
createObject(OBJ_FNC, FNC_FX0);
|
||||
createObject(OBJ_FNC, FNC_FX1);
|
||||
createObject(OBJ_FNC, FNC_FX2);
|
||||
createObject(OBJ_FNC, FNC_FX3);
|
||||
createObject(OBJ_FNC, FNC_FX4);
|
||||
createObject(OBJ_FNC, FNC_FX5);
|
||||
createObject(OBJ_FNC, FNC_FX6);
|
||||
createObject(OBJ_FNC, FNC_FX7);
|
||||
createObject(OBJ_FNC, FNC_FX8);
|
||||
createObject(OBJ_FNC, FNC_FX9);
|
||||
newEvent(OBJ_WIN, WIN_THROTTLE, EVNT_DRAW);
|
||||
break;
|
||||
case WIN_CONFIG:
|
||||
buttonData[BUT_CFG_I_LANG].objID = DSTR_ENGLISH + currLanguage;
|
||||
lastLanguage = currLanguage;
|
||||
createObject(OBJ_WIN, WIN_CONFIG);
|
||||
createObject(OBJ_DRAWSTR, DSTR_CFG_MENU);
|
||||
createObject(OBJ_BUTTON, BUT_CFG_I_LANG);
|
||||
createObject(OBJ_BUTTON, BUT_CFG_T_LANG);
|
||||
createObject(OBJ_BUTTON, BUT_CFG_I_SCR);
|
||||
createObject(OBJ_BUTTON, BUT_CFG_T_SCR);
|
||||
createObject(OBJ_BUTTON, BUT_CFG_I_SPD);
|
||||
createObject(OBJ_BUTTON, BUT_CFG_T_SPD);
|
||||
createObject(OBJ_BUTTON, BUT_CFG_I_WIFI);
|
||||
createObject(OBJ_BUTTON, BUT_CFG_T_WIFI);
|
||||
createObject(OBJ_BUTTON, BUT_CFG_I_FCLK);
|
||||
createObject(OBJ_BUTTON, BUT_CFG_T_FCLK);
|
||||
createObject(OBJ_BUTTON, BUT_CFG_I_LOCK);
|
||||
createObject(OBJ_BUTTON, BUT_CFG_T_LOCK);
|
||||
createObject(OBJ_BUTTON, BUT_CFG_I_ABOUT);
|
||||
createObject(OBJ_BUTTON, BUT_CFG_T_ABOUT);
|
||||
createObject(OBJ_ICON, ICON_CFG_EXIT);
|
||||
newEvent(OBJ_WIN, WIN_CONFIG, EVNT_DRAW);
|
||||
break;
|
||||
case WIN_SCREEN:
|
||||
barData[BAR_BLIGHT].value = backlight;
|
||||
switchData[SW_ROTATE].state = (locationUSB == USB_UP);
|
||||
createObject(OBJ_WIN, WIN_SCREEN);
|
||||
createObject(OBJ_ICON, ICON_BLIGHT);
|
||||
createObject(OBJ_BAR, BAR_BLIGHT);
|
||||
createObject(OBJ_SWITCH, SW_ROTATE);
|
||||
createObject(OBJ_LABEL, LBL_SCR_ROTATE);
|
||||
createObject(OBJ_BUTTON, BUT_CFG_TOUCH);
|
||||
createObject(OBJ_BUTTON, BUT_SCR_OK);
|
||||
createObject(OBJ_BUTTON, BUT_SCR_CNCL);
|
||||
newEvent(OBJ_WIN, WIN_SCREEN, EVNT_DRAW);
|
||||
break;
|
||||
case WIN_SPEED:
|
||||
switchData[SW_SHUNTING].state = shuntingMode;
|
||||
radioData[RAD_STOP_MODE].value = (stopMode > 0) ? 1 : 0;
|
||||
createObject(OBJ_WIN, WIN_SPEED);
|
||||
createObject(OBJ_LABEL, LBL_SHUNTING);
|
||||
createObject(OBJ_SWITCH, SW_SHUNTING);
|
||||
createObject(OBJ_RADIO, RAD_STOP_MODE);
|
||||
createObject(OBJ_ICON, ICON_STOP);
|
||||
createObject(OBJ_LABEL, LBL_STOP_0);
|
||||
createObject(OBJ_LABEL, LBL_STOP_E);
|
||||
createObject(OBJ_BUTTON, BUT_SPD_OK);
|
||||
newEvent(OBJ_WIN, WIN_SPEED, EVNT_DRAW);
|
||||
break;
|
||||
case WIN_SET_CLOCK:
|
||||
snprintf(keybHourBuf, 3, "%d", clockHour);
|
||||
snprintf(keybMinBuf, 3, "%d", clockMin);
|
||||
snprintf(keybRateBuf, 4, "%d", clockRate);
|
||||
showClockData(TXT_HOUR);
|
||||
createObject(OBJ_WIN, WIN_SET_CLOCK);
|
||||
createObject(OBJ_DRAWSTR, DSTR_CLOCK);
|
||||
createObject(OBJ_CHAR, CHAR_CLK_COLON);
|
||||
createObject(OBJ_ICON, ICON_SET_CLOCK);
|
||||
createObject(OBJ_TXT, TXT_HOUR);
|
||||
createObject(OBJ_TXT, TXT_MIN);
|
||||
createObject(OBJ_TXT, TXT_RATE);
|
||||
createObject(OBJ_LABEL, LBL_RATE);
|
||||
createObject(OBJ_KEYBOARD, KEYB_CLOCK);
|
||||
createObject(OBJ_BUTTON, BUT_CLOCK_OK);
|
||||
createObject(OBJ_BUTTON, BUT_CLOCK_CNCL);
|
||||
newEvent(OBJ_WIN, WIN_SET_CLOCK, EVNT_DRAW);
|
||||
break;
|
||||
case WIN_LOCK:
|
||||
switchData[SW_LOCK_LOK].state = (bitRead(lockOptions, LOCK_SEL_LOCO)) ? true : false;
|
||||
switchData[SW_LOCK_ACC].state = (bitRead(lockOptions, LOCK_TURNOUT)) ? true : false;
|
||||
switchData[SW_LOCK_PRG].state = (bitRead(lockOptions, LOCK_PROG)) ? true : false;
|
||||
createObject(OBJ_WIN, WIN_LOCK);
|
||||
createObject(OBJ_SWITCH, SW_LOCK_LOK);
|
||||
createObject(OBJ_SWITCH, SW_LOCK_ACC);
|
||||
createObject(OBJ_SWITCH, SW_LOCK_PRG);
|
||||
createObject(OBJ_LABEL, LBL_LOCK_LOK);
|
||||
createObject(OBJ_LABEL, LBL_LOCK_ACC);
|
||||
createObject(OBJ_LABEL, LBL_LOCK_PRG);
|
||||
createObject(OBJ_BUTTON, BUT_LOCK);
|
||||
newEvent(OBJ_WIN, WIN_LOCK, EVNT_DRAW);
|
||||
break;
|
||||
case WIN_ABOUT:
|
||||
snprintf (aboutPacoMouseCYD, PWD_LNG + 1, "v%s.%s%s", VER_H, VER_L, VER_R);
|
||||
snprintf (aboutIP, PWD_LNG + 1, "IP: %u.%u.%u.%u", WiFi.localIP().operator[](0), WiFi.localIP().operator[](1), WiFi.localIP().operator[](2), WiFi.localIP().operator[](3));
|
||||
snprintf (aboutMAC, PWD_LNG + 1, "MAC: %s", WiFi.macAddress().c_str());
|
||||
createObject(OBJ_WIN, WIN_ABOUT);
|
||||
createObject(OBJ_DRAWSTR, DSTR_ABOUT);
|
||||
createObject(OBJ_LABEL, LBL_PACO_TXT);
|
||||
createObject(OBJ_ICON, ICON_ABOUT_PACO);
|
||||
createObject(OBJ_TXT, TXT_ABOUT);
|
||||
createObject(OBJ_TXT, TXT_ABOUT_IP);
|
||||
createObject(OBJ_TXT, TXT_ABOUT_MAC);
|
||||
createObject(OBJ_LABEL, LBL_PACO_WEB);
|
||||
newEvent(OBJ_WIN, WIN_ABOUT, EVNT_DRAW);
|
||||
break;
|
||||
case WIN_LOK_EDIT:
|
||||
snprintf (locoEditName, NAME_LNG + 1, "%s", locoData[myLocoData].myName );
|
||||
sprintf (locoEditAddr, "%d", locoData[myLocoData].myAddr.address);
|
||||
sprintf (locoEditID, "%d", locoData[myLocoData].myLocoID);
|
||||
sprintf (locoEditVmax, "%d", locoData[myLocoData].myVmax);
|
||||
lpicData[LPIC_LOK_EDIT].id = locoData[myLocoData].myLocoID;
|
||||
for (n = 0; n < 29; n++)
|
||||
fncData[FNC_F0 + n].idIcon = locoData[myLocoData].myFuncIcon[n];
|
||||
createObject(OBJ_WIN, WIN_LOK_EDIT);
|
||||
createObject(OBJ_LABEL, LBL_ADDR);
|
||||
createObject(OBJ_LABEL, LBL_IMAGE);
|
||||
createObject(OBJ_LABEL, LBL_NAME);
|
||||
createObject(OBJ_LABEL, LBL_VMAX);
|
||||
createObject(OBJ_LPIC, LPIC_LOK_EDIT);
|
||||
createObject(OBJ_TXT, TXT_EDIT_ADDR);
|
||||
createObject(OBJ_TXT, TXT_EDIT_NAME);
|
||||
createObject(OBJ_TXT, TXT_EDIT_IMAGE);
|
||||
createObject(OBJ_TXT, TXT_EDIT_VMAX);
|
||||
createObject(OBJ_BUTTON, BUT_EDIT_FUNC);
|
||||
createObject(OBJ_BUTTON, BUT_EDIT_CNCL);
|
||||
if (wifiSetting.protocol != CLIENT_ECOS) {
|
||||
createObject(OBJ_BUTTON, BUT_EDIT_OK);
|
||||
if ((locoData[myLocoData].mySpeed < 2) && (countLocoInStack() > 1)) // stopped and remaining locos in stack
|
||||
createObject(OBJ_BUTTON, BUT_EDIT_DEL);
|
||||
}
|
||||
newEvent(OBJ_WIN, WIN_LOK_EDIT, EVNT_DRAW);
|
||||
break;
|
||||
case WIN_EDIT_NAME:
|
||||
snprintf(keybNameBuf, NAME_LNG + 1, locoData[myLocoData].myName);
|
||||
txtData[TXT_NAME].maxLength = NAME_LNG;
|
||||
createObject(OBJ_WIN, WIN_EDIT_NAME);
|
||||
createObject(OBJ_TXT, TXT_NAME);
|
||||
createObject(OBJ_KEYBOARD, KEYB_NAME);
|
||||
createObject(OBJ_BUTTON, BUT_NAME_OK);
|
||||
createObject(OBJ_BUTTON, BUT_NAME_CNCL);
|
||||
newEvent(OBJ_WIN, WIN_EDIT_NAME, EVNT_DRAW);
|
||||
break;
|
||||
case WIN_FUNC:
|
||||
createObject(OBJ_WIN, WIN_FUNC);
|
||||
for (n = 0; n < 29; n++)
|
||||
createObject(OBJ_FNC, FNC_F0 + n);
|
||||
createObject(OBJ_LABEL, LBL_ADDR);
|
||||
createObject(OBJ_TXT, TXT_EDIT_ADDR);
|
||||
createObject(OBJ_LABEL, LBL_EDIT_FUNC);
|
||||
if (wifiSetting.protocol != CLIENT_ECOS)
|
||||
createObject(OBJ_BUTTON, BUT_FNC_OK);
|
||||
createObject(OBJ_BUTTON, BUT_FNC_CNCL);
|
||||
newEvent(OBJ_WIN, WIN_FUNC, EVNT_DRAW);
|
||||
break;
|
||||
case WIN_CHG_FUNC:
|
||||
createObject(OBJ_WIN, WIN_CHG_FUNC);
|
||||
createObject(OBJ_FNC, FNC_CHG);
|
||||
createObject(OBJ_TXT, TXT_EDIT_FNC);
|
||||
newEvent(OBJ_WIN, WIN_CHG_FUNC, EVNT_DRAW);
|
||||
break;
|
||||
case WIN_VMAX:
|
||||
createObject(OBJ_WIN, WIN_VMAX);
|
||||
createObject(OBJ_TXT, TXT_KEYB_VMAX);
|
||||
createObject(OBJ_KEYBOARD, KEYB_VMAX);
|
||||
newEvent(OBJ_WIN, WIN_VMAX, EVNT_DRAW);
|
||||
break;
|
||||
case WIN_SEL_LOCO:
|
||||
createObject(OBJ_WIN, WIN_SEL_LOCO);
|
||||
createObject(OBJ_DRAWSTR, DSTR_SELLOK);
|
||||
posObjStack1 = createObject(OBJ_ICON, ICON_LAST_UP);
|
||||
prepareLocoList();
|
||||
createObject(OBJ_ICON, ICON_SEL_LOK);
|
||||
if (wifiSetting.protocol != CLIENT_ECOS)
|
||||
createObject(OBJ_FNC, FNC_SEL_KEYPAD);
|
||||
createObject(OBJ_TXT, TXT_SEL_ADDR1);
|
||||
createObject(OBJ_TXT, TXT_SEL_NAME1);
|
||||
createObject(OBJ_TXT, TXT_SEL_ADDR2);
|
||||
createObject(OBJ_TXT, TXT_SEL_NAME2);
|
||||
createObject(OBJ_TXT, TXT_SEL_ADDR3);
|
||||
createObject(OBJ_TXT, TXT_SEL_NAME3);
|
||||
createObject(OBJ_TXT, TXT_SEL_ADDR4);
|
||||
createObject(OBJ_TXT, TXT_SEL_NAME4);
|
||||
createObject(OBJ_TXT, TXT_SEL_ADDR5);
|
||||
createObject(OBJ_TXT, TXT_SEL_NAME5);
|
||||
createObject(OBJ_TXT, TXT_SEL_ADDR6);
|
||||
createObject(OBJ_TXT, TXT_SEL_NAME6);
|
||||
newEvent(OBJ_WIN, WIN_SEL_LOCO, EVNT_DRAW);
|
||||
break;
|
||||
case WIN_ENTER_ADDR:
|
||||
locoKeybAddr[0] = '\0';
|
||||
createObject(OBJ_WIN, WIN_ENTER_ADDR);
|
||||
createObject(OBJ_TXT, TXT_KEYB_ADDR);
|
||||
createObject(OBJ_KEYBOARD, KEYB_ADDR);
|
||||
newEvent(OBJ_WIN, WIN_ENTER_ADDR, EVNT_DRAW);
|
||||
break;
|
||||
case WIN_SEL_IMAGE:
|
||||
createObject(OBJ_WIN, WIN_SEL_IMAGE);
|
||||
createObject(OBJ_LABEL, LBL_SEL_IMAGE);
|
||||
createObject(OBJ_BUTTON, BUT_IMAGE_CNCL);
|
||||
drawWindow(WIN_SEL_IMAGE);
|
||||
populateImageList();
|
||||
createObject(OBJ_LPIC, LPIC_SEL_IMG1);
|
||||
createObject(OBJ_LPIC, LPIC_SEL_IMG2);
|
||||
createObject(OBJ_LPIC, LPIC_SEL_IMG3);
|
||||
createObject(OBJ_LPIC, LPIC_SEL_IMG4);
|
||||
createObject(OBJ_LPIC, LPIC_SEL_IMG5);
|
||||
createObject(OBJ_LPIC, LPIC_SEL_IMG6);
|
||||
createObject(OBJ_ICON, ICON_PREV_IMAGE);
|
||||
createObject(OBJ_ICON, ICON_NEXT_IMAGE);
|
||||
newEvent(OBJ_WIN, WIN_SEL_IMAGE, EVNT_DRAW);
|
||||
break;
|
||||
case WIN_MENU:
|
||||
createObject(OBJ_WIN, WIN_MENU);
|
||||
createObject(OBJ_BUTTON, BUT_MENU_I_DRIVE);
|
||||
createObject(OBJ_BUTTON, BUT_MENU_T_DRIVE);
|
||||
createObject(OBJ_BUTTON, BUT_MENU_I_ACC);
|
||||
createObject(OBJ_BUTTON, BUT_MENU_T_ACC);
|
||||
createObject(OBJ_BUTTON, BUT_MENU_I_CV);
|
||||
createObject(OBJ_BUTTON, BUT_MENU_T_CV);
|
||||
createObject(OBJ_BUTTON, BUT_MENU_I_CFG);
|
||||
createObject(OBJ_BUTTON, BUT_MENU_T_CFG);
|
||||
createObject(OBJ_BUTTON, BUT_MENU_I_UTILS);
|
||||
createObject(OBJ_BUTTON, BUT_MENU_T_UTILS);
|
||||
createObject(OBJ_DRAWSTR, DSTR_MENU);
|
||||
newEvent(OBJ_WIN, WIN_MENU, EVNT_DRAW);
|
||||
break;
|
||||
case WIN_OPTIONS:
|
||||
setOptionsData();
|
||||
createObject(OBJ_WIN, WIN_OPTIONS);
|
||||
switch (wifiSetting.protocol) {
|
||||
case CLIENT_Z21:
|
||||
//createObject(OBJ_SWITCH, SW_OPT_TT_OFFSET);
|
||||
//createObject(OBJ_LABEL, LBL_OPT_TT_OFFSET);
|
||||
createObject(OBJ_SWITCH, SW_OPT_ADR);
|
||||
createObject(OBJ_LABEL, LBL_OPT_ADR);
|
||||
break;
|
||||
case CLIENT_XNET:
|
||||
//createObject(OBJ_SWITCH, SW_OPT_TT_OFFSET);
|
||||
//createObject(OBJ_LABEL, LBL_OPT_TT_OFFSET);
|
||||
break;
|
||||
case CLIENT_LNET:
|
||||
switchData[SW_OPT_DISCOVER].state = (autoIdentifyCS > 0) ? true : false;
|
||||
createObject(OBJ_SWITCH, SW_OPT_DISCOVER);
|
||||
createObject(OBJ_LABEL, LBL_OPT_DISCOVER);
|
||||
createObject(OBJ_RADIO, RAD_CSTATION);
|
||||
createObject(OBJ_LABEL, LBL_OPT_IB2);
|
||||
createObject(OBJ_LABEL, LBL_OPT_UHLI);
|
||||
createObject(OBJ_LABEL, LBL_OPT_DIG);
|
||||
break;
|
||||
case CLIENT_ECOS:
|
||||
break;
|
||||
}
|
||||
createObject(OBJ_BUTTON, BUT_OPT_OK);
|
||||
newEvent(OBJ_WIN, WIN_OPTIONS, EVNT_DRAW);
|
||||
break;
|
||||
case WIN_SPEEDO:
|
||||
speedoSpeed = 0;
|
||||
speedoPhase = SPD_WAIT;
|
||||
setSpeedoPhase(SPD_WAIT);
|
||||
setTextSpeedo();
|
||||
snprintf(spdLengthBuf, NAME_LNG + 1, "%d", speedoLength);
|
||||
snprintf(spdSpeedBuf, NAME_LNG + 1, "%d km/h", speedoSpeed);
|
||||
iconData[ICON_SPEEDO_LOK].x = 40 + (speedoPhase * 32);
|
||||
drawStrData[DSTR_SPEEDO_BLANK].x = 40 + (speedoPhase * 32);
|
||||
lpicData[LPIC_SPEEDO].id = locoData[myLocoData].myLocoID;
|
||||
createObject(OBJ_WIN, WIN_SPEEDO);
|
||||
createObject(OBJ_LPIC, LPIC_SPEEDO);
|
||||
createObject(OBJ_LABEL, LBL_SCALE);
|
||||
createObject(OBJ_LABEL, LBL_MM);
|
||||
createObject(OBJ_GAUGE, GAUGE_SPEEDO);
|
||||
createObject(OBJ_FNC, FNC_SPEEDO_DIR);
|
||||
createObject(OBJ_DRAWSTR, DSTR_SPEEDO_BLANK);
|
||||
createObject(OBJ_DRAWSTR, DSTR_SPEEDO_TRK);
|
||||
createObject(OBJ_ICON, ICON_SPEEDO_LOK);
|
||||
createObject(OBJ_ICON, ICON_SPEEDO_RADAR);
|
||||
createObject(OBJ_BUTTON, BUT_SPEEDO_CNCL);
|
||||
createObject(OBJ_BUTTON, BUT_SPEEDO_CV);
|
||||
createObject(OBJ_TXT, TXT_SPEEDO_SCALE);
|
||||
createObject(OBJ_TXT, TXT_SPEEDO_LNG);
|
||||
createObject(OBJ_TXT, TXT_SPEEDO_SPD);
|
||||
newEvent(OBJ_WIN, WIN_SPEEDO, EVNT_DRAW);
|
||||
break;
|
||||
case WIN_SPEEDO_LNG:
|
||||
snprintf(speedoKeybLng, PORT_LNG + 1, "%d", speedoLength);
|
||||
createObject(OBJ_WIN, WIN_SPEEDO_LNG);
|
||||
createObject(OBJ_TXT, TXT_EDIT_LNG);
|
||||
createObject(OBJ_KEYBOARD, KEYB_LNG);
|
||||
newEvent(OBJ_WIN, WIN_SPEEDO_LNG, EVNT_DRAW);
|
||||
break;
|
||||
case WIN_SPEEDO_SCALE:
|
||||
setTextSpeedo();
|
||||
createObject(OBJ_WIN, WIN_SPEEDO_SCALE);
|
||||
createObject(OBJ_TXT, TXT_EDIT_SCALE);
|
||||
createObject(OBJ_TXT, TXT_NUM_SCALE);
|
||||
createObject(OBJ_KEYBOARD, KEYB_SCALE);
|
||||
createObject(OBJ_BUTTON, BUT_SPEEDO_H0);
|
||||
createObject(OBJ_BUTTON, BUT_SPEEDO_N);
|
||||
createObject(OBJ_BUTTON, BUT_SPEEDO_TT);
|
||||
createObject(OBJ_BUTTON, BUT_SPEEDO_Z);
|
||||
createObject(OBJ_BUTTON, BUT_SPEEDO_0);
|
||||
newEvent(OBJ_WIN, WIN_SPEEDO_SCALE, EVNT_DRAW);
|
||||
break;
|
||||
case WIN_READ_CV:
|
||||
createObject(OBJ_WIN, WIN_READ_CV);
|
||||
createObject(OBJ_DRAWSTR, DSTR_CFG_MENU);
|
||||
createObject(OBJ_BUTTON, BUT_CV_ADDR);
|
||||
createObject(OBJ_BUTTON, BUT_CV_SPD_L);
|
||||
createObject(OBJ_BUTTON, BUT_CV_SPD_M);
|
||||
createObject(OBJ_BUTTON, BUT_CV_SPD_H);
|
||||
createObject(OBJ_BUTTON, BUT_CV_ACC);
|
||||
createObject(OBJ_BUTTON, BUT_CV_DEC);
|
||||
createObject(OBJ_BUTTON, BUT_CV_CFG);
|
||||
createObject(OBJ_BUTTON, BUT_CV_MAN);
|
||||
newEvent(OBJ_WIN, WIN_READ_CV, EVNT_DRAW);
|
||||
break;
|
||||
case WIN_PROG_CV:
|
||||
//buttonData[BUT_CV_LNCV].backgnd = (wifiSetting.protocol == CLIENT_LNET) ? COLOR_CREAM : COLOR_LIGHTBLACK;
|
||||
setFieldsCV();
|
||||
setBitsCV();
|
||||
setStatusCV();
|
||||
switchData[SW_POM].state = modeProg;
|
||||
createObject(OBJ_WIN, WIN_PROG_CV);
|
||||
createObject(OBJ_LABEL, LBL_CV);
|
||||
createObject(OBJ_LABEL, LBL_POM);
|
||||
createObject(OBJ_LABEL, LBL_BITS);
|
||||
createObject(OBJ_SWITCH, SW_POM);
|
||||
createObject(OBJ_BUTTON, BUT_CV_READ);
|
||||
createObject(OBJ_BUTTON, BUT_CV_CNCL);
|
||||
if (wifiSetting.protocol == CLIENT_LNET)
|
||||
createObject(OBJ_BUTTON, BUT_CV_LNCV);
|
||||
createObject(OBJ_KEYBOARD, KEYB_CV);
|
||||
createObject(OBJ_CHAR, CHAR_CV_EQUAL);
|
||||
createObject(OBJ_BUTTON, BUT_CV_0);
|
||||
createObject(OBJ_BUTTON, BUT_CV_1);
|
||||
createObject(OBJ_BUTTON, BUT_CV_2);
|
||||
createObject(OBJ_BUTTON, BUT_CV_3);
|
||||
createObject(OBJ_BUTTON, BUT_CV_4);
|
||||
createObject(OBJ_BUTTON, BUT_CV_5);
|
||||
createObject(OBJ_BUTTON, BUT_CV_6);
|
||||
createObject(OBJ_BUTTON, BUT_CV_7);
|
||||
createObject(OBJ_TXT, TXT_CV);
|
||||
createObject(OBJ_TXT, TXT_CV_VAL);
|
||||
createObject(OBJ_TXT, TXT_CV_STATUS);
|
||||
newEvent(OBJ_WIN, WIN_PROG_CV, EVNT_DRAW);
|
||||
break;
|
||||
case WIN_PROG_ADDR:
|
||||
getLabelTxt(LBL_CV_ADDR, buf);
|
||||
snprintf(cvStatusBuf, PWD_LNG + 1, "%s", buf);
|
||||
createObject(OBJ_WIN, WIN_PROG_ADDR);
|
||||
createObject(OBJ_TXT, TXT_CV_STATUS);
|
||||
createObject(OBJ_ICON, ICON_ADDR);
|
||||
createObject(OBJ_TXT, TXT_CV_ADDR);
|
||||
createObject(OBJ_KEYBOARD, KEYB_CV_ADDR);
|
||||
createObject(OBJ_BUTTON, BUT_ADDR_CNCL);
|
||||
newEvent(OBJ_WIN, WIN_PROG_ADDR, EVNT_DRAW);
|
||||
break;
|
||||
case WIN_PROG_LNCV:
|
||||
setFieldsLNCV();
|
||||
createObject(OBJ_WIN, WIN_PROG_LNCV);
|
||||
createObject(OBJ_KEYBOARD, KEYB_LNCV);
|
||||
createObject(OBJ_LABEL, LBL_LNCV_ART);
|
||||
createObject(OBJ_LABEL, LBL_LNCV_MOD);
|
||||
createObject(OBJ_LABEL, LBL_LNCV_NUM);
|
||||
createObject(OBJ_BUTTON, BUT_LNCV_FIND);
|
||||
createObject(OBJ_BUTTON, BUT_LNCV_CNCL);
|
||||
createObject(OBJ_TXT, TXT_LNCV_ART);
|
||||
createObject(OBJ_TXT, TXT_LNCV_MOD);
|
||||
createObject(OBJ_TXT, TXT_LNCV_ADR);
|
||||
createObject(OBJ_TXT, TXT_LNCV_VAL);
|
||||
createObject(OBJ_CHAR, CHAR_LNCV_EQUAL);
|
||||
newEvent(OBJ_WIN, WIN_PROG_LNCV, EVNT_DRAW);
|
||||
break;
|
||||
case WIN_STEAM:
|
||||
fncData[FNC_ST_SMOKE].state = false;
|
||||
createObject(OBJ_WIN, WIN_STEAM);
|
||||
createObject(OBJ_DRAWSTR, DSTR_STEAM);
|
||||
createObject(OBJ_ICON, ICON_POWER);
|
||||
createObject(OBJ_ICON, ICON_MANOMETER);
|
||||
createObject(OBJ_ICON, ICON_STEAM_EDIT);
|
||||
createObject(OBJ_BUTTON, BUT_STEAM_CNCL);
|
||||
createObject(OBJ_FNC, FNC_ST_WATER);
|
||||
createObject(OBJ_FNC, FNC_ST_TENDER);
|
||||
createObject(OBJ_FNC, FNC_ST_WHISTLE);
|
||||
createObject(OBJ_FNC, FNC_ST_FIRE);
|
||||
createObject(OBJ_FNC, FNC_ST_SMOKE);
|
||||
createObject(OBJ_BAR, BAR_JOHNSON);
|
||||
createObject(OBJ_BAR, BAR_WATER);
|
||||
createObject(OBJ_BAR, BAR_TENDER);
|
||||
createObject(OBJ_BAR, BAR_BRAKE);
|
||||
newEvent(OBJ_WIN, WIN_STEAM, EVNT_DRAW);
|
||||
break;
|
||||
case WIN_UTIL:
|
||||
createObject(OBJ_WIN, WIN_UTIL);
|
||||
createObject(OBJ_BUTTON, BUT_UTL_I_SPEEDO);
|
||||
createObject(OBJ_BUTTON, BUT_UTL_T_SPEEDO);
|
||||
createObject(OBJ_BUTTON, BUT_UTL_I_STEAM);
|
||||
createObject(OBJ_BUTTON, BUT_UTL_T_STEAM);
|
||||
createObject(OBJ_BUTTON, BUT_UTL_I_SCAN);
|
||||
createObject(OBJ_BUTTON, BUT_UTL_T_SCAN);
|
||||
createObject(OBJ_BUTTON, BUT_UTL_I_STA);
|
||||
createObject(OBJ_BUTTON, BUT_UTL_T_STA);
|
||||
createObject(OBJ_ICON, ICON_UTL_EXIT);
|
||||
createObject(OBJ_DRAWSTR, DSTR_UTL_MENU);
|
||||
newEvent(OBJ_WIN, WIN_UTIL, EVNT_DRAW);
|
||||
break;
|
||||
case WIN_ACCESSORY:
|
||||
editAccessory = false;
|
||||
winData[WIN_ACCESSORY].backgnd = COLOR_WHITE;
|
||||
updateAccPanel();
|
||||
createObject(OBJ_WIN, WIN_ACCESSORY);
|
||||
createObject(OBJ_BUTTON, BUT_ACC_0);
|
||||
createObject(OBJ_BUTTON, BUT_ACC_1);
|
||||
createObject(OBJ_BUTTON, BUT_ACC_2);
|
||||
createObject(OBJ_BUTTON, BUT_ACC_3);
|
||||
createObject(OBJ_BUTTON, BUT_ACC_4);
|
||||
createObject(OBJ_BUTTON, BUT_ACC_5);
|
||||
createObject(OBJ_BUTTON, BUT_ACC_6);
|
||||
createObject(OBJ_BUTTON, BUT_ACC_7);
|
||||
createObject(OBJ_BUTTON, BUT_ACC_8);
|
||||
createObject(OBJ_BUTTON, BUT_ACC_9);
|
||||
createObject(OBJ_BUTTON, BUT_ACC_10);
|
||||
createObject(OBJ_BUTTON, BUT_ACC_11);
|
||||
createObject(OBJ_BUTTON, BUT_ACC_12);
|
||||
createObject(OBJ_BUTTON, BUT_ACC_13);
|
||||
createObject(OBJ_BUTTON, BUT_ACC_14);
|
||||
createObject(OBJ_BUTTON, BUT_ACC_15);
|
||||
createObject(OBJ_BUTTON, BUT_ACC_CNCL);
|
||||
createObject(OBJ_BUTTON, BUT_ACC_EDIT);
|
||||
createObject(OBJ_TXT, TXT_ACC_0);
|
||||
createObject(OBJ_TXT, TXT_ACC_1);
|
||||
createObject(OBJ_TXT, TXT_ACC_2);
|
||||
createObject(OBJ_TXT, TXT_ACC_3);
|
||||
createObject(OBJ_TXT, TXT_ACC_4);
|
||||
createObject(OBJ_TXT, TXT_ACC_5);
|
||||
createObject(OBJ_TXT, TXT_ACC_6);
|
||||
createObject(OBJ_TXT, TXT_ACC_7);
|
||||
createObject(OBJ_TXT, TXT_ACC_8);
|
||||
createObject(OBJ_TXT, TXT_ACC_9);
|
||||
createObject(OBJ_TXT, TXT_ACC_10);
|
||||
createObject(OBJ_TXT, TXT_ACC_11);
|
||||
createObject(OBJ_TXT, TXT_ACC_12);
|
||||
createObject(OBJ_TXT, TXT_ACC_13);
|
||||
createObject(OBJ_TXT, TXT_ACC_14);
|
||||
createObject(OBJ_TXT, TXT_ACC_15);
|
||||
createObject(OBJ_TXT, TXT_PANEL);
|
||||
newEvent(OBJ_WIN, WIN_ACCESSORY, EVNT_DRAW);
|
||||
break;
|
||||
case WIN_PANELS:
|
||||
createObject(OBJ_WIN, WIN_PANELS);
|
||||
createObject(OBJ_TXT, TXT_PANEL0);
|
||||
createObject(OBJ_TXT, TXT_PANEL1);
|
||||
createObject(OBJ_TXT, TXT_PANEL2);
|
||||
createObject(OBJ_TXT, TXT_PANEL3);
|
||||
createObject(OBJ_TXT, TXT_PANEL4);
|
||||
createObject(OBJ_TXT, TXT_PANEL5);
|
||||
createObject(OBJ_TXT, TXT_PANEL6);
|
||||
createObject(OBJ_TXT, TXT_PANEL7);
|
||||
createObject(OBJ_TXT, TXT_PANEL8);
|
||||
createObject(OBJ_TXT, TXT_PANEL9);
|
||||
createObject(OBJ_TXT, TXT_PANEL10);
|
||||
createObject(OBJ_TXT, TXT_PANEL11);
|
||||
createObject(OBJ_TXT, TXT_PANEL12);
|
||||
createObject(OBJ_TXT, TXT_PANEL13);
|
||||
createObject(OBJ_TXT, TXT_PANEL14);
|
||||
createObject(OBJ_TXT, TXT_PANEL15);
|
||||
newEvent(OBJ_WIN, WIN_PANELS, EVNT_DRAW);
|
||||
break;
|
||||
case WIN_PANEL_NAME:
|
||||
snprintf(keybNameBuf, PANEL_LNG + 1, panelNameBuf);
|
||||
txtData[TXT_NAME].maxLength = PANEL_LNG;
|
||||
createObject(OBJ_WIN, WIN_PANEL_NAME);
|
||||
createObject(OBJ_TXT, TXT_NAME);
|
||||
createObject(OBJ_KEYBOARD, KEYB_NAME);
|
||||
createObject(OBJ_BUTTON, BUT_NAME_OK);
|
||||
createObject(OBJ_BUTTON, BUT_NAME_CNCL);
|
||||
newEvent(OBJ_WIN, WIN_PANEL_NAME, EVNT_DRAW);
|
||||
break;
|
||||
case WIN_ACC_CTRL:
|
||||
snprintf(accKeybAddr, ADDR_LNG + 1, "%d", myTurnout);
|
||||
createObject(OBJ_WIN, WIN_ACC_CTRL);
|
||||
createObject(OBJ_TXT, TXT_ACC_ADDR);
|
||||
createObject(OBJ_KEYBOARD, KEYB_ACC);
|
||||
createObject(OBJ_ICON, ICON_KEYB_ACC);
|
||||
createObject(OBJ_BUTTON, BUT_ACC_RED);
|
||||
createObject(OBJ_BUTTON, BUT_ACC_GREEN);
|
||||
newEvent(OBJ_WIN, WIN_ACC_CTRL, EVNT_DRAW);
|
||||
break;
|
||||
case WIN_ACC_ASPECT:
|
||||
createObject(OBJ_WIN, WIN_ACC_ASPECT);
|
||||
createObject(OBJ_BUTTON, BUT_ACC_ASPECT0);
|
||||
createObject(OBJ_BUTTON, BUT_ACC_ASPECT1);
|
||||
createObject(OBJ_BUTTON, BUT_ACC_ASPECT2);
|
||||
if (currAccAspects == 4)
|
||||
createObject(OBJ_BUTTON, BUT_ACC_ASPECT3);
|
||||
newEvent(OBJ_WIN, WIN_ACC_ASPECT, EVNT_DRAW);
|
||||
break;
|
||||
case WIN_ACC_TYPE:
|
||||
createObject(OBJ_WIN, WIN_ACC_TYPE);
|
||||
createObject(OBJ_LABEL, LBL_ACC_TYPE);
|
||||
createObject(OBJ_FNC, FNC_ACC_TYPE);
|
||||
newEvent(OBJ_WIN, WIN_ACC_TYPE, EVNT_DRAW);
|
||||
break;
|
||||
case WIN_ACC_EDIT:
|
||||
n = accDef[currAccEdit.type].aspects;
|
||||
winData[WIN_ACC_EDIT].h = 130 + (n * 40);
|
||||
buttonData[BUT_TYPE_OK].y = 93 + (n * 40);
|
||||
buttonData[BUT_TYPE_CNCL].y = 93 + (n * 40);
|
||||
iconData[ICON_TYPE_OK].y = 97 + (n * 40);
|
||||
iconData[ICON_TYPE_CNCL].y = 97 + (n * 40);
|
||||
createObject(OBJ_WIN, WIN_ACC_EDIT);
|
||||
createObject(OBJ_LABEL, LBL_ACC_NAME);
|
||||
createObject(OBJ_LABEL, LBL_ACC_ADDR);
|
||||
createObject(OBJ_TXT, TXT_ACC_NAME);
|
||||
createObject(OBJ_TXT, TXT_ACC_ADDR1);
|
||||
createObject(OBJ_FNC, FNC_EDIT_ASPECT0);
|
||||
createObject(OBJ_BUTTON, BUT_ACC_OUT0);
|
||||
createObject(OBJ_BUTTON, BUT_ACC_OUT1);
|
||||
if (n > 1) {
|
||||
createObject(OBJ_FNC, FNC_EDIT_ASPECT1);
|
||||
createObject(OBJ_BUTTON, BUT_ACC_OUT4);
|
||||
createObject(OBJ_BUTTON, BUT_ACC_OUT5);
|
||||
}
|
||||
if (n > 2) {
|
||||
createObject(OBJ_TXT, TXT_ACC_ADDR2);
|
||||
createObject(OBJ_ICON, ICON_PLUS_ONE);
|
||||
createObject(OBJ_FNC, FNC_EDIT_ASPECT2);
|
||||
createObject(OBJ_BUTTON, BUT_ACC_OUT2);
|
||||
createObject(OBJ_BUTTON, BUT_ACC_OUT3);
|
||||
createObject(OBJ_BUTTON, BUT_ACC_OUT6);
|
||||
createObject(OBJ_BUTTON, BUT_ACC_OUT7);
|
||||
createObject(OBJ_BUTTON, BUT_ACC_OUT8);
|
||||
createObject(OBJ_BUTTON, BUT_ACC_OUT9);
|
||||
createObject(OBJ_BUTTON, BUT_ACC_OUT10);
|
||||
createObject(OBJ_BUTTON, BUT_ACC_OUT11);
|
||||
}
|
||||
if (n > 3) {
|
||||
createObject(OBJ_FNC, FNC_EDIT_ASPECT3);
|
||||
createObject(OBJ_BUTTON, BUT_ACC_OUT12);
|
||||
createObject(OBJ_BUTTON, BUT_ACC_OUT13);
|
||||
createObject(OBJ_BUTTON, BUT_ACC_OUT14);
|
||||
createObject(OBJ_BUTTON, BUT_ACC_OUT15);
|
||||
}
|
||||
createObject(OBJ_BUTTON, BUT_TYPE_OK);
|
||||
createObject(OBJ_BUTTON, BUT_TYPE_CNCL);
|
||||
newEvent(OBJ_WIN, WIN_ACC_EDIT, EVNT_DRAW);
|
||||
break;
|
||||
case WIN_ACC_NAME:
|
||||
snprintf(keybNameBuf, ACC_LNG + 1, accKeybName);
|
||||
txtData[TXT_NAME].maxLength = ACC_LNG;
|
||||
createObject(OBJ_WIN, WIN_ACC_NAME);
|
||||
createObject(OBJ_TXT, TXT_NAME);
|
||||
createObject(OBJ_KEYBOARD, KEYB_NAME);
|
||||
createObject(OBJ_BUTTON, BUT_NAME_OK);
|
||||
createObject(OBJ_BUTTON, BUT_NAME_CNCL);
|
||||
newEvent(OBJ_WIN, WIN_ACC_NAME, EVNT_DRAW);
|
||||
break;
|
||||
case WIN_ACC_ADDR1:
|
||||
snprintf(accKeybAdrEdit, ADDR_LNG + 1, "%d", currAccEdit.addr);
|
||||
createObject(OBJ_WIN, WIN_ACC_ADDR1);
|
||||
createObject(OBJ_TXT, TXT_ACC_EDIT);
|
||||
createObject(OBJ_KEYBOARD, KEYB_ACC_ADDR);
|
||||
newEvent(OBJ_WIN, WIN_ACC_ADDR1, EVNT_DRAW);
|
||||
break;
|
||||
case WIN_ACC_ADDR2:
|
||||
snprintf(accKeybAdrEdit, ADDR_LNG + 1, "%d", currAccEdit.addr2);
|
||||
createObject(OBJ_WIN, WIN_ACC_ADDR2);
|
||||
createObject(OBJ_TXT, TXT_ACC_EDIT);
|
||||
createObject(OBJ_KEYBOARD, KEYB_ACC_ADDR);
|
||||
newEvent(OBJ_WIN, WIN_ACC_ADDR2, EVNT_DRAW);
|
||||
break;
|
||||
case WIN_WIFI_SCAN:
|
||||
setTimer(TMR_SCAN, 5, TMR_ONESHOT);
|
||||
createObject(OBJ_WIN, WIN_WIFI_SCAN);
|
||||
createObject(OBJ_DRAWSTR, DSTR_WIFI_SCAN);
|
||||
createObject(OBJ_LABEL, LBL_SSID_SCAN);
|
||||
createObject(OBJ_FNC, FNC_SCAN_RESET);
|
||||
newEvent(OBJ_WIN, WIN_WIFI_SCAN, EVNT_DRAW);
|
||||
break;
|
||||
case WIN_STA_RUN:
|
||||
updateStationTime(staTime);
|
||||
updateStationLevel();
|
||||
updateStationStars();
|
||||
updateTargetStations();
|
||||
createObject(OBJ_WIN, WIN_STA_RUN);
|
||||
createObject(OBJ_LABEL, LBL_STA_RUN);
|
||||
createObject(OBJ_LABEL, LBL_STA_LEVEL);
|
||||
createObject(OBJ_LABEL, LBL_STA_INSTR);
|
||||
createObject(OBJ_FNC, FNC_STA_STARS);
|
||||
createObject(OBJ_ICON, ICON_STA_CLOCK);
|
||||
createObject(OBJ_ICON, ICON_STA_STATION);
|
||||
createObject(OBJ_ICON, ICON_STA_EDIT);
|
||||
createObject(OBJ_BUTTON, BUT_STA_START);
|
||||
createObject(OBJ_BUTTON, BUT_STA_CNCL);
|
||||
createObject(OBJ_TXT, TXT_STA_LEVEL);
|
||||
createObject(OBJ_TXT, TXT_STA_STARS);
|
||||
createObject(OBJ_TXT, TXT_STA_STATION);
|
||||
createObject(OBJ_TXT, TXT_STA_CLOCK);
|
||||
newEvent(OBJ_WIN, WIN_STA_RUN, EVNT_DRAW);
|
||||
break;
|
||||
case WIN_STA_PLAY:
|
||||
updateTurnoutButtons();
|
||||
fncData[FNC_STA_RAYO].state = isTrackOff();
|
||||
createObject(OBJ_WIN, WIN_STA_PLAY);
|
||||
createObject(OBJ_DRAWSTR, DSTR_STATION_PLAY);
|
||||
createObject(OBJ_ICON, ICON_STA_TARGET);
|
||||
createObject(OBJ_ICON, ICON_STA_TRAIN);
|
||||
createObject(OBJ_ICON, ICON_STA_PIN);
|
||||
createObject(OBJ_ICON, ICON_STA_TIME);
|
||||
createObject(OBJ_ICON, ICON_STA_COUNT);
|
||||
createObject(OBJ_TXT, TXT_STA_TIME);
|
||||
createObject(OBJ_TXT, TXT_STA_COUNT);
|
||||
createObject(OBJ_TXT, TXT_STA_STARC);
|
||||
createObject(OBJ_GAUGE, GAUGE_STATION);
|
||||
createObject(OBJ_FNC, FNC_STA_DIR);
|
||||
createObject(OBJ_FNC, FNC_STA_STARC);
|
||||
createObject(OBJ_FNC, FNC_STA_RAYO);
|
||||
createObject(OBJ_BUTTON, BUT_STA_STOP);
|
||||
switch (staMaxTurnout) {
|
||||
case 1:
|
||||
fncData[FNC_STA_ACC0].x = 104;
|
||||
buttonData[BUT_STA_ACC0].x = 100;
|
||||
createObject(OBJ_BUTTON, BUT_STA_ACC0);
|
||||
break;
|
||||
case 2:
|
||||
fncData[FNC_STA_ACC0].x = 54;
|
||||
fncData[FNC_STA_ACC1].x = 154;
|
||||
buttonData[BUT_STA_ACC0].x = 50;
|
||||
buttonData[BUT_STA_ACC1].x = 150;
|
||||
createObject(OBJ_BUTTON, BUT_STA_ACC0);
|
||||
createObject(OBJ_BUTTON, BUT_STA_ACC1);
|
||||
break;
|
||||
case 3:
|
||||
fncData[FNC_STA_ACC0].x = 40;
|
||||
fncData[FNC_STA_ACC1].x = 104;
|
||||
fncData[FNC_STA_ACC2].x = 168;
|
||||
buttonData[BUT_STA_ACC0].x = 36;
|
||||
buttonData[BUT_STA_ACC1].x = 100;
|
||||
buttonData[BUT_STA_ACC2].x = 164;
|
||||
createObject(OBJ_BUTTON, BUT_STA_ACC0);
|
||||
createObject(OBJ_BUTTON, BUT_STA_ACC1);
|
||||
createObject(OBJ_BUTTON, BUT_STA_ACC2);
|
||||
break;
|
||||
default:
|
||||
fncData[FNC_STA_ACC0].x = 20;
|
||||
fncData[FNC_STA_ACC1].x = 76;
|
||||
fncData[FNC_STA_ACC2].x = 132;
|
||||
fncData[FNC_STA_ACC3].x = 188;
|
||||
buttonData[BUT_STA_ACC0].x = 16;
|
||||
buttonData[BUT_STA_ACC1].x = 72;
|
||||
buttonData[BUT_STA_ACC2].x = 128;
|
||||
buttonData[BUT_STA_ACC3].x = 184;
|
||||
createObject(OBJ_BUTTON, BUT_STA_ACC0);
|
||||
createObject(OBJ_BUTTON, BUT_STA_ACC1);
|
||||
createObject(OBJ_BUTTON, BUT_STA_ACC2);
|
||||
createObject(OBJ_BUTTON, BUT_STA_ACC3);
|
||||
break;
|
||||
}
|
||||
newEvent(OBJ_WIN, WIN_STA_PLAY, EVNT_DRAW);
|
||||
break;
|
||||
case WIN_STA_STARS:
|
||||
createObject(OBJ_WIN, WIN_STA_STARS);
|
||||
if (staCurrTime > 0) {
|
||||
staStars++;
|
||||
createObject(OBJ_FNC, FNC_STA_STAR1);
|
||||
if (staCurrTime > 10) { // time remaining
|
||||
staStars++;
|
||||
createObject(OBJ_FNC, FNC_STA_STAR2);
|
||||
createObject(OBJ_LABEL, LBL_STA_EXCEL);
|
||||
}
|
||||
else {
|
||||
createObject(OBJ_LABEL, LBL_STA_GREAT);
|
||||
}
|
||||
updateStationStars();
|
||||
}
|
||||
else {
|
||||
createObject(OBJ_ICON, ICON_STA_TIMEOUT);
|
||||
createObject(OBJ_LABEL, LBL_STA_TIMEOUT);
|
||||
}
|
||||
newEvent(OBJ_WIN, WIN_STA_STARS, EVNT_DRAW);
|
||||
break;
|
||||
case WIN_STA_EDIT:
|
||||
snprintf(staStartTimeBuf, IP_LNG + 1, "%d", staStartTime);
|
||||
snprintf(staStatNumBuf, IP_LNG + 1, "%d", staMaxStations);
|
||||
snprintf(staTurnNumBuf, IP_LNG + 1, "%d", staMaxTurnout);
|
||||
snprintf(staTurnout1Buf, ADDR_LNG + 1, "%d", staTurnoutAdr1);
|
||||
snprintf(staTurnout2Buf, ADDR_LNG + 1, "%d", staTurnoutAdr2);
|
||||
snprintf(staTurnout3Buf, ADDR_LNG + 1, "%d", staTurnoutAdr3);
|
||||
snprintf(staTurnout4Buf, ADDR_LNG + 1, "%d", staTurnoutAdr4);
|
||||
for (n = 0; n < 8; n++)
|
||||
switchData[SW_STA_OR1 + n].state = bitRead(staTurnoutDef, n);
|
||||
createObject(OBJ_WIN, WIN_STA_EDIT);
|
||||
createObject(OBJ_LABEL, LBL_STA_STATIONS);
|
||||
createObject(OBJ_LABEL, LBL_STA_TURNOUTS);
|
||||
createObject(OBJ_LABEL, LBL_STA_TIME);
|
||||
createObject(OBJ_LABEL, LBL_STA_DESC);
|
||||
createObject(OBJ_TXT, TXT_STA_STARTTIME);
|
||||
createObject(OBJ_TXT, TXT_STA_STATNUM);
|
||||
createObject(OBJ_TXT, TXT_STA_TURNNUM);
|
||||
createObject(OBJ_TXT, TXT_STA_TURNOUT1);
|
||||
createObject(OBJ_TXT, TXT_STA_TURNOUT2);
|
||||
createObject(OBJ_TXT, TXT_STA_TURNOUT3);
|
||||
createObject(OBJ_TXT, TXT_STA_TURNOUT4);
|
||||
createObject(OBJ_BUTTON, BUT_STA_EDIT);
|
||||
createObject(OBJ_SWITCH, SW_STA_OR1);
|
||||
createObject(OBJ_SWITCH, SW_STA_OR2);
|
||||
createObject(OBJ_SWITCH, SW_STA_OR3);
|
||||
createObject(OBJ_SWITCH, SW_STA_OR4);
|
||||
createObject(OBJ_SWITCH, SW_STA_INV1);
|
||||
createObject(OBJ_SWITCH, SW_STA_INV2);
|
||||
createObject(OBJ_SWITCH, SW_STA_INV3);
|
||||
createObject(OBJ_SWITCH, SW_STA_INV4);
|
||||
createObject(OBJ_BUTTON, BUT_STA_STAM);
|
||||
createObject(OBJ_BUTTON, BUT_STA_STAP);
|
||||
createObject(OBJ_BUTTON, BUT_STA_TURNM);
|
||||
createObject(OBJ_BUTTON, BUT_STA_TURNP);
|
||||
newEvent(OBJ_WIN, WIN_STA_EDIT, EVNT_DRAW);
|
||||
break;
|
||||
case WIN_STA_KEYB:
|
||||
createObject(OBJ_WIN, WIN_STA_KEYB);
|
||||
createObject(OBJ_KEYBOARD, KEYB_STA);
|
||||
newEvent(OBJ_WIN, WIN_STA_KEYB, EVNT_DRAW);
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void alertWindow(byte err) {
|
||||
errType = err;
|
||||
createObject(OBJ_WIN, WIN_ALERT);
|
||||
switch (err) {
|
||||
case ERR_SERV:
|
||||
createObject(OBJ_ICON, ICON_WARNING);
|
||||
createObject(OBJ_ICON, ICON_WARNING_ON);
|
||||
createObject(OBJ_LABEL, LBL_SERVICE);
|
||||
break;
|
||||
case ERR_CHG_WIFI:
|
||||
createObject(OBJ_ICON, ICON_INFO);
|
||||
createObject(OBJ_LABEL, LBL_CHG_WIFI);
|
||||
break;
|
||||
case ERR_FULL:
|
||||
createObject(OBJ_ICON, ICON_WARNING);
|
||||
createObject(OBJ_ICON, ICON_WARNING_ON);
|
||||
createObject(OBJ_LABEL, LBL_STACK_FULL);
|
||||
break;
|
||||
case ERR_STOP:
|
||||
createObject(OBJ_ICON, ICON_ESTOP);
|
||||
createObject(OBJ_LABEL, LBL_ESTOP);
|
||||
break;
|
||||
case ERR_WAIT:
|
||||
case ERR_CV:
|
||||
barData[BAR_WAIT].value = 0;
|
||||
setTimer(TMR_WAIT, 5, TMR_ONESHOT);
|
||||
if (err == ERR_WAIT)
|
||||
createObject(OBJ_ICON, ICON_WAIT);
|
||||
else
|
||||
createObject(OBJ_ICON, ICON_WAIT_CV);
|
||||
createObject(OBJ_BAR, BAR_WAIT);
|
||||
break;
|
||||
case ERR_ASK_SURE:
|
||||
createObject(OBJ_ICON, ICON_WARNING);
|
||||
createObject(OBJ_ICON, ICON_WARNING_ON);
|
||||
createObject(OBJ_LABEL, LBL_ASK_SURE);
|
||||
createObject(OBJ_BUTTON, BUT_SURE_OK);
|
||||
createObject(OBJ_BUTTON, BUT_SURE_CNCL);
|
||||
break;
|
||||
}
|
||||
newEvent(OBJ_WIN, WIN_ALERT, EVNT_DRAW);
|
||||
}
|
||||
648
PacoMouseCYD/src/PacoMouseCYD/xnet.ino
Normal file
@@ -0,0 +1,648 @@
|
||||
/* PacoMouseCYD throttle -- F. Cañada 2025-2026 -- https://usuaris.tinet.cat/fmco/
|
||||
|
||||
This software and associated files are a DIY project that is not intended for commercial use.
|
||||
This software uses libraries with different licenses, follow all their different terms included.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED.
|
||||
|
||||
Sources are only provided for building and uploading to the device.
|
||||
You are not allowed to modify the source code or fork/publish this project.
|
||||
Commercial use is forbidden.
|
||||
*/
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// ***** XPRESSNET LAN SOPORTE *****
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
void showErrorXnet() { // muestra pantalla de error
|
||||
if (csStatus & csEmergencyOff) {
|
||||
iconData[ICON_POWER].color = COLOR_RED;
|
||||
setTimer (TMR_POWER, 5, TMR_PERIODIC); // Flash power icon
|
||||
if ((isWindow(WIN_THROTTLE)) || (isWindow(WIN_STEAM)))
|
||||
newEvent(OBJ_ICON, ICON_POWER, EVNT_DRAW);
|
||||
if (isWindow(WIN_STA_PLAY)) {
|
||||
fncData[FNC_STA_RAYO].state = true;
|
||||
newEvent(OBJ_FNC, FNC_STA_RAYO, EVNT_DRAW);
|
||||
}
|
||||
}
|
||||
if (csStatus & csServiceMode) {
|
||||
if ((isWindow(WIN_THROTTLE)) || (isWindow(WIN_STEAM)))
|
||||
alertWindow(ERR_SERV);
|
||||
}
|
||||
if (csStatus & csEmergencyStop) {
|
||||
if ((isWindow(WIN_THROTTLE)) || (isWindow(WIN_STEAM)))
|
||||
alertWindow(ERR_STOP);
|
||||
}
|
||||
}
|
||||
|
||||
void showNormalOpsXnet() {
|
||||
stopTimer (TMR_POWER);
|
||||
iconData[ICON_POWER].color = COLOR_GREEN;
|
||||
if ((isWindow(WIN_THROTTLE)) || (isWindow(WIN_STEAM)))
|
||||
newEvent(OBJ_ICON, ICON_POWER, EVNT_DRAW);
|
||||
if (isWindow(WIN_STA_PLAY)) {
|
||||
fncData[FNC_STA_RAYO].state = false;
|
||||
newEvent(OBJ_FNC, FNC_STA_RAYO, EVNT_DRAW);
|
||||
}
|
||||
if (isWindow(WIN_ALERT)) {
|
||||
switch (errType) {
|
||||
case ERR_SERV:
|
||||
case ERR_STOP:
|
||||
case ERR_CV:
|
||||
closeWindow(WIN_ALERT);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t addrXnet(uint16_t adr) {
|
||||
if (adr > 99) // Comprueba si es direccion larga
|
||||
adr |= 0xC000;
|
||||
return adr;
|
||||
}
|
||||
|
||||
|
||||
bool isRecentMM () { // Comprueba central Multimaus reciente
|
||||
if ((xnetCS == 0x10) && (highVerMM > 0) && (lowVerMM > 0x02))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// ***** XPRESSNET LAN MESSAGES *****
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
void getStatusXnet () {
|
||||
headerXN (0x21); // Command station status request (0x21,0x24,0x05)
|
||||
dataXN (0x24);
|
||||
sendXN();
|
||||
}
|
||||
|
||||
|
||||
void getVersionXnet () {
|
||||
headerXN (0x21); // Command station software version (0x21,0x21,0x00)
|
||||
dataXN (0x21);
|
||||
sendXN();
|
||||
}
|
||||
|
||||
void versionMultimaus() {
|
||||
headerXN (0xF1); // Multimaus software version (0xF1,0x0A,XOR)
|
||||
dataXN (0x0A);
|
||||
sendXN();
|
||||
}
|
||||
|
||||
|
||||
void getResultsXnet() {
|
||||
headerXN (0x21); // Request for Service Mode results (0x21,0x10,0x31)
|
||||
dataXN (0x10);
|
||||
sendXN();
|
||||
//getResultsSM = false;
|
||||
}
|
||||
|
||||
|
||||
void resumeOperationsXnet () {
|
||||
headerXN (0x21); // Resume operations request (0x21,0x81,0xA0)
|
||||
dataXN (0x81);
|
||||
sendXN();
|
||||
}
|
||||
|
||||
|
||||
void emergencyOffXnet() {
|
||||
headerXN (0x21); // Stop operations request (emergency off)(0x21,0x80,0xA1)
|
||||
dataXN (0x80);
|
||||
sendXN();
|
||||
}
|
||||
|
||||
|
||||
void infoLocomotoraXnet (unsigned int loco) { // Locomotive information request (0xE3,0x00,ADRH,ADRL,XOR)
|
||||
uint16_t adr;
|
||||
adr = addrXnet(loco);
|
||||
headerXN (0xE3);
|
||||
dataXN (0x00);
|
||||
dataXN (highByte(adr));
|
||||
dataXN (lowByte (adr));
|
||||
sendXN();
|
||||
if ((xnetVersion > 0x35) || (xnetCS == 0x10)) {
|
||||
headerXN (0xE3);
|
||||
if (xnetCS == 0x10)
|
||||
dataXN (0xF0); // Locomotive function F13..F20 info MM (0xE3,0xF0,ADRH,ADRL,XOR)
|
||||
else
|
||||
dataXN (0x09); // Locomotive function F13..F28 info v3.6 (0xE3,0x09,ADRH,ADRL,XOR)
|
||||
dataXN (highByte(adr));
|
||||
dataXN (lowByte (adr));
|
||||
sendXN();
|
||||
}
|
||||
getInfoLoco = false;
|
||||
}
|
||||
|
||||
|
||||
void locoOperationSpeedXnet() { // Locomotive speed and direction operations (0xE4,ID,ADRH,ADRL,SPD,XOR)
|
||||
uint16_t adr;
|
||||
adr = addrXnet(locoData[myLocoData].myAddr.address);
|
||||
headerXN (0xE4);
|
||||
if (bitRead(locoData[myLocoData].mySteps, 2)) { // 128 steps
|
||||
dataXN (0x13);
|
||||
}
|
||||
else {
|
||||
if (bitRead(locoData[myLocoData].mySteps, 1)) { // 28 steps
|
||||
dataXN (0x12);
|
||||
}
|
||||
else {
|
||||
dataXN (0x10); // 14 steps
|
||||
}
|
||||
}
|
||||
dataXN (highByte(adr));
|
||||
dataXN (lowByte(adr));
|
||||
dataXN (locoData[myLocoData].mySpeed | locoData[myLocoData].myDir);
|
||||
sendXN();
|
||||
bitClear(locoData[myLocoData].mySteps, 3); // currently operated by me
|
||||
updateSpeedDir();
|
||||
}
|
||||
|
||||
|
||||
void funcOperationsXnet (byte fnc) { // Function operation instructions (0xE4,ID,ADRH,ADRL,GRP,XOR)
|
||||
byte grp, grpID;
|
||||
uint16_t adr;
|
||||
adr = addrXnet(locoData[myLocoData].myAddr.address);
|
||||
if (fnc > 20) {
|
||||
grpID = 0x28; // F21..F28
|
||||
grp = ((locoData[myLocoData].myFunc.xFunc[2] >> 5) & 0x07);
|
||||
grp |= (locoData[myLocoData].myFunc.xFunc[3] << 3);
|
||||
}
|
||||
else {
|
||||
if (fnc > 12) {
|
||||
if (xnetCS == 0x10)
|
||||
grpID = 0xF3; // F13..F20 MM (0xE4,0xF3,ADH,ADL,F13F20,XOR)
|
||||
else
|
||||
grpID = 0x23; // F13..F20
|
||||
grp = ((locoData[myLocoData].myFunc.xFunc[1] >> 5) & 0x07);
|
||||
grp |= (locoData[myLocoData].myFunc.xFunc[2] << 3);
|
||||
}
|
||||
else {
|
||||
if (fnc > 8) {
|
||||
grpID = 0x22; // F9..F12
|
||||
grp = ((locoData[myLocoData].myFunc.xFunc[1] >> 1) & 0x0F);
|
||||
}
|
||||
else {
|
||||
if (fnc > 4) {
|
||||
grpID = 0x21; // F5..F8
|
||||
grp = ((locoData[myLocoData].myFunc.xFunc[0] >> 5) & 0x07);
|
||||
if (bitRead(locoData[myLocoData].myFunc.xFunc[1], 0))
|
||||
grp |= 0x08;
|
||||
}
|
||||
else {
|
||||
grpID = 0x20; // F0..F4
|
||||
grp = ((locoData[myLocoData].myFunc.xFunc[0] >> 1) & 0x0F);
|
||||
if (bitRead(locoData[myLocoData].myFunc.xFunc[0], 0))
|
||||
grp |= 0x10;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
headerXN (0xE4);
|
||||
dataXN (grpID);
|
||||
dataXN (highByte(adr));
|
||||
dataXN (lowByte(adr));
|
||||
dataXN (grp);
|
||||
sendXN();
|
||||
bitClear(locoData[myLocoData].mySteps, 3); // currently operated by me
|
||||
}
|
||||
|
||||
|
||||
byte getCurrentStepXnet() {
|
||||
byte currStep;
|
||||
if (bitRead(locoData[myLocoData].mySteps, 2)) { // 128 steps -> 0..126
|
||||
if (locoData[myLocoData].mySpeed > 1)
|
||||
return (locoData[myLocoData].mySpeed - 1);
|
||||
}
|
||||
else {
|
||||
if (bitRead(locoData[myLocoData].mySteps, 1)) { // 28 steps -> 0..28 '---04321' -> '---43210'
|
||||
currStep = (locoData[myLocoData].mySpeed << 1) & 0x1F;
|
||||
bitWrite(currStep, 0, bitRead(locoData[myLocoData].mySpeed, 4));
|
||||
if (currStep > 3)
|
||||
return (currStep - 3);
|
||||
}
|
||||
else { // 14 steps -> 0..14
|
||||
if (locoData[myLocoData].mySpeed > 1)
|
||||
return (locoData[myLocoData].mySpeed - 1);
|
||||
}
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
void setAccessoryXnet (unsigned int direccion, bool activa, byte posicion) { // 1..1024
|
||||
byte adr, dato;
|
||||
direccion--; // 000000AAAAAAAABB
|
||||
adr = (direccion >> 2) & 0x00FF; // AAAAAAAA
|
||||
dato = ((direccion & 0x0003) << 1) | 0x80; // 1000xBBx
|
||||
if (posicion > 0)
|
||||
dato |= 0x01;
|
||||
if (activa) { // 1000dBBD
|
||||
dato |= 0x08;
|
||||
}
|
||||
headerXN (0x52); // Accessory Decoder operation request (0x52,AAAAAAAA,1000dBBD,XOR)
|
||||
dataXN (adr);
|
||||
dataXN (dato);
|
||||
sendXN();
|
||||
}
|
||||
|
||||
|
||||
void setTimeXnet(byte hh, byte mm, byte rate) {
|
||||
clockHour = hh;
|
||||
clockMin = mm;
|
||||
clockRate = rate;
|
||||
if (rate > 0) {
|
||||
headerXN (0x24); // set clock
|
||||
dataXN (0x2B);
|
||||
dataXN (hh);
|
||||
dataXN (mm);
|
||||
dataXN (rate);
|
||||
sendXN ();
|
||||
/*
|
||||
headerXN (0x21); // start clock
|
||||
dataXN (0x2C);
|
||||
sendXN (0x07);
|
||||
*/
|
||||
}
|
||||
else {
|
||||
headerXN (0x21); // recommended for rate=0. stop clock
|
||||
dataXN (0x2D);
|
||||
sendXN ();
|
||||
}
|
||||
}
|
||||
|
||||
void readCVXnet (unsigned int adr, byte stepPrg) {
|
||||
if (!modeProg) { // Read only in Direct mode
|
||||
if (isRecentMM()) {
|
||||
headerXN (0x23); // Multimaus v1.03
|
||||
dataXN (0x15);
|
||||
adr--;
|
||||
dataXN (highByte(adr) & 0x03);
|
||||
dataXN (lowByte(adr));
|
||||
sendXN();
|
||||
lastCV = lowByte(adr) + 1;
|
||||
}
|
||||
else {
|
||||
headerXN (0x22);
|
||||
if (xnetVersion > 0x35)
|
||||
dataXN (0x18 | (highByte(adr) & 0x03)); // v3.6 & up CV1..CV1024
|
||||
else
|
||||
dataXN (0x15); // v3.0 CV1..CV256
|
||||
dataXN (lowByte(adr));
|
||||
sendXN();
|
||||
lastCV = lowByte(adr);
|
||||
}
|
||||
getResultsSM = true;
|
||||
infoTimer = millis();
|
||||
progStepCV = stepPrg;
|
||||
//DEBUG_MSG("Read CV %d", adr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void writeCVXnet (unsigned int adr, unsigned int data, byte stepPrg) {
|
||||
uint16_t adrLoco;
|
||||
if (modeProg) {
|
||||
headerXN (0xE6); // Operations Mode Programming byte mode write request (0xE6,0x30,ADRH,ADRL,0xEC+C,CV,DATA,XOR)
|
||||
dataXN (0x30);
|
||||
adrLoco = addrXnet(locoData[myLocoData].myAddr.address);
|
||||
dataXN (highByte(adrLoco));
|
||||
dataXN (lowByte(adrLoco));
|
||||
adr--;
|
||||
dataXN (0xEC | (highByte(adr) & 0x03));
|
||||
dataXN (lowByte(adr));
|
||||
dataXN(data);
|
||||
sendXN();
|
||||
}
|
||||
else {
|
||||
if (isRecentMM()) {
|
||||
headerXN (0x24); // Multimaus v1.03
|
||||
dataXN (0x16);
|
||||
adr--;
|
||||
dataXN (highByte(adr) & 0x03);
|
||||
dataXN (lowByte(adr));
|
||||
dataXN(data);
|
||||
sendXN();
|
||||
lastCV = lowByte(adr) + 1;
|
||||
}
|
||||
else {
|
||||
headerXN (0x23);
|
||||
if (xnetVersion > 0x35)
|
||||
dataXN (0x1C | (highByte(adr) & 0x03)); // v3.6 & up CV1..CV1024
|
||||
else
|
||||
dataXN (0x16); // v3.0 CV1..CV256
|
||||
dataXN (lowByte(adr));
|
||||
dataXN(data);
|
||||
sendXN();
|
||||
lastCV = lowByte(adr);
|
||||
}
|
||||
getResultsSM = true;
|
||||
infoTimer = millis();
|
||||
}
|
||||
progStepCV = stepPrg;
|
||||
//DEBUG_MSG("Write CV%d = %d", adr, data);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// ***** XPRESSNET LAN DECODE *****
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
void headerXN (byte header) {
|
||||
txBytes = HEADER; // coloca header en el buffer
|
||||
txXOR = header;
|
||||
txBuffer[txBytes++] = header;
|
||||
txBuffer[FRAME1] = 0xFF;
|
||||
txBuffer[FRAME2] = 0xFE;
|
||||
}
|
||||
|
||||
|
||||
void dataXN (byte dato) {
|
||||
txBuffer[txBytes++] = dato; // coloca dato en el buffer
|
||||
txXOR ^= dato;
|
||||
}
|
||||
|
||||
|
||||
void sendXN () {
|
||||
bool recvAnswer;
|
||||
txBuffer[txBytes++] = txXOR; // coloca XOR byte en el buffer
|
||||
#ifdef DEBUG
|
||||
Serial.print(F("TX: "));
|
||||
for (uint8_t x = 0; x < txBytes; x++) {
|
||||
uint8_t val = txBuffer[x];
|
||||
if (val < 16)
|
||||
Serial.print('0');
|
||||
Serial.print(val, HEX);
|
||||
Serial.print(' ');
|
||||
}
|
||||
Serial.println();
|
||||
#endif
|
||||
Client.write((byte *)&txBuffer[FRAME1], txBytes); // envia paquete xpressnet
|
||||
timeoutXnet = millis();
|
||||
recvAnswer = false;
|
||||
while ((millis() - timeoutXnet < 500) && (!recvAnswer)) // wait answer for 500ms
|
||||
recvAnswer = xnetReceive();
|
||||
}
|
||||
|
||||
|
||||
bool xnetReceive() {
|
||||
bool getAnswer;
|
||||
getAnswer = false;
|
||||
while (Client.available()) {
|
||||
rxData = Client.read();
|
||||
//DEBUG_MSG("%d-%02X", rxIndice, rxData);
|
||||
switch (rxIndice) {
|
||||
case FRAME1:
|
||||
rxBufferXN[FRAME1] = rxData;
|
||||
if (rxData == 0xFF) // 0xFF... Posible inicio de paquete
|
||||
rxIndice = FRAME2;
|
||||
break;
|
||||
case FRAME2:
|
||||
rxBufferXN[FRAME2] = rxData;
|
||||
switch (rxData) {
|
||||
case 0xFF: // 0xFF 0xFF... FRAME2 puede ser FRAME1 (inicio de otro paquete)
|
||||
break;
|
||||
case 0xFE: // 0xFF 0xFE... Inicio paquete correcto
|
||||
case 0xFD: // 0xFF 0xFD... Inicio paquete de broadcast correcto
|
||||
rxIndice = HEADER;
|
||||
rxXOR = 0;
|
||||
break;
|
||||
default: // 0xFF 0xXX... No es inicio de paquete
|
||||
rxIndice = FRAME1;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
rxBufferXN[rxIndice++] = rxData;
|
||||
rxXOR ^= rxData;
|
||||
if (((rxBufferXN[HEADER] & 0x0F) + 4) == rxIndice) { // si se han recibido todos los datos indicados en el paquete
|
||||
if (rxXOR == 0) { // si el paquete es correcto
|
||||
rxBytes = rxIndice;
|
||||
#ifdef DEBUG
|
||||
Serial.print(F("RX: "));
|
||||
for (uint8_t x = 0; x < rxBytes; x++) {
|
||||
uint8_t val = rxBufferXN[x];
|
||||
if (val < 16)
|
||||
Serial.print('0');
|
||||
Serial.print(val, HEX);
|
||||
Serial.print(' ');
|
||||
}
|
||||
Serial.println();
|
||||
#endif
|
||||
procesaXN(); // nuevo paquete recibido, procesarlo
|
||||
getAnswer = true;
|
||||
}
|
||||
rxIndice = FRAME1; // proximo paquete
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return getAnswer;
|
||||
}
|
||||
|
||||
void processXnet () { // procesa Xpressnet
|
||||
xnetReceive();
|
||||
if (getInfoLoco && (csStatus == csNormalOps))
|
||||
infoLocomotoraXnet(addrXnet(locoData[myLocoData].myAddr.address));
|
||||
if (millis() - infoTimer > 1000UL) { // Cada segundo
|
||||
infoTimer = millis();
|
||||
if (getResultsSM) // Resultados de CV pendientes
|
||||
getResultsXnet(); // pide resultados
|
||||
else {
|
||||
if (bitRead(locoData[myLocoData].mySteps, 3)) // Loco controlada por otro mando
|
||||
getInfoLoco = true; // pide info locomotora
|
||||
if (askMultimaus) { // pide info Multimaus
|
||||
askMultimaus = false;
|
||||
versionMultimaus();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (progFinished) { // fin de lectura/programacion CV
|
||||
progFinished = false;
|
||||
endProg();
|
||||
}
|
||||
if (millis() - pingTimer > XNET_PING_INTERVAL) { // Refresca para mantener la conexion
|
||||
pingTimer = millis();
|
||||
getStatusXnet(); // pide estado de la central
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void procesaXN () {
|
||||
byte n, longitud, modulo, dato;
|
||||
uint16_t adr;
|
||||
|
||||
switch (rxBufferXN[HEADER]) { // segun el header byte
|
||||
case 0x61:
|
||||
switch (rxBufferXN[DATA1]) {
|
||||
case 0x01: // Normal operation resumed (0x61,0x01,0x60)
|
||||
csStatus = csNormalOps;
|
||||
showNormalOpsXnet();
|
||||
break;
|
||||
case 0x08: // Z21 LAN_X_BC_TRACK_SHORT_CIRCUIT (0x61,0x08,XOR)
|
||||
case 0x00: // Track power off (0x61,0x00,0x61)
|
||||
csStatus |= csEmergencyOff;
|
||||
showErrorXnet();
|
||||
break;
|
||||
case 0x02: // Service mode entry (0x61,0x02,0x63)
|
||||
csStatus |= csServiceMode;
|
||||
if (!getResultsSM) // show 'Service Mode' if we aren't programming CV
|
||||
showErrorXnet();
|
||||
break;
|
||||
case 0x12: // Programming info. "shortcircuit" (0x61,0x12,XOR)
|
||||
case 0x13: // Programming info. "Data byte not found" (0x61,0x13,XOR)
|
||||
CVdata = 0x0600;
|
||||
getResultsSM = false;
|
||||
progFinished = true;
|
||||
break;
|
||||
case 0x81: // Command station busy response (0x61,0x81,XOR)
|
||||
break;
|
||||
case 0x1F: // Programming info. "Command station busy" (0x61,0x1F,XOR)
|
||||
getResultsSM = true;
|
||||
infoTimer = millis();
|
||||
break;
|
||||
case 0x82: // Instruction not supported by command station (0x61,0x82,XOR)
|
||||
getResultsSM = false;
|
||||
if (csStatus & csServiceMode) {
|
||||
CVdata = 0x0600;
|
||||
progFinished = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0x81:
|
||||
if (rxBufferXN[DATA1] == 0) { // Emergency Stop (0x81,0x00,0x81)
|
||||
csStatus |= csEmergencyStop;
|
||||
showErrorXnet();
|
||||
}
|
||||
break;
|
||||
case 0x62:
|
||||
if (rxBufferXN[DATA1] == 0x22) { // Command station status indication response (0x62,0x22,DATA,XOR)
|
||||
csStatus = rxBufferXN[DATA2] & (csEmergencyStop | csEmergencyOff | csServiceMode) ;
|
||||
if ((xnetCS >= 0x10) && (rxBufferXN[DATA2] & csProgrammingModeActive)) // Multimaus/Z21 Service Mode
|
||||
csStatus |= csServiceMode;
|
||||
if (csStatus == csNormalOps)
|
||||
showNormalOpsXnet();
|
||||
else
|
||||
showErrorXnet();
|
||||
}
|
||||
break;
|
||||
case 0x63:
|
||||
switch (rxBufferXN[DATA1]) {
|
||||
case 0x03: // Broadcast "Modellzeit" (0x63,0x03,dddhhhhh,s0mmmmmm,XOR) (v4.0)
|
||||
clockHour = rxBufferXN[DATA2] & 0x1F;
|
||||
clockMin = rxBufferXN[DATA3] & 0x3F;
|
||||
clockRate = !bitRead(rxBufferXN[DATA3], 7);
|
||||
updateFastClock();
|
||||
break;
|
||||
case 0x14: // Service Mode response for Direct CV mode (0x63,0x1x,CV,DATA,XOR)
|
||||
case 0x15:
|
||||
case 0x16:
|
||||
case 0x17:
|
||||
if (rxBufferXN[DATA2] == lastCV) { // comprobar CV (DR5000)
|
||||
lastCV ^= 0x55;
|
||||
getResultsSM = false;
|
||||
CVdata = rxBufferXN[DATA3];
|
||||
progFinished = true;
|
||||
}
|
||||
break;
|
||||
case 0x21: // Command station software version (0x63,0x21,VER,ID,XOR)
|
||||
xnetVersion = rxBufferXN[DATA2];
|
||||
xnetCS = rxBufferXN[DATA3];
|
||||
if (xnetCS == 0x10)
|
||||
askMultimaus = true;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0xE3:
|
||||
if (rxBufferXN[DATA1] == 0x40) { // Locomotive is being operated by another device response (0xE3,0x40,ADRH,ADRL,XOR)
|
||||
adr = addrXnet(locoData[myLocoData].myAddr.address);
|
||||
if ((rxBufferXN[DATA3] == lowByte(adr)) && (rxBufferXN[DATA2] == highByte(adr))) { // DR5000 workaround
|
||||
bitSet(locoData[myLocoData].mySteps, 3);
|
||||
}
|
||||
}
|
||||
if (rxBufferXN[DATA1] == 0x52) { // Locomotive function info F13..F28 (0xE3,0x52,FNC,FNC,XOR)
|
||||
locoData[myLocoData].myFunc.Bits &= 0xE0001FFF;
|
||||
locoData[myLocoData].myFunc.Bits |= ((unsigned long)rxBufferXN[DATA2] << 13);
|
||||
locoData[myLocoData].myFunc.Bits |= ((unsigned long)rxBufferXN[DATA3] << 21);
|
||||
updateFuncState(isWindow(WIN_THROTTLE));
|
||||
}
|
||||
break;
|
||||
case 0xE4:
|
||||
if ((rxBufferXN[DATA1] & 0xF0) == 0x00) { // Locomotive information normal locomotive (0xE4,ID,SPD,FKTA,FKTB,XOR)
|
||||
locoData[myLocoData].mySteps = rxBufferXN[DATA1]; // '0000BFFF'
|
||||
locoData[myLocoData].myDir = rxBufferXN[DATA2] & 0x80; // 'RVVVVVVV'
|
||||
locoData[myLocoData].mySpeed = rxBufferXN[DATA2] & 0x7F;
|
||||
locoData[myLocoData].myFunc.Bits &= 0xFFFFE000; // '000FFFFF','FFFFFFFF'
|
||||
locoData[myLocoData].myFunc.Bits |= ((unsigned long)rxBufferXN[DATA4] << 5);
|
||||
locoData[myLocoData].myFunc.xFunc[0] |= ((rxBufferXN[DATA3] & 0x0F) << 1);
|
||||
bitWrite(locoData[myLocoData].myFunc.xFunc[0], 0, bitRead(rxBufferXN[DATA3], 4));
|
||||
updateFuncState(isWindow(WIN_THROTTLE));
|
||||
if (isWindow(WIN_THROTTLE) || isWindow(WIN_SPEEDO))
|
||||
updateSpeedHID();
|
||||
}
|
||||
break;
|
||||
case 0xE7:
|
||||
if ((rxBufferXN[DATA1] & 0xF0) == 0x00) { // Locomotive function info F13..F20 MM (0xE7,STP,SPD,FNC,FNC,FNC,0x00,0x00,XOR)
|
||||
locoData[myLocoData].mySteps = rxBufferXN[DATA1]; // '0000BFFF'
|
||||
locoData[myLocoData].myDir = rxBufferXN[DATA2] & 0x80; // 'RVVVVVVV'
|
||||
locoData[myLocoData].mySpeed = rxBufferXN[DATA2] & 0x7F;
|
||||
locoData[myLocoData].myFunc.Bits &= 0xFE00000;
|
||||
locoData[myLocoData].myFunc.Bits |= ((unsigned long)rxBufferXN[DATA5] << 13);
|
||||
locoData[myLocoData].myFunc.Bits |= ((unsigned long)rxBufferXN[DATA4] << 5);
|
||||
locoData[myLocoData].myFunc.xFunc[0] |= ((rxBufferXN[DATA3] & 0x0F) << 1);
|
||||
bitWrite(locoData[myLocoData].myFunc.xFunc[0], 0, bitRead(rxBufferXN[DATA3], 4));
|
||||
updateFuncState(isWindow(WIN_THROTTLE));
|
||||
if (isWindow(WIN_THROTTLE) || isWindow(WIN_SPEEDO))
|
||||
updateSpeedHID();
|
||||
}
|
||||
break;
|
||||
case 0xF3:
|
||||
if (rxBufferXN[DATA1] == 0x0A) { // Multimaus firmware version (0xF3,0x0A,VERH,VERL,XOR)
|
||||
highVerMM = rxBufferXN[DATA2];
|
||||
lowVerMM = rxBufferXN[DATA3];
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if ((rxBufferXN[HEADER] & 0xF0) == 0x40) { // Feedback broadcast / Accessory decoder information response (0x4X,MOD,DATA,...,XOR)
|
||||
/*
|
||||
for (n = HEADER; n < (rxBytes - 2); n += 2) {
|
||||
modulo = rxBufferXN[n + 1];
|
||||
dato = rxBufferXN[n + 2];
|
||||
if (modulo == miModulo) { // Si es mi desvio guarda su posicion
|
||||
if (bitRead(dato, 4) == bitRead(miAccPos, 1)) {
|
||||
if (bitRead(miAccPos, 0))
|
||||
myPosTurnout = (dato >> 2) & 0x03;
|
||||
else
|
||||
myPosTurnout = dato & 0x03;
|
||||
if (scrOLED == SCR_TURNOUT)
|
||||
updateOLED = true;
|
||||
}
|
||||
}
|
||||
#ifdef USE_AUTOMATION
|
||||
for (byte n = 0; n < MAX_AUTO_SEQ; n++) {
|
||||
if ((automation[n].opcode & OPC_AUTO_MASK) == OPC_AUTO_FBK) {
|
||||
if (modulo == automation[n].param) {
|
||||
unsigned int nibble = (dato & 0x10) ? 0x0F : 0xF0;
|
||||
automation[n].value &= nibble;
|
||||
nibble = (dato & 0x10) ? (dato << 4) : (dato & 0x0F);
|
||||
automation[n].value |= nibble;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
modulo++;
|
||||
if (modulo == Shuttle.moduleA) // shuttle contacts
|
||||
updateShuttleStatus(&Shuttle.statusA, dato);
|
||||
if (modulo == Shuttle.moduleB)
|
||||
updateShuttleStatus(&Shuttle.statusB, dato);
|
||||
}
|
||||
*/
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
581
PacoMouseCYD/src/PacoMouseCYD/z21.ino
Normal file
@@ -0,0 +1,581 @@
|
||||
/* PacoMouseCYD throttle -- F. Cañada 2025-2026 -- https://usuaris.tinet.cat/fmco/
|
||||
|
||||
This software and associated files are a DIY project that is not intended for commercial use.
|
||||
This software uses libraries with different licenses, follow all their different terms included.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED.
|
||||
|
||||
Sources are only provided for building and uploading to the device.
|
||||
You are not allowed to modify the source code or fork/publish this project.
|
||||
Commercial use is forbidden.
|
||||
*/
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// ***** Z21 SOPORTE *****
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
void readCVZ21 (unsigned int adr, byte stepPrg) {
|
||||
if (!modeProg) {
|
||||
askZ21begin (LAN_X_Header);
|
||||
askZ21data (0x23);
|
||||
askZ21data (0x11);
|
||||
adr--;
|
||||
askZ21data ((adr >> 8) & 0xFF);
|
||||
askZ21data (adr & 0xFF);
|
||||
askZ21xor ();
|
||||
sendUDP (0x09);
|
||||
waitResultCV = true;
|
||||
lastCV = lowByte(adr);
|
||||
progStepCV = stepPrg;
|
||||
DEBUG_MSG("Read CV %d", adr + 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void writeCVZ21 (unsigned int adr, unsigned int data, byte stepPrg) {
|
||||
byte Adr_MSB;
|
||||
if (modeProg) {
|
||||
askZ21begin (LAN_X_Header);
|
||||
askZ21data (0xE6);
|
||||
askZ21data (0x30);
|
||||
Adr_MSB = locoData[myLocoData].myAddr.adr[1] & 0x3F;
|
||||
if (locoData[myLocoData].myAddr.address & 0x3F80)
|
||||
Adr_MSB |= 0xC0;
|
||||
askZ21data (Adr_MSB);
|
||||
askZ21data (locoData[myLocoData].myAddr.adr[0]);
|
||||
adr--;
|
||||
askZ21data (0xEC | ((adr >> 8) & 0x03));
|
||||
askZ21data (adr & 0xFF);
|
||||
askZ21data (data);
|
||||
askZ21xor ();
|
||||
sendUDP (0x0C);
|
||||
}
|
||||
else {
|
||||
askZ21begin (LAN_X_Header);
|
||||
askZ21data (0x24);
|
||||
askZ21data (0x12);
|
||||
adr--;
|
||||
askZ21data ((adr >> 8) & 0xFF);
|
||||
askZ21data (adr & 0xFF);
|
||||
askZ21data (data);
|
||||
askZ21xor ();
|
||||
sendUDP (0x0A);
|
||||
waitResultCV = true;
|
||||
lastCV = lowByte(adr);
|
||||
|
||||
}
|
||||
progStepCV = stepPrg;
|
||||
DEBUG_MSG("Write CV%d = %d", adr + 1, data);
|
||||
}
|
||||
|
||||
|
||||
void showErrorZ21() { // muestra pantalla de error
|
||||
if (csStatus & csTrackVoltageOff) {
|
||||
iconData[ICON_POWER].color = COLOR_RED;
|
||||
setTimer (TMR_POWER, 5, TMR_PERIODIC); // Flash power icon
|
||||
if ((isWindow(WIN_THROTTLE)) || (isWindow(WIN_STEAM)))
|
||||
newEvent(OBJ_ICON, ICON_POWER, EVNT_DRAW);
|
||||
if (isWindow(WIN_STA_PLAY)) {
|
||||
fncData[FNC_STA_RAYO].state = true;
|
||||
newEvent(OBJ_FNC, FNC_STA_RAYO, EVNT_DRAW);
|
||||
}
|
||||
}
|
||||
if (csStatus & csProgrammingModeActive) {
|
||||
if ((isWindow(WIN_THROTTLE)) || (isWindow(WIN_STEAM)))
|
||||
alertWindow(ERR_SERV);
|
||||
}
|
||||
if (csStatus & csEmergencyStop) {
|
||||
if ((isWindow(WIN_THROTTLE)) || (isWindow(WIN_STEAM)))
|
||||
alertWindow(ERR_STOP);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void showNormalOpsZ21() {
|
||||
stopTimer (TMR_POWER);
|
||||
iconData[ICON_POWER].color = COLOR_GREEN;
|
||||
if ((isWindow(WIN_THROTTLE)) || (isWindow(WIN_STEAM)))
|
||||
newEvent(OBJ_ICON, ICON_POWER, EVNT_DRAW);
|
||||
if (isWindow(WIN_STA_PLAY)) {
|
||||
fncData[FNC_STA_RAYO].state = false;
|
||||
newEvent(OBJ_FNC, FNC_STA_RAYO, EVNT_DRAW);
|
||||
}
|
||||
if (isWindow(WIN_ALERT)) {
|
||||
switch (errType) {
|
||||
case ERR_SERV:
|
||||
case ERR_STOP:
|
||||
case ERR_CV:
|
||||
closeWindow(WIN_ALERT);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void setTimeZ21(byte hh, byte mm, byte rate) {
|
||||
clockHour = hh;
|
||||
clockMin = mm;
|
||||
clockRate = rate;
|
||||
askZ21begin (LAN_FAST_CLOCK_CONTROL); // set clock
|
||||
if (rate > 0) {
|
||||
askZ21data (0x24);
|
||||
askZ21data (0x2B);
|
||||
askZ21data (hh);
|
||||
askZ21data (mm);
|
||||
askZ21data (rate);
|
||||
askZ21xor ();
|
||||
sendUDP (0x0A);
|
||||
askZ21begin (LAN_FAST_CLOCK_CONTROL);
|
||||
askZ21data (0x21); // start clock
|
||||
askZ21data (0x2C);
|
||||
askZ21xor ();
|
||||
sendUDP (0x07);
|
||||
}
|
||||
else {
|
||||
askZ21data (0x21); // recommended for rate=0. stop clock
|
||||
askZ21data (0x2D);
|
||||
askZ21xor ();
|
||||
sendUDP (0x07);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// ***** Z21 DECODE *****
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
void processZ21() {
|
||||
int len, packetSize;
|
||||
|
||||
packetSize = Udp.parsePacket(); // z21 UDP packet
|
||||
if (packetSize) {
|
||||
len = Udp.read(packetBuffer, packetSize); // read the packet into packetBufffer
|
||||
ReceiveZ21 (len, packetBuffer); // decode received packet
|
||||
}
|
||||
delay(0);
|
||||
if (millis() - infoTimer > 1000UL) { // Cada segundo
|
||||
infoTimer = millis();
|
||||
pingTimer++;
|
||||
if (pingTimer >= Z21_PING_INTERVAL) {
|
||||
pingTimer = 0;
|
||||
if (!(csStatus & csProgrammingModeActive))
|
||||
getStatusZ21();
|
||||
}
|
||||
/*
|
||||
battery = ESP.getVcc (); // Read VCC voltage
|
||||
if (battery < LowBattADC)
|
||||
lowBATT = true;
|
||||
*/
|
||||
}
|
||||
if (progFinished) { // fin de lectura/programacion CV
|
||||
progFinished = false;
|
||||
endProg();
|
||||
}
|
||||
delay(0);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------------------
|
||||
|
||||
void setBroadcastFlags (unsigned long bFlags) {
|
||||
askZ21begin (LAN_SET_BROADCASTFLAGS);
|
||||
askZ21data (bFlags & 0xFF);
|
||||
askZ21data ((bFlags >> 8) & 0xFF);
|
||||
askZ21data ((bFlags >> 16) & 0xFF);
|
||||
askZ21data ((bFlags >> 24) & 0xFF);
|
||||
sendUDP (0x08);
|
||||
}
|
||||
|
||||
void resumeOperationsZ21 () { // LAN_X_SET_TRACK_POWER_ON
|
||||
askZ21begin (LAN_X_Header);
|
||||
askZ21data (0x21);
|
||||
askZ21data (0x81);
|
||||
askZ21xor ();
|
||||
sendUDP (0x07);
|
||||
}
|
||||
|
||||
|
||||
void emergencyOffZ21() { // LAN_X_SET_TRACK_POWER_OFF
|
||||
askZ21begin (LAN_X_Header);
|
||||
askZ21data (0x21);
|
||||
askZ21data (0x80);
|
||||
askZ21xor ();
|
||||
sendUDP (0x07);
|
||||
}
|
||||
|
||||
|
||||
void getStatusZ21 () {
|
||||
askZ21begin (LAN_X_Header);
|
||||
askZ21data (0x21);
|
||||
askZ21data (0x24);
|
||||
askZ21xor ();
|
||||
sendUDP (0x07);
|
||||
}
|
||||
|
||||
void getSerialNumber () {
|
||||
askZ21begin (LAN_GET_SERIAL_NUMBER);
|
||||
sendUDP (0x04);
|
||||
}
|
||||
|
||||
void infoLocomotoraZ21 (unsigned int Adr) {
|
||||
byte Adr_MSB;
|
||||
askZ21begin (LAN_X_Header);
|
||||
askZ21data (0xE3);
|
||||
askZ21data (0xF0);
|
||||
Adr_MSB = (Adr >> 8) & 0x3F;
|
||||
if (Adr & 0x3F80)
|
||||
Adr_MSB |= 0xC0;
|
||||
askZ21data (Adr_MSB);
|
||||
askZ21data (Adr & 0xFF);
|
||||
askZ21xor ();
|
||||
sendUDP (0x09);
|
||||
}
|
||||
|
||||
void locoOperationSpeedZ21() {
|
||||
byte Adr_MSB;
|
||||
DEBUG_MSG("Loco Operations")
|
||||
askZ21begin (LAN_X_Header);
|
||||
askZ21data (0xE4);
|
||||
if (bitRead(locoData[myLocoData].mySteps, 2)) { // 128 steps
|
||||
askZ21data (0x13);
|
||||
}
|
||||
else {
|
||||
if (bitRead(locoData[myLocoData].mySteps, 1)) { // 28 steps
|
||||
askZ21data (0x12);
|
||||
}
|
||||
else {
|
||||
askZ21data (0x10); // 14 steps
|
||||
}
|
||||
}
|
||||
Adr_MSB = locoData[myLocoData].myAddr.adr[1] & 0x3F;
|
||||
if (locoData[myLocoData].myAddr.address & 0x3F80)
|
||||
Adr_MSB |= 0xC0;
|
||||
askZ21data (Adr_MSB);
|
||||
askZ21data (locoData[myLocoData].myAddr.adr[0]);
|
||||
askZ21data (locoData[myLocoData].mySpeed | locoData[myLocoData].myDir);
|
||||
askZ21xor ();
|
||||
sendUDP (0x0A);
|
||||
bitClear(locoData[myLocoData].mySteps, 3); // currently operated by me
|
||||
updateSpeedDir();
|
||||
}
|
||||
|
||||
|
||||
byte getCurrentStepZ21() {
|
||||
byte currStep;
|
||||
DEBUG_MSG("Get Steps: %02X - Speed: %02X", locoData[myLocoData].mySteps, locoData[myLocoData].mySpeed);
|
||||
if (bitRead(locoData[myLocoData].mySteps, 2)) { // 128 steps -> 0..126
|
||||
if (locoData[myLocoData].mySpeed > 1)
|
||||
return (locoData[myLocoData].mySpeed - 1);
|
||||
}
|
||||
else {
|
||||
if (bitRead(locoData[myLocoData].mySteps, 1)) { // 28 steps -> 0..28 '---04321' -> '---43210'
|
||||
currStep = (locoData[myLocoData].mySpeed << 1) & 0x1F;
|
||||
bitWrite(currStep, 0, bitRead(locoData[myLocoData].mySpeed, 4));
|
||||
if (currStep > 3)
|
||||
return (currStep - 3);
|
||||
}
|
||||
else { // 14 steps -> 0..14
|
||||
if (locoData[myLocoData].mySpeed > 1)
|
||||
return (locoData[myLocoData].mySpeed - 1);
|
||||
}
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
void funcOperationsZ21 (byte fnc) {
|
||||
byte Adr_MSB;
|
||||
askZ21begin (LAN_X_Header);
|
||||
askZ21data (0xE4);
|
||||
askZ21data (0xF8);
|
||||
Adr_MSB = locoData[myLocoData].myAddr.adr[1] & 0x3F;
|
||||
if (locoData[myLocoData].myAddr.address & 0x3F80)
|
||||
Adr_MSB |= 0xC0;
|
||||
askZ21data (Adr_MSB);
|
||||
askZ21data (locoData[myLocoData].myAddr.adr[0]);
|
||||
if (bitRead(locoData[myLocoData].myFunc.Bits, fnc))
|
||||
askZ21data (fnc | 0x40);
|
||||
else
|
||||
askZ21data (fnc);
|
||||
askZ21xor ();
|
||||
sendUDP (0x0A);
|
||||
bitClear(locoData[myLocoData].mySteps, 3); // currently operated by me
|
||||
}
|
||||
|
||||
|
||||
void infoDesvio (unsigned int FAdr) {
|
||||
FAdr--;
|
||||
askZ21begin (LAN_X_Header);
|
||||
askZ21data (0x43);
|
||||
askZ21data ((FAdr >> 8) & 0xFF);
|
||||
askZ21data (FAdr & 0xFF);
|
||||
askZ21xor ();
|
||||
sendUDP (0x08);
|
||||
}
|
||||
|
||||
|
||||
void setAccessoryZ21 (unsigned int FAdr, int pair, bool active) {
|
||||
byte db2;
|
||||
FAdr--;
|
||||
askZ21begin (LAN_X_Header);
|
||||
askZ21data (0x53);
|
||||
askZ21data ((FAdr >> 8) & 0xFF);
|
||||
askZ21data (FAdr & 0xFF);
|
||||
db2 = active ? 0x88 : 0x80;
|
||||
if (pair > 0)
|
||||
db2 |= 0x01;
|
||||
askZ21data (db2); // '10Q0A00P'
|
||||
askZ21xor ();
|
||||
sendUDP (0x09);
|
||||
}
|
||||
|
||||
|
||||
void getFeedbackInfo (byte group) {
|
||||
askZ21begin (LAN_RMBUS_GETDATA);
|
||||
askZ21data (group);
|
||||
sendUDP (0x05);
|
||||
}
|
||||
|
||||
|
||||
void ReceiveZ21 (int len, byte * packet) { // get UDP packet, maybe more than one!!
|
||||
int DataLen, isPacket;
|
||||
#ifdef DEBUG____X
|
||||
Serial.print("\nRX Length: ");
|
||||
Serial.println (len);
|
||||
for (int i = 0; i < len; i++) {
|
||||
Serial.print(packet[i], HEX);
|
||||
Serial.print(" ");
|
||||
}
|
||||
Serial.println();
|
||||
#endif
|
||||
isPacket = 1;
|
||||
while (isPacket) {
|
||||
DataLen = (packet[DATA_LENH] << 8) + packet[DATA_LENL];
|
||||
DecodeZ21 (DataLen, packet);
|
||||
if (DataLen >= len) {
|
||||
isPacket = 0;
|
||||
}
|
||||
else {
|
||||
packet = packet + DataLen;
|
||||
len = len - DataLen;
|
||||
}
|
||||
delay(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DecodeZ21 (int len, byte * packet) { // decode z21 UDP packets
|
||||
int Header, DataLen;
|
||||
unsigned int FAdr;
|
||||
byte group;
|
||||
|
||||
Header = (packet[DATA_HEADERH] << 8) + packet[DATA_HEADERL];
|
||||
switch (Header) {
|
||||
case LAN_GET_SERIAL_NUMBER:
|
||||
break;
|
||||
case LAN_GET_CODE: // FW 1.28
|
||||
break;
|
||||
case LAN_GET_HWINFO:
|
||||
break;
|
||||
case LAN_GET_BROADCASTFLAGS:
|
||||
break;
|
||||
case LAN_GET_LOCOMODE:
|
||||
break;
|
||||
case LAN_GET_TURNOUTMODE:
|
||||
break;
|
||||
case LAN_RMBUS_DATACHANGED:
|
||||
/*
|
||||
if (Shuttle.moduleA > 0) { // only check shuttle contacts
|
||||
if ((packet[4] == 0x01) && (Shuttle.moduleA > 10))
|
||||
Shuttle.statusA = packet[Shuttle.moduleA - 6];
|
||||
if ((packet[4] == 0x00) && (Shuttle.moduleA < 11))
|
||||
Shuttle.statusA = packet[Shuttle.moduleA + 4];
|
||||
}
|
||||
if (Shuttle.moduleB > 0) {
|
||||
if ((packet[4] == 0x01) && (Shuttle.moduleB > 10))
|
||||
Shuttle.statusB = packet[Shuttle.moduleB - 6];
|
||||
if ((packet[4] == 0x00) && (Shuttle.moduleB < 11))
|
||||
Shuttle.statusB = packet[Shuttle.moduleB + 4];
|
||||
}
|
||||
#ifdef USE_AUTOMATION
|
||||
for (byte n = 0; n < MAX_AUTO_SEQ; n++) {
|
||||
if ((automation[n].opcode & OPC_AUTO_MASK) == OPC_AUTO_FBK) {
|
||||
if ((packet[4] == 0x01) && (automation[n].param > 9))
|
||||
automation[n].value = packet[automation[n].param - 5];
|
||||
if ((packet[4] == 0x00) && (automation[n].param < 10))
|
||||
automation[n].value = packet[automation[n].param + 5];
|
||||
DEBUG_MSG("RBUS %d", automation[n].value)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
*/
|
||||
break;
|
||||
case LAN_SYSTEMSTATE_DATACHANGED:
|
||||
csStatus = packet[16] & (csEmergencyStop | csTrackVoltageOff | csProgrammingModeActive); // CentralState
|
||||
if (packet[16] & csShortCircuit)
|
||||
csStatus |= csTrackVoltageOff;
|
||||
break;
|
||||
case LAN_RAILCOM_DATACHANGED:
|
||||
break;
|
||||
|
||||
case LAN_LOCONET_Z21_TX: // a message has been written to the LocoNet bus by the Z21.
|
||||
case LAN_LOCONET_Z21_RX: // a message has been received by the Z21 from the LocoNet bus.
|
||||
case LAN_LOCONET_FROM_LAN: // another LAN client has written a message to the LocoNet bus via the Z21.
|
||||
switch (packet[4]) {
|
||||
case 0x83:
|
||||
csStatus = csNormalOps; // OPC_GPON
|
||||
showNormalOpsZ21();
|
||||
break;
|
||||
case 0x82:
|
||||
csStatus |= csTrackVoltageOff; // OPC_GPOFF
|
||||
showErrorZ21();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case LAN_LOCONET_DETECTOR:
|
||||
break;
|
||||
case LAN_FAST_CLOCK_DATA: // fast clock data FW 1.43
|
||||
if (packet[8] & 0x80) { // Stop flag
|
||||
clockRate = 0;
|
||||
}
|
||||
else {
|
||||
clockHour = packet[6] & 0x1F;
|
||||
clockMin = packet[7] & 0x3F;
|
||||
clockRate = packet[9] & 0x3F;
|
||||
updateFastClock();
|
||||
}
|
||||
DEBUG_MSG("Clock: %d:%d %d", clockHour, clockMin, clockRate);
|
||||
break;
|
||||
|
||||
case LAN_X_Header:
|
||||
switch (packet[XHEADER]) {
|
||||
case 0x43: // LAN_X_TURNOUT_INFO
|
||||
FAdr = (packet[DB0] << 8) + packet[DB1] + 1;
|
||||
/*
|
||||
if (FAdr == myTurnout) {
|
||||
myPosTurnout = packet[DB2] & 0x03;
|
||||
if (scrOLED == SCR_TURNOUT)
|
||||
updateOLED = true;
|
||||
}
|
||||
*/
|
||||
break;
|
||||
case 0x61:
|
||||
switch (packet[DB0]) {
|
||||
case 0x01: // LAN_X_BC_TRACK_POWER_ON
|
||||
csStatus = csNormalOps;
|
||||
showNormalOpsZ21();
|
||||
break;
|
||||
case 0x08: // LAN_X_BC_TRACK_SHORT_CIRCUIT
|
||||
csStatus |= csShortCircuit;
|
||||
case 0x00: // LAN_X_BC_TRACK_POWER_OFF
|
||||
csStatus |= csTrackVoltageOff;
|
||||
showErrorZ21();
|
||||
break;
|
||||
case 0x02: // LAN_X_BC_PROGRAMMING_MODE
|
||||
csStatus |= csProgrammingModeActive;
|
||||
if (!waitResultCV)
|
||||
showErrorZ21();
|
||||
break;
|
||||
case 0x12: // LAN_X_CV_NACK_SC
|
||||
case 0x13: // LAN_X_CV_NACK
|
||||
CVdata = 0x0600;
|
||||
waitResultCV = false;
|
||||
progFinished = true;
|
||||
break;
|
||||
case 0x82: // LAN_X_UNKNOWN_COMMAND
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0x62:
|
||||
switch (packet[DB0]) {
|
||||
case 0x22: // LAN_X_STATUS_CHANGED
|
||||
csStatus = packet[DB1] & (csEmergencyStop | csTrackVoltageOff | csProgrammingModeActive);
|
||||
if (packet[DB1] & csShortCircuit)
|
||||
csStatus |= csTrackVoltageOff;
|
||||
if (csStatus == csNormalOps)
|
||||
showNormalOpsZ21();
|
||||
else
|
||||
showErrorZ21();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0x64:
|
||||
if (packet[DB0] == 0x14) { // LAN_X_CV_RESULT
|
||||
if (packet[DB2] == lastCV) {
|
||||
lastCV ^= 0x55;
|
||||
CVdata = packet[DB3];
|
||||
waitResultCV = false;
|
||||
progFinished = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0x81:
|
||||
if (packet[DB0] == 0) { // LAN_X_BC_STOPPED
|
||||
csStatus |= csEmergencyStop;
|
||||
showErrorZ21();
|
||||
}
|
||||
break;
|
||||
case 0xEF: // LAN_X_LOCO_INFO
|
||||
DEBUG_MSG("RX: Loco data")
|
||||
FAdr = ((packet[DB0] << 8) + packet[DB1]) & 0x3FFF;
|
||||
if (FAdr == locoData[myLocoData].myAddr.address) {
|
||||
locoData[myLocoData].mySteps = packet[DB2]; // '0000BFFF'
|
||||
locoData[myLocoData].myDir = packet[DB3] & 0x80; // 'RVVVVVVV'
|
||||
locoData[myLocoData].mySpeed = packet[DB3] & 0x7F;
|
||||
locoData[myLocoData].myFunc.Bits &= 0xE0000000; // '000FFFFF','FFFFFFFF'
|
||||
locoData[myLocoData].myFunc.xFunc[0] |= ((packet[DB4] & 0x0F) << 1);
|
||||
bitWrite(locoData[myLocoData].myFunc.xFunc[0], 0, bitRead(packet[DB4], 4));
|
||||
locoData[myLocoData].myFunc.Bits |= (unsigned long)(packet[DB5] << 5);
|
||||
locoData[myLocoData].myFunc.Bits |= (unsigned long)(packet[DB6] << 13);
|
||||
locoData[myLocoData].myFunc.Bits |= (unsigned long)(packet[DB7] << 21);
|
||||
updateFuncState(isWindow(WIN_THROTTLE));
|
||||
if (isWindow(WIN_THROTTLE) || isWindow(WIN_SPEEDO))
|
||||
updateSpeedHID(); // set encoder
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default: // Header other
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void askZ21begin (unsigned int header) {
|
||||
OutData[DATA_HEADERL] = header & 0xFF;
|
||||
OutData[DATA_HEADERH] = header >> 8;
|
||||
OutPos = XHEADER;
|
||||
OutXOR = 0;
|
||||
}
|
||||
|
||||
|
||||
void askZ21data (byte data) {
|
||||
OutData[OutPos++] = data;
|
||||
OutXOR ^= data;
|
||||
}
|
||||
|
||||
void askZ21xor () {
|
||||
OutData[OutPos] = OutXOR;
|
||||
}
|
||||
|
||||
|
||||
void sendUDP (int len) {
|
||||
OutData[DATA_LENL] = len & 0xFF;
|
||||
OutData[DATA_LENH] = len >> 8;
|
||||
Udp.beginPacket(wifiSetting.CS_IP, z21Port);
|
||||
Udp.write(OutData, len);
|
||||
Udp.endPacket();
|
||||
delay(0);
|
||||
#ifdef DEBUG___X
|
||||
Serial.print("TX: ");
|
||||
for (int i = 0; i < len; i++) {
|
||||
Serial.print(OutData[i], HEX);
|
||||
Serial.print(" ");
|
||||
}
|
||||
Serial.println();
|
||||
#endif
|
||||
}
|
||||