Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 435dbe67d9 | |||
|
|
eb13bb7bf4 | ||
|
|
ea894db82d | ||
|
|
758e35ba42 | ||
|
|
4f63998766 | ||
|
|
cd8f382ed4 |
114
README.md
Normal file
@@ -0,0 +1,114 @@
|
||||
# Introduction
|
||||
|
||||
This is the source files folder for the EasyDccMouse.
|
||||
|
||||
EasyDccMouse is a system to remote control DCC scale locomotive, it is based on a ESP32 with tft display, touch screen, encoder and battery.
|
||||
|
||||
EasyDccMouse sends actions to a DCC centrale station.
|
||||
|
||||
|
||||
```
|
||||
+------------------------------------------------------+
|
||||
| [O] [⇄] [ID] [⚡] | <-- Header with 4 icons:
|
||||
| ON Dir DCC Power | [O] Status (ON/OFF)
|
||||
| | [⇄] Direction (Forward/Reverse)
|
||||
| [================== Train ===================] | [ID] DCC id
|
||||
| | [⚡] Power/Connection
|
||||
| |██████████████████████████████████████████| | <-- Model picture (190x40 px)
|
||||
| |
|
||||
| ___ |
|
||||
| .-' '-. |
|
||||
| .' '. |
|
||||
| / \ |
|
||||
| | /\ /\ | | <-- Speedometer (arc + needle)
|
||||
| | / \ / \ | |
|
||||
| | / \_/ \ | |
|
||||
| |/ \| |
|
||||
| '---------------' |
|
||||
| | | |
|
||||
| | | |
|
||||
| Needle |
|
||||
| |
|
||||
| [F1] [F2] [F3] [F4] [F5] [F6] [F7] [F8] | <-- Function pad (row 1)
|
||||
| [F9] [F10][F11][F12][F13][F14][F15][F16] | <-- Function pad (row 2)
|
||||
+------------------------------------------------------+
|
||||
```
|
||||
|
||||
# Implementation
|
||||
|
||||
|
||||
## How to draw speedometer with arc and needle on my TFT display?
|
||||
|
||||
To draw an arc-style speedometer with a moving needle on your TFT display (e.g., ILI9341), you can use the TFT_eSPI library. Here’s a step-by-step example:
|
||||
|
||||
1. **Draw the arc:**
|
||||
- Use `drawArc()` or draw multiple short lines to approximate an arc.
|
||||
- Example: Draw an arc from 135° to 45° (like a semicircle at the bottom).
|
||||
|
||||
2. **Draw the needle:**
|
||||
- Calculate the angle for the needle based on the speed value.
|
||||
- Use `drawLine()` from the center of the arc to the edge at the calculated angle.
|
||||
|
||||
3. **Display the speed value:**
|
||||
- Use `setCursor()` and `print()` to show the numeric speed.
|
||||
|
||||
**Example code:**
|
||||
```cpp
|
||||
#include <TFT_eSPI.h>
|
||||
#include <math.h>
|
||||
|
||||
TFT_eSPI tft = TFT_eSPI();
|
||||
|
||||
void drawSpeedometer(int speed) {
|
||||
int cx = 120, cy = 120, r = 80; // Center and radius
|
||||
int minAngle = 135, maxAngle = 45; // Degrees
|
||||
int minSpeed = 0, maxSpeed = 100;
|
||||
|
||||
// Draw arc (approximate with lines)
|
||||
for (int a = minAngle; a >= maxAngle; a -= 3) {
|
||||
float rad = a * 3.14159 / 180.0;
|
||||
int x1 = cx + (r - 10) * cos(rad);
|
||||
int y1 = cy + (r - 10) * sin(rad);
|
||||
int x2 = cx + r * cos(rad);
|
||||
int y2 = cy + r * sin(rad);
|
||||
tft.drawLine(x1, y1, x2, y2, TFT_WHITE);
|
||||
}
|
||||
|
||||
// Draw needle
|
||||
float angle = minAngle - (float)(speed - minSpeed) / (maxSpeed - minSpeed) * (minAngle - maxAngle);
|
||||
float rad = angle * 3.14159 / 180.0;
|
||||
int nx = cx + (r - 20) * cos(rad);
|
||||
int ny = cy + (r - 20) * sin(rad);
|
||||
tft.drawLine(cx, cy, nx, ny, TFT_RED);
|
||||
|
||||
// Draw speed value
|
||||
tft.setCursor(cx - 20, cy + 30);
|
||||
tft.setTextColor(TFT_WHITE, TFT_BLACK);
|
||||
tft.setTextSize(2);
|
||||
tft.printf("%d", speed);
|
||||
}
|
||||
```
|
||||
|
||||
**Tips:**
|
||||
- Clear the previous needle before drawing a new one for smooth animation.
|
||||
- Adjust `cx`, `cy`, and `r` for your display size.
|
||||
- You can enhance the arc with tick marks and labels for a more realistic look.
|
||||
|
||||
|
||||
Hi,
|
||||
I’ve made an open-source graphics editor designed to help create visuals for TFT_eSPI, U8g2, AdafruitGFX, and ESPHome.
|
||||
|
||||
Pick the GUI library or platform you're using, choose your display size, and start building with visual tools — draw shapes, add text, and more. As you work, a code window below will auto-generate the source code you can copy into your project to reproduce the design.
|
||||
|
||||
You can import your own images and convert them into data arrays. There's also a built-in icon library to help you get started quickly.
|
||||
|
||||
It’s open source and community-supported: https://github.com/sbrin/lopaka
|
||||
The cloud version is live at https://lopaka.app
|
||||
|
||||
There’s even a gallery of editable screens and UI designs created by others, so you don’t have to start from scratch.
|
||||
|
||||
I'd love to hear your thoughts:
|
||||
– What do you think of the idea?
|
||||
– What features do you wish it had?
|
||||
|
||||
Your feedback is the best motivation to keep building!
|
||||
BIN
SD/Imgs/Init.bmp
Normal file
|
After Width: | Height: | Size: 150 KiB |
BIN
SD/Imgs/Init.xcf
Normal file
BIN
SD/Imgs/catalan.png
Normal file
|
After Width: | Height: | Size: 504 B |
BIN
SD/Imgs/deutsch.png
Normal file
|
After Width: | Height: | Size: 264 B |
BIN
SD/Imgs/english.png
Normal file
|
After Width: | Height: | Size: 635 B |
BIN
SD/Imgs/iconID0.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
SD/Imgs/iconID1.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
SD/Imgs/iconID10.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
SD/Imgs/iconID11.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
SD/Imgs/iconID12.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
SD/Imgs/iconID13.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
SD/Imgs/iconID14.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
SD/Imgs/iconID15.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
SD/Imgs/iconID16.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
SD/Imgs/iconID17.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
SD/Imgs/iconID18.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
SD/Imgs/iconID19.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
SD/Imgs/iconID2.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
SD/Imgs/iconID20.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
SD/Imgs/iconID21.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
SD/Imgs/iconID22.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
SD/Imgs/iconID23.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
SD/Imgs/iconID24.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
SD/Imgs/iconID25.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
SD/Imgs/iconID26.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
SD/Imgs/iconID27.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
SD/Imgs/iconID28.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
SD/Imgs/iconID29.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
SD/Imgs/iconID3.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
SD/Imgs/iconID30.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
SD/Imgs/iconID31.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
SD/Imgs/iconID32.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
SD/Imgs/iconID33.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
SD/Imgs/iconID34.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
SD/Imgs/iconID35.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
SD/Imgs/iconID36.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
SD/Imgs/iconID37.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
SD/Imgs/iconID38.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
SD/Imgs/iconID39.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
SD/Imgs/iconID4.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
SD/Imgs/iconID40.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
SD/Imgs/iconID5.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
SD/Imgs/iconID6.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
SD/Imgs/iconID7.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
SD/Imgs/iconID8.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
SD/Imgs/iconID9.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
SD/Imgs/paco.png
Normal file
|
After Width: | Height: | Size: 5.2 KiB |
BIN
SD/Imgs/spanish.png
Normal file
|
After Width: | Height: | Size: 271 B |
186
SD/LocoEditor.html
Normal file
@@ -0,0 +1,186 @@
|
||||
<html>
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head><meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
|
||||
<title>PacoMouseCYD Loco Editor</title>
|
||||
<link rel="stylesheet" href="css/style.css">
|
||||
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="headertxt">
|
||||
<b>PacoMouseCYD Loco Editor</b>
|
||||
</div>
|
||||
|
||||
<div class="dropdown dropdown-dark">
|
||||
<span lang="es"><img class='spanish'></span>
|
||||
<span lang="ca"><img class='catalan'></span>
|
||||
<span lang="en"><img class='english'></span>
|
||||
<span lang="de"><img class='deutsch'></span>
|
||||
|
||||
<select id="language-select" class="dropdown-select" onchange="changelanguage();">
|
||||
<option value="en">English</option>
|
||||
<option value="es">Castellano</option>
|
||||
<option value="de">Deutsch</option>
|
||||
<option value="ca">Català</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="labeltxt">
|
||||
<table border='0' cellspacing='0' cellpadding='3' width="100%">
|
||||
<tr><td>
|
||||
<span lang="es">Locomotora:</span>
|
||||
<span lang="ca">Locomotora:</span>
|
||||
<span lang="en">Locomotive:</span>
|
||||
<span lang="de">Lokomotive:</span>
|
||||
</td><td> <input type="text" id="NumLoco" class="texttxt" placeholder="?"></td></tr>
|
||||
<tr><td>
|
||||
|
||||
<span lang="es">Nombre:</span>
|
||||
<span lang="ca">Nom:</span>
|
||||
<span lang="en">Name:</span>
|
||||
<span lang="de">Name:</span>
|
||||
|
||||
</td><td> <input type="text" id="NameLoco" class="texttxt" ></td></tr>
|
||||
<tr><td>
|
||||
<span lang="es">Vel. max.:</span>
|
||||
<span lang="ca">Vel. max.:</span>
|
||||
<span lang="en">Speed max.:</span>
|
||||
<span lang="de">Geschw.max.:</span>
|
||||
</td><td> <input type="text" id="SpeedMax" class="texttxt"> km/h</td></tr>
|
||||
<tr><td><br></td></tr>
|
||||
<tr><td>
|
||||
<span lang="es">Archivo CSV:</span>
|
||||
<span lang="ca">Arxiu CSV:</span>
|
||||
<span lang="en">CSV File:</span>
|
||||
<span lang="de">CSV-Datei:</span>
|
||||
</td><td>loco/ <input type="file" id="fileToLoad" class="texttxt"></td> </tr>
|
||||
<tr><td></td><td><button class="buttontxt" onclick="loadFileAsText()">
|
||||
<span lang="es">Cargar ...</span>
|
||||
<span lang="ca">Carregar ...</span>
|
||||
<span lang="en">Load ...</span>
|
||||
<span lang="de">Laden ...</span>
|
||||
</button><td></tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="labeltxt">
|
||||
<table border='0' cellspacing='0' cellpadding='3' width="100%">
|
||||
<tr><td>
|
||||
<span lang="es">Imagen:</span>
|
||||
<span lang="ca">Imatge:</span>
|
||||
<span lang="en">Image:</span>
|
||||
<span lang="de">Bild:</span>
|
||||
</td><td> <input type="text" id="NumImage" class="texttxt" placeholder="?" onChange="changeImageLoco();"></td></tr>
|
||||
<tr><td><br><br><br></td><td><img src="image/0.bmp" id="imageToShow" width="190" height="40"></td></tr>
|
||||
<tr><td>
|
||||
<span lang="es">Archivo BMP:</span>
|
||||
<span lang="ca">Arxiu BMP:</span>
|
||||
<span lang="en">BMP File:</span>
|
||||
<span lang="de">BMP-Datei:</span>
|
||||
</td><td>image/ <input type="file" id="imageToLoad" class="texttxt"></td> </tr>
|
||||
<tr><td></td><td><button class="buttontxt" onclick="loadFileAsImage()">
|
||||
<span lang="es">Cargar ...</span>
|
||||
<span lang="ca">Carregar ...</span>
|
||||
<span lang="en">Load ...</span>
|
||||
<span lang="de">Laden ...</span>
|
||||
</button><td></tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="labeltxt">
|
||||
<span lang="es">Funciones:</span>
|
||||
<span lang="ca">Funcions:</span>
|
||||
<span lang="en">Functions:</span>
|
||||
<span lang="de">Funktionen:</span>
|
||||
<hr>
|
||||
<table>
|
||||
<tr><td>F0</td><td>F1</td><td>F2</td><td>F3</td><td>F4</td><td>F5</td><td>F6</td><td>F7</td><td>F8</td><td>F9</td></tr>
|
||||
<tr><td><img id="F0" class="iconID3" onClick="selectIcon(0);"></td><td><img id="F1" class="iconID2" onClick="selectIcon(1);"></td><td><img id="F2" class="iconID2" onClick="selectIcon(2);"></td>
|
||||
<td><img id="F3" class="iconID2" onClick="selectIcon(3);"></td><td><img id="F4" class="iconID2" onClick="selectIcon(4);"></td><td><img id="F5" class="iconID2" onClick="selectIcon(5);"></td>
|
||||
<td><img id="F6" class="iconID2" onClick="selectIcon(6);"></td><td><img id="F7" class="iconID2" onClick="selectIcon(7);"></td><td><img id="F8" class="iconID2" onClick="selectIcon(8);"></td>
|
||||
<td><img id="F9" class="iconID2" onClick="selectIcon(9);"></td></tr>
|
||||
<tr><td>F10</td><td>F11</td><td>F12</td><td>F13</td><td>F14</td><td>F15</td><td>F16</td><td>F17</td><td>F18</td><td>F19</td></tr>
|
||||
<tr><td><img id="F10" class="iconID2" onClick="selectIcon(10);"></td><td><img id="F11" class="iconID2" onClick="selectIcon(11);"></td><td><img id="F12" class="iconID2" onClick="selectIcon(12);"></td>
|
||||
<td><img id="F13" class="iconID2" onClick="selectIcon(13);"></td><td><img id="F14" class="iconID2" onClick="selectIcon(14);"></td><td><img id="F15" class="iconID2" onClick="selectIcon(15);"></td>
|
||||
<td><img id="F16" class="iconID2" onClick="selectIcon(16);"></td><td><img id="F17" class="iconID2" onClick="selectIcon(17);"></td><td><img id="F18" class="iconID2" onClick="selectIcon(18);"></td>
|
||||
<td><img id="F19" class="iconID2" onClick="selectIcon(19);"></td></tr>
|
||||
<tr><td>F20</td><td>F21</td><td>F22</td><td>F23</td><td>F24</td><td>F25</td><td>F26</td><td>F27</td><td>F28</td></tr>
|
||||
<tr><td><img id="F20" class="iconID2" onClick="selectIcon(20);"></td><td><img id="F21" class="iconID2" onClick="selectIcon(21);"></td><td><img id="F22" class="iconID2" onClick="selectIcon(22);"></td>
|
||||
<td><img id="F23" class="iconID2" onClick="selectIcon(23);"></td><td><img id="F24" class="iconID2" onClick="selectIcon(24);"></td><td><img id="F25" class="iconID2" onClick="selectIcon(25);"></td>
|
||||
<td><img id="F26" class="iconID2" onClick="selectIcon(26);"></td><td><img id="F27" class="iconID2" onClick="selectIcon(27);"></td><td><img id="F28" class="iconID2" onClick="selectIcon(28);"></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<div id="iconAll" style="display:none">
|
||||
<hr>
|
||||
<table>
|
||||
<tr><td>
|
||||
<span lang="es">Icono para</span>
|
||||
<span lang="ca">Icona per a</span>
|
||||
<span lang="en">Icon for</span>
|
||||
<span lang="de">Symbol für</span>
|
||||
</td><td id="Fx">F</td></tr>
|
||||
</table>
|
||||
<br>
|
||||
<table>
|
||||
<tr><td><img id="icon1" class="iconID1" onClick="updateIcon(1);"></td><td><img id="icon2" class="iconID2" onClick="updateIcon(2);"></td><td><img id="icon3" class="iconID3" onClick="updateIcon(3);"></td>
|
||||
<td><img id="icon4" class="iconID4" onClick="updateIcon(4);"></td><td><img id="icon5" class="iconID5" onClick="updateIcon(5);"></td><td><img id="icon6" class="iconID6" onClick="updateIcon(6);"></td>
|
||||
<td><img id="icon7" class="iconID7" onClick="updateIcon(7);"></td><td><img id="icon8" class="iconID8" onClick="updateIcon(8);"></td><td><img id="icon9" class="iconID9" onClick="updateIcon(9);"></td>
|
||||
<td><img id="icon10" class="iconID10" onClick="updateIcon(10);"></tr>
|
||||
|
||||
<tr><td><img id="icon11" class="iconID11" onClick="updateIcon(11);"></td><td><img id="icon12" class="iconID12" onClick="updateIcon(12);"></td><td><img id="icon13" class="iconID13" onClick="updateIcon(13);"></td>
|
||||
<td><img id="icon14" class="iconID14" onClick="updateIcon(14);"></td><td><img id="icon15" class="iconID15" onClick="updateIcon(15);"></td><td><img id="icon16" class="iconID16" onClick="updateIcon(16);"></td>
|
||||
<td><img id="icon17" class="iconID17" onClick="updateIcon(17);"></td><td><img id="icon18" class="iconID18" onClick="updateIcon(18);"></td><td><img id="icon19" class="iconID19" onClick="updateIcon(19);"></td>
|
||||
<td><img id="icon20" class="iconID20" onClick="updateIcon(20);"></tr>
|
||||
|
||||
<tr><td><img id="icon21" class="iconID21" onClick="updateIcon(21);"></td><td><img id="icon22" class="iconID22" onClick="updateIcon(22);"></td><td><img id="icon23" class="iconID23" onClick="updateIcon(23);"></td>
|
||||
<td><img id="icon24" class="iconID24" onClick="updateIcon(24);"></td><td><img id="icon25" class="iconID25" onClick="updateIcon(25);"></td><td><img id="icon26" class="iconID26" onClick="updateIcon(26);"></td>
|
||||
<td><img id="icon27" class="iconID27" onClick="updateIcon(27);"></td><td><img id="icon28" class="iconID28" onClick="updateIcon(28);"></td><td><img id="icon29" class="iconID29" onClick="updateIcon(29);"></td>
|
||||
<td><img id="icon30" class="iconID30" onClick="updateIcon(30);"></tr>
|
||||
|
||||
<tr><td><img id="icon31" class="iconID31" onClick="updateIcon(31);"></td><td><img id="icon32" class="iconID32" onClick="updateIcon(32);"></td><td><img id="icon33" class="iconID33" onClick="updateIcon(33);"></td>
|
||||
<td><img id="icon34" class="iconID34" onClick="updateIcon(34);"></td><td><img id="icon35" class="iconID35" onClick="updateIcon(35);"></td><td><img id="icon36" class="iconID36" onClick="updateIcon(36);"></td>
|
||||
<td><img id="icon37" class="iconID37" onClick="updateIcon(37);"></td><td><img id="icon38" class="iconID38" onClick="updateIcon(38);"></td><td><img id="icon39" class="iconID39" onClick="updateIcon(39);"></td>
|
||||
<td><img id="icon40" class="iconID40" onClick="updateIcon(40);"></tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="instruc" class="labeltxt" style="display:none">
|
||||
<center>
|
||||
<span lang="es">Copia el archivo .csv de la carpeta <b>Descargas</b> del ordenador a la carpeta <b>loco</b> de la SD</span>
|
||||
<span lang="ca">Copia el fitxer .csv de la carpeta <b>Descàrregues</b> de l'ordinador a la carpeta <b>loco</b> de la targeta SD</span>
|
||||
<span lang="en">Copy the .csv file from the <b>Downloads</b> folder on your computer to the <b>loco</b> folder on your SD card</span>
|
||||
<span lang="de">Kopieren Sie die .csv-Datei aus dem <b>Download</b>-Ordner auf Ihrem Computer in den Ordner <b>loco</b> auf Ihrer SD-Karte.</span>
|
||||
</center>
|
||||
</div>
|
||||
|
||||
<div id="saveCSV">
|
||||
<center>
|
||||
<table><tr>
|
||||
<td>
|
||||
<button class="buttontxt" style="font-size: 40px;padding: 20px 60px;" onclick="createTextCSV()">
|
||||
<span lang="es">Guardar ...</span>
|
||||
<span lang="ca">Desar ...</span>
|
||||
<span lang="en">Save ...</span>
|
||||
<span lang="de">Speichern ...</span>
|
||||
</button>
|
||||
</td><td>
|
||||
<img class='paco'>
|
||||
</td></tr>
|
||||
</table>
|
||||
</center>
|
||||
</div>
|
||||
|
||||
|
||||
<div style="display:none">
|
||||
<textarea id="inputTextToSave" cols="80" rows="5"></textarea>
|
||||
<input id="inputFileNameToSaveAs"></input>
|
||||
<input type="text" id="NumFunc" value="2" style="display:block">
|
||||
</div>
|
||||
|
||||
<script src="js/loco.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
18
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
|
||||
|
||||
|
36
SD/bgr565.html
Normal file
@@ -0,0 +1,36 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>BGR565 Inverted Image Converter</title>
|
||||
<link rel="stylesheet" href="css/bgr565.css">
|
||||
</head>
|
||||
<body>
|
||||
<h1>BGR565 Inverted Image Converter</h1>
|
||||
<form id="imageForm">
|
||||
<input type="file" id="imageInput" accept="image/*">
|
||||
<br>
|
||||
<label>Width: <input type="number" id="width" value="190" min="1"></label>
|
||||
<label>Height: <input type="number" id="height" value="40" min="1"></label>
|
||||
<button type="button" id="convertBtn">Convert & Download .raw</button>
|
||||
</form>
|
||||
<canvas id="canvas" style="display:none;"></canvas>
|
||||
<div id="preview"></div>
|
||||
<script src="js/bgr565.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
<!--
|
||||
How this tool works:
|
||||
1. Select an image file (any format supported by your browser).
|
||||
2. Set the desired width and height (default: 190x40).
|
||||
3. Click "Convert & Download .raw".
|
||||
4. The image is resized/cropped to the specified size, converted to inverted BGR565 format (matching your display), and a .raw file is downloaded.
|
||||
5. The .raw file can be copied to your SD card and displayed directly on your ESP32 with your display code.
|
||||
|
||||
Technical details:
|
||||
- Uses HTML5 Canvas to process the image in the browser.
|
||||
- JavaScript reads pixel data, converts to BGR565, inverts each value, and outputs a binary .raw file.
|
||||
- No data is uploaded; all processing is local in your browser.
|
||||
-->
|
||||
</html>
|
||||
</html>
|
||||
32
SD/css/bgr565.css
Normal file
@@ -0,0 +1,32 @@
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
margin: 2em;
|
||||
background: #f9f9f9;
|
||||
color: #222;
|
||||
}
|
||||
h1 {
|
||||
color: #005580;
|
||||
}
|
||||
form {
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
label {
|
||||
margin-right: 1em;
|
||||
}
|
||||
#preview img {
|
||||
max-width: 300px;
|
||||
border: 1px solid #ccc;
|
||||
margin-top: 1em;
|
||||
}
|
||||
button {
|
||||
padding: 0.5em 1em;
|
||||
font-size: 1em;
|
||||
background: #005580;
|
||||
color: #fff;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
}
|
||||
button:hover {
|
||||
background: #0077aa;
|
||||
}
|
||||
92
SD/css/style.css
Normal file
@@ -0,0 +1,92 @@
|
||||
html {
|
||||
font-family: Arial, Helvetica, sans-serif;
|
||||
display: inline-block;
|
||||
margin: 0px auto;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
|
||||
body {
|
||||
background-color: white;
|
||||
font-size: 25px;}
|
||||
|
||||
input.texttxt {
|
||||
font-size: 25px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
div.labeltxt {
|
||||
color: black;
|
||||
background-color: #B6B6B6;
|
||||
font-size: 25px;
|
||||
padding: 20px 20px;
|
||||
margin: 20px;
|
||||
text-align: left;
|
||||
border-radius: 10px;}
|
||||
|
||||
div.headertxt {
|
||||
color: white;
|
||||
background-color: blue;
|
||||
font-size: 25px;
|
||||
padding: 20px 200px;
|
||||
margin: 20px;
|
||||
text-align: center;
|
||||
border-radius: 10px;}
|
||||
|
||||
|
||||
|
||||
td {
|
||||
font-size: 25px;
|
||||
padding: 5px 10px
|
||||
}
|
||||
|
||||
button.buttontxt {
|
||||
background-color: #f48100;
|
||||
border: none;
|
||||
color: white;
|
||||
padding: 13px 10px
|
||||
text-decoration:none;
|
||||
font-size: 25px;
|
||||
margin: 0px auto 15px;
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
font-weight: bold;}
|
||||
|
||||
span[lang=es], span[lang=de], span[lang=ca], { display: none}
|
||||
|
||||
.dropdown {
|
||||
display: block;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
padding: 10px 10px;
|
||||
margin: 30px 50px;
|
||||
background: lightgrey;
|
||||
border: 1px solid;
|
||||
border-color: white;
|
||||
border-radius: 20px;
|
||||
-webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.08);
|
||||
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.08);}
|
||||
|
||||
|
||||
.dropdown-dark {
|
||||
background: lightgrey;
|
||||
border-color: lightgrey;
|
||||
-webkit-box-shadow: inset 0 1px rgba(255, 255, 255, 0.1), 0 1px 1px rgba(0, 0, 0, 0.2);
|
||||
box-shadow: inset 0 1px rgba(255, 255, 255, 0.1), 0 1px 1px rgba(0, 0, 0, 0.2);}
|
||||
|
||||
.dropdown-select {
|
||||
position: relative;
|
||||
width: 80%;
|
||||
margin: 20;
|
||||
padding: 20px 20px;
|
||||
line-height: 34px;
|
||||
font-size: 25px;
|
||||
color: black;
|
||||
text-shadow: 0 0px white;
|
||||
background: lightgrey; /* Fallback for IE 8 */
|
||||
background: rgba(0, 0, 0, 0) !important; /* "transparent" doesn't work with Opera */
|
||||
border: 0;
|
||||
border-radius: 0;
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
66
SD/extract_css_images.py
Normal file
@@ -0,0 +1,66 @@
|
||||
import re
|
||||
import os
|
||||
import base64
|
||||
|
||||
|
||||
CSS_FILE = os.path.join(os.path.dirname(__file__), 'css', 'style.css')
|
||||
OUTPUT_DIR = os.path.join(os.path.dirname(__file__), 'Imgs')
|
||||
|
||||
print(f"Reading CSS file: {CSS_FILE}")
|
||||
if not os.path.exists(OUTPUT_DIR):
|
||||
os.makedirs(OUTPUT_DIR)
|
||||
|
||||
with open(CSS_FILE, 'r') as f:
|
||||
css = f.read()
|
||||
print(f"First 1000 chars of CSS:\n{css[:1000]}")
|
||||
|
||||
# Regex to match: img.class { ... content: url(data:image/png;base64,....); ... }
|
||||
|
||||
# Loosened regex: match any img.class { ... content: url(data:image/...) ... } block, regardless of property order or spacing
|
||||
pattern = re.compile(
|
||||
r'img\\.([a-zA-Z0-9_]+)\\s*{{[^}}]*?content\s*:\s*url\\s*\\(\\s*data:image/(png|bmp|jpeg|jpg);base64,([A-Za-z0-9+/=]+)\\)[^}}]*}}',
|
||||
re.DOTALL)
|
||||
|
||||
matches = list(pattern.finditer(css))
|
||||
print(f"Found {len(matches)} images in CSS with main regex.")
|
||||
if len(matches) == 0:
|
||||
print("WARNING: No images found with main regex. Printing first and last 2000 chars of CSS for debug:")
|
||||
print("--- FIRST 2000 CHARS ---\n" + css[:2000])
|
||||
print("--- LAST 2000 CHARS ---\n" + css[-2000:])
|
||||
# Try to print a sample img.class block for debugging
|
||||
import re as _re
|
||||
# Print the exact img.class block containing 'content: url(data:image' for further debugging
|
||||
# Print the first img.class block with content:url for debug
|
||||
img_content_block = _re.search(r'(img\\.[a-zA-Z0-9_]+\\s*{{[^}}]*content\\s*:\\s*url\\s*\\(\\s*data:image/[^;]+;base64,([A-Za-z0-9+/=\\s]+)\\)[^}}]*}})', css, _re.DOTALL)
|
||||
if img_content_block:
|
||||
print("--- img.class BLOCK WITH BASE64 ---\n" + img_content_block.group(1))
|
||||
b64_sample = img_content_block.group(2)
|
||||
print(f"Base64 sample length: {len(b64_sample)}")
|
||||
print(f"Base64 sample (first 200 chars): {b64_sample[:200]}")
|
||||
else:
|
||||
print("No img.class block with content: url(data:image...) found.")
|
||||
# Fallback: match any data:image base64 in the file, allowing for whitespace and newlines in base64
|
||||
fallback_pattern = re.compile(r'url\\s*\\(\\s*data:image/(png|bmp|jpeg|jpg);base64,([A-Za-z0-9+/=\\s]+?)\\)', re.DOTALL)
|
||||
fallback_matches = list(fallback_pattern.finditer(css))
|
||||
print(f"Fallback found {len(fallback_matches)} images.")
|
||||
for i, match in enumerate(fallback_matches):
|
||||
img_type, b64data = match.groups()
|
||||
ext = 'jpg' if img_type == 'jpeg' else img_type
|
||||
out_path = os.path.join(OUTPUT_DIR, f"fallback_image_{i+1}.{ext}")
|
||||
try:
|
||||
clean_b64 = ''.join(b64data.split())
|
||||
with open(out_path, 'wb') as imgf:
|
||||
imgf.write(base64.b64decode(clean_b64.strip()))
|
||||
print(f"Extracted {out_path} (type: {img_type})")
|
||||
except Exception as e:
|
||||
print(f"Failed to extract {out_path}: {e}")
|
||||
else:
|
||||
for match in matches:
|
||||
class_name, img_type, b64data = match.groups()
|
||||
ext = 'jpg' if img_type == 'jpeg' else img_type
|
||||
out_path = os.path.join(OUTPUT_DIR, f"{class_name}.{ext}")
|
||||
with open(out_path, 'wb') as imgf:
|
||||
imgf.write(base64.b64decode(b64data.strip()))
|
||||
print(f"Extracted {out_path} (class: {class_name}, type: {img_type})")
|
||||
|
||||
print("Done.")
|
||||
44
SD/extract_imgs_css.py
Normal file
@@ -0,0 +1,44 @@
|
||||
import os
|
||||
import re
|
||||
import base64
|
||||
|
||||
INPUT_CSS = 'SD/css/imgs.css'
|
||||
OUTPUT_DIR = 'Imgs/'
|
||||
|
||||
os.makedirs(OUTPUT_DIR, exist_ok=True)
|
||||
|
||||
|
||||
with open(INPUT_CSS, 'r') as f:
|
||||
css = f.read()
|
||||
print('First 500 chars of CSS:')
|
||||
print(css[:500])
|
||||
|
||||
|
||||
# Improved regex to match the actual CSS structure in imgs.css
|
||||
# Handles: img.className { ... content: url(data:image/TYPE;base64,BASE64DATA) ... }
|
||||
|
||||
# Regex for CSS image blocks with single braces and correct escaping
|
||||
pattern = re.compile(
|
||||
r'img\.([a-zA-Z0-9_]+)\s*\{[^}]*?content\s*:\s*url\(data:image/(png|bmp|jpeg|jpg);base64,([A-Za-z0-9+/=\s]+)\)[^}]*?\}',
|
||||
re.DOTALL)
|
||||
|
||||
|
||||
matches = list(pattern.finditer(css))
|
||||
print(f"Found {len(matches)} images in CSS.")
|
||||
if matches:
|
||||
print('First match:')
|
||||
print(matches[0].group(0))
|
||||
|
||||
for match in matches:
|
||||
class_name, img_type, b64data = match.groups()
|
||||
ext = 'jpg' if img_type == 'jpeg' else img_type
|
||||
out_path = os.path.join(OUTPUT_DIR, f"{class_name}.{ext}")
|
||||
try:
|
||||
clean_b64 = ''.join(b64data.split())
|
||||
with open(out_path, 'wb') as imgf:
|
||||
imgf.write(base64.b64decode(clean_b64))
|
||||
print(f"Extracted {out_path} (class: {class_name}, type: {img_type})")
|
||||
except Exception as e:
|
||||
print(f"Failed to extract {out_path}: {e}")
|
||||
|
||||
print("Done.")
|
||||
BIN
SD/image/0.bmp
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
SD/image/1.bmp
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
SD/image/1000.bmp
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
SD/image/1001.bmp
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
SD/image/1002.bmp
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
SD/image/1003.bmp
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
SD/image/1004.bmp
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
SD/image/1005.bmp
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
SD/image/1006.bmp
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
SD/image/1007.bmp
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
SD/image/1008.bmp
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
SD/image/1009.bmp
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
SD/image/1010.bmp
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
SD/image/1011.bmp
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
SD/image/1012.bmp
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
SD/image/1013.bmp
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
SD/image/1014.bmp
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
SD/image/1015.bmp
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
SD/image/1016.bmp
Normal file
|
After Width: | Height: | Size: 23 KiB |
BIN
SD/image/1017.bmp
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
SD/image/2.bmp
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
SD/image/3.bmp
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
SD/image/4.bmp
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
SD/image/5.bmp
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
SD/image/6.bmp
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
SD/image/7.bmp
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
SD/image/8.bmp
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
SD/image/9.bmp
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
SD/image/BackGround.bmp
Normal file
|
After Width: | Height: | Size: 150 KiB |
BIN
SD/image/Compteur.bmp
Normal file
|
After Width: | Height: | Size: 78 KiB |
64
SD/image/image.md
Normal file
@@ -0,0 +1,64 @@
|
||||
# 1001.bmp Image Characteristics
|
||||
|
||||
- **File Name:** 1001.bmp
|
||||
- **Location:** SD/image/1001.bmp
|
||||
- **Format:** Windows 3.x BMP (BMP3)
|
||||
- **Dimensions:** 190 x 40 pixels
|
||||
- **Color Depth:** 24-bit (8-bit per channel, sRGB)
|
||||
- **Image Size:** 22,934 bytes
|
||||
- **Resolution:** 2834 x 2834 pixels/meter
|
||||
- **Data Offset:** 54 bytes (header size)
|
||||
|
||||
This image is suitable for use with ESP32 projects that support 24-bit BMP files. For optimal performance on microcontrollers, consider converting to a raw or 16-bit (RGB565) format if needed by your display library.
|
||||
|
||||
# Converting
|
||||
|
||||
For ESP32 with ILIxxx displays, storing images as uncompressed 24-bit BMP (like your current 1001.bmp) is convenient if your display library supports BMP decoding and you have enough storage and RAM. However, for best performance and efficiency, especially on microcontrollers, the most common and recommended format is:
|
||||
|
||||
Raw RGB565 (16-bit) format: This matches the color format of most ILIxxx displays, is fast to load, and uses less space than 24-bit BMP.
|
||||
Why RGB565 Raw is Better:
|
||||
Directly compatible with ILIxxx displays (no conversion needed at runtime).
|
||||
Smaller file size (190 × 40 × 2 bytes = 15,200 bytes).
|
||||
|
||||
Fastest to read and display.
|
||||
|
||||
# How to Convert a Photo or Image:
|
||||
|
||||
## Resize and Crop:
|
||||
|
||||
Use an image editor (GIMP, Photoshop, or free online tools) to resize your image to 190x40 pixels.
|
||||
Crop as needed to fit the aspect ratio.
|
||||
## Convert to RGB565 Raw:
|
||||
|
||||
Use a tool or script to convert the image to RGB565 format.
|
||||
Save as a .raw or .bin file (not BMP, not compressed).
|
||||
|
||||
## Copy to SD Card:
|
||||
|
||||
Place the .raw file on your SD card.
|
||||
Read and display it directly using your ESP32 code.
|
||||
|
||||
## Example Conversion Tools:
|
||||
|
||||
**GIMP**: Export as RGB565 using a plugin or export as raw data.
|
||||
Python script: Use PIL (Pillow) to convert and save as RGB565.
|
||||
Online tools: Search for “image to RGB565 converter”.
|
||||
If you want, I can provide a Python script to automate the conversion from any image to 190x40 RGB565 raw format. Let me know if you need this!
|
||||
|
||||
|
||||
Your display uses an inverted BGR565 format (not standard RGB565), meaning:
|
||||
|
||||
The color order is BGR (not RGB).
|
||||
The 16-bit value is inverted: color = 0xFFFF - standard BGR565.
|
||||
How to Convert an Image for Your Display
|
||||
Convert the image to 16-bit BGR565 format.
|
||||
Invert each 16-bit value (bitwise NOT or subtract from 0xFFFF).
|
||||
Save as a .raw file (no header, just pixel data).
|
||||
Can This Be Done in JavaScript (Browser)?
|
||||
Yes! You can:
|
||||
|
||||
Use an HTML <canvas> to load, resize, and crop the image.
|
||||
Read pixel data with getImageData.
|
||||
Convert each pixel to BGR565, invert it, and write to a binary buffer.
|
||||
Offer the result as a downloadable .raw file.
|
||||
Would you like a ready-to-use JavaScript/HTML tool for this? I can provide a complete example you can run in your browser.
|
||||
BIN
SD/image/logo.bmp
Normal file
|
After Width: | Height: | Size: 98 KiB |
5
SD/index.html
Normal file
@@ -0,0 +1,5 @@
|
||||
<html>
|
||||
<body>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
49
SD/js/bgr565.js
Normal file
@@ -0,0 +1,49 @@
|
||||
document.getElementById('convertBtn').onclick = function() {
|
||||
const fileInput = document.getElementById('imageInput');
|
||||
const width = parseInt(document.getElementById('width').value, 10);
|
||||
const height = parseInt(document.getElementById('height').value, 10);
|
||||
if (!fileInput.files.length) {
|
||||
alert('Please select an image file.');
|
||||
return;
|
||||
}
|
||||
const file = fileInput.files[0];
|
||||
const reader = new FileReader();
|
||||
reader.onload = function(e) {
|
||||
const img = new Image();
|
||||
img.onload = function() {
|
||||
const canvas = document.getElementById('canvas');
|
||||
canvas.width = width;
|
||||
canvas.height = height;
|
||||
const ctx = canvas.getContext('2d');
|
||||
ctx.clearRect(0, 0, width, height);
|
||||
ctx.drawImage(img, 0, 0, width, height);
|
||||
// Preview
|
||||
document.getElementById('preview').innerHTML = '';
|
||||
const previewImg = new Image();
|
||||
previewImg.src = canvas.toDataURL();
|
||||
document.getElementById('preview').appendChild(previewImg);
|
||||
// Get pixel data
|
||||
const imageData = ctx.getImageData(0, 0, width, height).data;
|
||||
const buf = new Uint8Array(width * height * 2);
|
||||
for (let i = 0, j = 0; i < imageData.length; i += 4, j += 2) {
|
||||
let r = imageData[i];
|
||||
let g = imageData[i+1];
|
||||
let b = imageData[i+2];
|
||||
// Convert to BGR565
|
||||
let bgr565 = ((b & 0xF8) << 8) | ((g & 0xFC) << 3) | (r >> 3);
|
||||
// Invert
|
||||
bgr565 = 0xFFFF - bgr565;
|
||||
buf[j] = bgr565 & 0xFF;
|
||||
buf[j+1] = (bgr565 >> 8) & 0xFF;
|
||||
}
|
||||
// Download
|
||||
const blob = new Blob([buf], {type: 'application/octet-stream'});
|
||||
const a = document.createElement('a');
|
||||
a.href = URL.createObjectURL(blob);
|
||||
a.download = file.name.replace(/\.[^.]+$/, '') + `_${width}x${height}_bgr565inv.raw`;
|
||||
a.click();
|
||||
};
|
||||
img.src = e.target.result;
|
||||
};
|
||||
reader.readAsDataURL(file);
|
||||
};
|
||||
184
SD/js/loco.js
Normal file
@@ -0,0 +1,184 @@
|
||||
|
||||
changelanguage();
|
||||
|
||||
// Check for Web Browser API support.
|
||||
if (window.File && window.FileReader && window.FileList && window.Blob) {
|
||||
} else {
|
||||
alert("File APIs are not fully supported in this browser.");
|
||||
}
|
||||
|
||||
function saveTextAsFile()
|
||||
{
|
||||
var textToSave = document.getElementById("inputTextToSave").value;
|
||||
var textToSaveAsBlob = new Blob([textToSave], {type:"text/plain"});
|
||||
var textToSaveAsURL = window.URL.createObjectURL(textToSaveAsBlob);
|
||||
var fileNameToSaveAs = document.getElementById("inputFileNameToSaveAs").value;
|
||||
fileNameToSaveAs = fileNameToSaveAs + ".csv";
|
||||
|
||||
var downloadLink = document.createElement("a");
|
||||
downloadLink.download = fileNameToSaveAs;
|
||||
downloadLink.innerHTML = "Download File";
|
||||
downloadLink.href = textToSaveAsURL;
|
||||
downloadLink.onclick = destroyClickedElement;
|
||||
downloadLink.style.display = "none";
|
||||
document.body.appendChild(downloadLink);
|
||||
|
||||
downloadLink.click();
|
||||
}
|
||||
|
||||
function destroyClickedElement(event)
|
||||
{
|
||||
document.body.removeChild(event.target);
|
||||
}
|
||||
|
||||
function parseCSV()
|
||||
{
|
||||
var iconName;
|
||||
var funcName;
|
||||
var iconSel;
|
||||
var textToSave = document.getElementById("inputTextToSave");
|
||||
var textCSV = textToSave.value;
|
||||
var lines = textCSV.split("\n");
|
||||
var information = lines[1].split(";");
|
||||
var field = document.getElementById("NameLoco");
|
||||
field.value = information[0];
|
||||
field = document.getElementById("NumImage");
|
||||
field.value = information[1];
|
||||
field = document.getElementById("SpeedMax");
|
||||
field.value = information[2];
|
||||
for (let i = 0; i < 29; i++) {
|
||||
iconName = "iconID" + information[3 + i];
|
||||
funcName = "F" + i;
|
||||
iconSel = document.getElementById(funcName);
|
||||
iconSel.className = iconName;
|
||||
}
|
||||
var imgSrc = document.getElementById("imageToShow");
|
||||
imgSrc.src = "image/" + information[1] + ".bmp";
|
||||
}
|
||||
|
||||
|
||||
function loadFileAsText()
|
||||
{
|
||||
var fileToLoad = document.getElementById("fileToLoad").files[0];
|
||||
var loco = document.getElementById("NumLoco");
|
||||
var locoFileName = fileToLoad.name.split(".");
|
||||
loco.value = locoFileName[0];
|
||||
|
||||
var fileReader = new FileReader();
|
||||
fileReader.onload = function(fileLoadedEvent)
|
||||
{
|
||||
var textFromFileLoaded = fileLoadedEvent.target.result;
|
||||
document.getElementById("inputTextToSave").value = textFromFileLoaded;
|
||||
};
|
||||
fileReader.onloadend = function(progressEvent)
|
||||
{
|
||||
parseCSV();
|
||||
}
|
||||
fileReader.readAsText(fileToLoad, "UTF-8");
|
||||
hideInstrucctions();
|
||||
}
|
||||
|
||||
function loadFileAsImage()
|
||||
{
|
||||
var imgSrc = document.getElementById("imageToShow");
|
||||
var imgNum = document.getElementById("NumImage");
|
||||
var fileToLoad = document.getElementById("imageToLoad").files[0];
|
||||
var imgFileName = fileToLoad.name.split(".");
|
||||
imgNum.value = imgFileName[0];
|
||||
imgSrc.src = "image/" + imgFileName[0] + ".bmp";
|
||||
|
||||
hideInstrucctions();
|
||||
}
|
||||
|
||||
function changeImageLoco()
|
||||
{
|
||||
var imgNum = document.getElementById("NumImage");
|
||||
var imgSrc = document.getElementById("imageToShow");
|
||||
imgSrc.src = "image/" + imgNum.value + ".bmp";
|
||||
}
|
||||
|
||||
|
||||
function changelanguage()
|
||||
{
|
||||
const languageSelect = document.getElementById('language-select');
|
||||
elements = document.querySelectorAll(`span[lang]`);
|
||||
for (let element of elements) {
|
||||
element.style.display = 'none';
|
||||
}
|
||||
var x = languageSelect.selectedIndex;
|
||||
if (x==0) {elements = document.querySelectorAll(`span[lang="en"]`);}
|
||||
if (x==1) {elements = document.querySelectorAll(`span[lang="es"]`);}
|
||||
if (x==2) {elements = document.querySelectorAll(`span[lang="de"]`);}
|
||||
if (x==3) {elements = document.querySelectorAll(`span[lang="ca"]`); }
|
||||
for (let i = 0; i < elements.length; i++) {
|
||||
elements[i].style.display = 'inline-block';
|
||||
}
|
||||
};
|
||||
|
||||
function selectIcon(value)
|
||||
{
|
||||
var allIcon = document.getElementById('iconAll');
|
||||
allIcon.style.display = 'block';
|
||||
var funcNum = document.getElementById('NumFunc');
|
||||
funcNum.value = value;
|
||||
var iconFunc = document.getElementById('Fx');
|
||||
const iconText = "F" + value;
|
||||
iconFunc.innerHTML = iconText;
|
||||
}
|
||||
|
||||
|
||||
function updateIcon(value)
|
||||
{
|
||||
var funcNum = document.getElementById('NumFunc');
|
||||
const iconName = "iconID" + value;
|
||||
const funcName = "F" + funcNum.value;
|
||||
var iconSel = document.getElementById(funcName);
|
||||
iconSel.className = iconName;
|
||||
var allIcon = document.getElementById('iconAll');
|
||||
allIcon.style.display = 'none';
|
||||
hideInstrucctions();
|
||||
}
|
||||
|
||||
function hideInstrucctions()
|
||||
{
|
||||
var showIns = document.getElementById('instruc');
|
||||
showIns.style.display = 'none';
|
||||
}
|
||||
|
||||
function createTextCSV()
|
||||
{
|
||||
var fileNameToSaveAs = document.getElementById("inputFileNameToSaveAs")
|
||||
var textToSave = document.getElementById("inputTextToSave");
|
||||
var textCSV = "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\n";
|
||||
var loco = document.getElementById("NumLoco");
|
||||
var field = document.getElementById("NameLoco");
|
||||
var funcName;
|
||||
var iconSel;
|
||||
if (loco.value != "") {
|
||||
textCSV = textCSV + field.value;
|
||||
field = document.getElementById("NumImage");
|
||||
if (field.value == "")
|
||||
field.value = "0";
|
||||
textCSV = textCSV + ";" + field.value;
|
||||
field = document.getElementById("SpeedMax");
|
||||
if (field.value == "")
|
||||
field.value = "100";
|
||||
textCSV = textCSV + ";" + field.value ;
|
||||
|
||||
for (let i = 0; i < 29; i++) {
|
||||
funcName = "F" + i;
|
||||
iconSel = document.getElementById(funcName).className.split("iconID");
|
||||
iconSel = iconSel[1];
|
||||
textCSV = textCSV + ";" + iconSel ;
|
||||
}
|
||||
textCSV = textCSV + "\n"
|
||||
textToSave.value = textCSV;
|
||||
fileNameToSaveAs.value = loco.value;
|
||||
saveTextAsFile();
|
||||
field = document.getElementById('instruc');
|
||||
field.style.display = 'block';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
2
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
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
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
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
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
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
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
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
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
|
||||
|