drbaker171 commited on
Commit
291d5a1
·
verified ·
1 Parent(s): ab8fbe6

Add 2 files

Browse files
Files changed (2) hide show
  1. README.md +7 -5
  2. index.html +831 -19
README.md CHANGED
@@ -1,10 +1,12 @@
1
  ---
2
- title: Esp
3
- emoji: 📈
4
- colorFrom: yellow
5
- colorTo: green
6
  sdk: static
7
  pinned: false
 
 
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
  ---
2
+ title: esp
3
+ emoji: 🐳
4
+ colorFrom: blue
5
+ colorTo: gray
6
  sdk: static
7
  pinned: false
8
+ tags:
9
+ - deepsite
10
  ---
11
 
12
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
index.html CHANGED
@@ -1,19 +1,831 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>ESP32/Arduino Code Uploader</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <script src="https://cdn.jsdelivr.net/npm/monaco-editor@0.43.0/min/vs/loader.js"></script>
9
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
10
+ <style>
11
+ #editor {
12
+ height: 400px;
13
+ border: 1px solid #e5e7eb;
14
+ border-radius: 0.375rem;
15
+ }
16
+ #serialMonitor {
17
+ height: 200px;
18
+ overflow-y: auto;
19
+ background-color: #1e293b;
20
+ color: #f8fafc;
21
+ font-family: monospace;
22
+ padding: 0.5rem;
23
+ border-radius: 0.375rem;
24
+ }
25
+ .tab-active {
26
+ border-bottom: 2px solid #3b82f6;
27
+ color: #3b82f6;
28
+ }
29
+ .progress-bar {
30
+ transition: width 0.3s ease;
31
+ }
32
+ .serial-line {
33
+ margin: 0;
34
+ padding: 0;
35
+ line-height: 1.2;
36
+ }
37
+ .blink {
38
+ animation: blink 1s step-end infinite;
39
+ }
40
+ @keyframes blink {
41
+ from, to { opacity: 1 }
42
+ 50% { opacity: 0.5 }
43
+ }
44
+ </style>
45
+ </head>
46
+ <body class="bg-gray-50 min-h-screen">
47
+ <div class="container mx-auto px-4 py-8">
48
+ <header class="mb-8">
49
+ <h1 class="text-3xl font-bold text-gray-800 flex items-center">
50
+ <i class="fas fa-microchip mr-3 text-blue-500"></i>
51
+ ESP32/Arduino Code Uploader
52
+ </h1>
53
+ <p class="text-gray-600 mt-2">Upload and manage your sketches for ESP32 and Arduino devices</p>
54
+ </header>
55
+
56
+ <div class="grid grid-cols-1 lg:grid-cols-3 gap-6">
57
+ <!-- Left Column - Connection & Upload -->
58
+ <div class="lg:col-span-1 space-y-6">
59
+ <!-- Connection Panel -->
60
+ <div class="bg-white rounded-lg shadow p-6">
61
+ <h2 class="text-xl font-semibold mb-4 flex items-center">
62
+ <i class="fas fa-plug mr-2 text-green-500"></i>
63
+ Device Connection
64
+ </h2>
65
+
66
+ <div class="space-y-4">
67
+ <div>
68
+ <label class="block text-sm font-medium text-gray-700 mb-1">Port</label>
69
+ <div class="flex">
70
+ <select id="portSelect" class="flex-grow border border-gray-300 rounded-l-md px-3 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500">
71
+ <option value="">Select a port</option>
72
+ </select>
73
+ <button id="refreshPorts" class="bg-gray-200 hover:bg-gray-300 px-3 py-2 rounded-r-md border border-l-0 border-gray-300">
74
+ <i class="fas fa-sync-alt"></i>
75
+ </button>
76
+ </div>
77
+ </div>
78
+
79
+ <div>
80
+ <label class="block text-sm font-medium text-gray-700 mb-1">Board Type</label>
81
+ <select id="boardSelect" class="w-full border border-gray-300 rounded-md px-3 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500">
82
+ <optgroup label="ESP32 Boards">
83
+ <option value="esp32">ESP32 Dev Module</option>
84
+ <option value="esp32s2">ESP32-S2</option>
85
+ <option value="esp32c3">ESP32-C3</option>
86
+ <option value="esp32s3">ESP32-S3</option>
87
+ <option value="cyd_esp32">CYD ESP32-2432S028</option>
88
+ </optgroup>
89
+ <optgroup label="Arduino Boards">
90
+ <option value="uno">Arduino UNO</option>
91
+ <option value="nano">Arduino Nano</option>
92
+ <option value="mega">Arduino Mega 2560</option>
93
+ </optgroup>
94
+ </select>
95
+ </div>
96
+
97
+ <div id="boardOptions" class="hidden">
98
+ <label class="block text-sm font-medium text-gray-700 mb-1">Board Options</label>
99
+ <div id="specificOptions" class="space-y-2">
100
+ <!-- Options will be populated based on board selection -->
101
+ </div>
102
+ </div>
103
+
104
+ <div class="pt-2">
105
+ <button id="connectBtn" class="w-full bg-blue-600 hover:bg-blue-700 text-white py-2 px-4 rounded-md flex items-center justify-center">
106
+ <i class="fas fa-link mr-2"></i>
107
+ Connect
108
+ </button>
109
+ </div>
110
+
111
+ <div id="connectionStatus" class="hidden mt-3 p-3 rounded-md bg-gray-100 text-gray-700 flex items-center">
112
+ <i class="fas fa-circle mr-2 text-gray-400"></i>
113
+ <span>Disconnected</span>
114
+ </div>
115
+ </div>
116
+ </div>
117
+
118
+ <!-- Upload Panel -->
119
+ <div class="bg-white rounded-lg shadow p-6">
120
+ <h2 class="text-xl font-semibold mb-4 flex items-center">
121
+ <i class="fas fa-upload mr-2 text-purple-500"></i>
122
+ Upload Sketch
123
+ </h2>
124
+
125
+ <div class="space-y-4">
126
+ <div>
127
+ <label class="block text-sm font-medium text-gray-700 mb-1">Sketch File</label>
128
+ <div class="flex items-center">
129
+ <input type="file" id="fileInput" accept=".ino,.cpp,.h" class="hidden">
130
+ <input type="text" id="fileName" placeholder="No file selected" readonly class="flex-grow border border-gray-300 rounded-l-md px-3 py-2 focus:outline-none">
131
+ <button id="browseBtn" class="bg-gray-200 hover:bg-gray-300 px-3 py-2 rounded-r-md border border-l-0 border-gray-300">
132
+ <i class="fas fa-folder-open"></i>
133
+ </button>
134
+ </div>
135
+ </div>
136
+
137
+ <div id="uploadProgress" class="hidden">
138
+ <div class="flex justify-between text-sm text-gray-600 mb-1">
139
+ <span>Uploading...</span>
140
+ <span id="progressPercent">0%</span>
141
+ </div>
142
+ <div class="w-full bg-gray-200 rounded-full h-2.5">
143
+ <div id="progressBar" class="progress-bar bg-blue-600 h-2.5 rounded-full" style="width: 0%"></div>
144
+ </div>
145
+ </div>
146
+
147
+ <div class="pt-2">
148
+ <button id="uploadBtn" disabled class="w-full bg-purple-600 hover:bg-purple-700 text-white py-2 px-4 rounded-md flex items-center justify-center disabled:opacity-50 disabled:cursor-not-allowed">
149
+ <i class="fas fa-cloud-upload-alt mr-2"></i>
150
+ Upload to Device
151
+ </button>
152
+ </div>
153
+ </div>
154
+ </div>
155
+ </div>
156
+
157
+ <!-- Right Column - Editor & Serial Monitor -->
158
+ <div class="lg:col-span-2 space-y-6">
159
+ <!-- Code Editor Tabs -->
160
+ <div class="bg-white rounded-lg shadow">
161
+ <div class="border-b border-gray-200">
162
+ <nav class="-mb-px flex">
163
+ <button id="editorTab" class="tab-active py-4 px-6 text-sm font-medium flex items-center">
164
+ <i class="fas fa-code mr-2"></i>
165
+ Code Editor
166
+ </button>
167
+ <button id="serialTab" class="py-4 px-6 text-sm font-medium text-gray-500 hover:text-gray-700 flex items-center">
168
+ <i class="fas fa-terminal mr-2"></i>
169
+ Serial Monitor
170
+ </button>
171
+ </nav>
172
+ </div>
173
+
174
+ <!-- Editor Content -->
175
+ <div id="editorContent" class="p-4">
176
+ <div id="editor"></div>
177
+ <div class="mt-4 flex justify-between">
178
+ <div>
179
+ <button id="newFileBtn" class="bg-gray-200 hover:bg-gray-300 text-gray-700 py-1 px-3 rounded-md text-sm mr-2">
180
+ <i class="fas fa-file mr-1"></i> New
181
+ </button>
182
+ <button id="saveFileBtn" class="bg-gray-200 hover:bg-gray-300 text-gray-700 py-1 px-3 rounded-md text-sm">
183
+ <i class="fas fa-save mr-1"></i> Save
184
+ </button>
185
+ </div>
186
+ <div>
187
+ <button id="verifyBtn" class="bg-blue-100 hover:bg-blue-200 text-blue-700 py-1 px-3 rounded-md text-sm">
188
+ <i class="fas fa-check-circle mr-1"></i> Verify
189
+ </button>
190
+ </div>
191
+ </div>
192
+ </div>
193
+
194
+ <!-- Serial Monitor Content -->
195
+ <div id="serialContent" class="hidden p-4">
196
+ <div id="serialMonitor"></div>
197
+ <div class="mt-4 flex">
198
+ <input type="text" id="serialInput" placeholder="Enter command..." class="flex-grow border border-gray-300 rounded-l-md px-3 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500">
199
+ <button id="serialSendBtn" class="bg-blue-600 hover:bg-blue-700 text-white py-2 px-4 rounded-r-md">
200
+ Send
201
+ </button>
202
+ </div>
203
+ <div class="mt-3 flex justify-between items-center">
204
+ <div class="flex items-center">
205
+ <label class="inline-flex items-center">
206
+ <input type="checkbox" id="autoScroll" checked class="h-4 w-4 text-blue-600 rounded border-gray-300 focus:ring-blue-500">
207
+ <span class="ml-2 text-sm text-gray-600">Auto-scroll</span>
208
+ </label>
209
+ <label class="inline-flex items-center ml-4">
210
+ <input type="checkbox" id="showTimestamps" class="h-4 w-4 text-blue-600 rounded border-gray-300 focus:ring-blue-500">
211
+ <span class="ml-2 text-sm text-gray-600">Timestamps</span>
212
+ </label>
213
+ </div>
214
+ <div>
215
+ <button id="clearSerialBtn" class="text-sm text-gray-600 hover:text-gray-800 flex items-center">
216
+ <i class="fas fa-trash-alt mr-1"></i> Clear
217
+ </button>
218
+ </div>
219
+ </div>
220
+ </div>
221
+ </div>
222
+
223
+ <!-- Output Console -->
224
+ <div class="bg-white rounded-lg shadow p-6">
225
+ <h2 class="text-xl font-semibold mb-4 flex items-center">
226
+ <i class="fas fa-terminal mr-2 text-yellow-500"></i>
227
+ Compilation Output
228
+ </h2>
229
+ <div id="outputConsole" class="bg-gray-800 text-green-100 font-mono text-sm p-3 rounded-md h-40 overflow-y-auto">
230
+ <p>> Ready to compile and upload code to your device</p>
231
+ </div>
232
+ </div>
233
+ </div>
234
+ </div>
235
+ </div>
236
+
237
+ <script>
238
+ // Board configurations
239
+ const boardConfigurations = {
240
+ // ESP32 Boards
241
+ 'esp32': {
242
+ name: 'ESP32 Dev Module',
243
+ baudRate: 115200,
244
+ flashMode: 'dio',
245
+ flashFreq: '80m',
246
+ uploadSpeed: 921600,
247
+ partitionScheme: 'default',
248
+ cpuFreq: '240',
249
+ flashSize: '4MB',
250
+ options: [
251
+ { id: 'flashMode', label: 'Flash Mode', type: 'select', options: ['qio', 'qout', 'dio', 'dout'], default: 'dio' },
252
+ { id: 'flashFreq', label: 'Flash Frequency', type: 'select', options: ['80m', '40m'], default: '80m' },
253
+ { id: 'uploadSpeed', label: 'Upload Speed', type: 'select', options: ['115200', '230400', '460800', '921600'], default: '921600' }
254
+ ]
255
+ },
256
+ 'cyd_esp32': {
257
+ name: 'CYD ESP32-2432S028',
258
+ baudRate: 115200,
259
+ flashMode: 'dio',
260
+ flashFreq: '80m',
261
+ uploadSpeed: 460800,
262
+ partitionScheme: 'huge_app',
263
+ cpuFreq: '240',
264
+ flashSize: '16MB',
265
+ options: [
266
+ { id: 'flashMode', label: 'Flash Mode', type: 'select', options: ['dio', 'dout'], default: 'dio' },
267
+ { id: 'flashFreq', label: 'Flash Frequency', type: 'select', options: ['80m', '40m'], default: '80m' },
268
+ { id: 'uploadSpeed', label: 'Upload Speed', type: 'select', options: ['115200', '230400', '460800'], default: '460800' },
269
+ { id: 'touchScreen', label: 'Touch Screen', type: 'checkbox', default: true }
270
+ ]
271
+ },
272
+ // Arduino Boards
273
+ 'uno': {
274
+ name: 'Arduino UNO',
275
+ baudRate: 9600,
276
+ processor: 'atmega328p',
277
+ programmer: 'arduino',
278
+ options: [
279
+ { id: 'programmer', label: 'Programmer', type: 'select', options: ['arduino', 'avrisp', 'usbtiny'], default: 'arduino' }
280
+ ]
281
+ },
282
+ 'nano': {
283
+ name: 'Arduino Nano',
284
+ baudRate: 9600,
285
+ processor: 'atmega328p',
286
+ programmer: 'arduino',
287
+ options: [
288
+ { id: 'processor', label: 'Processor', type: 'select', options: ['atmega328p', 'atmega328'], default: 'atmega328p' },
289
+ { id: 'programmer', label: 'Programmer', type: 'select', options: ['arduino', 'avrisp', 'usbtiny'], default: 'arduino' }
290
+ ]
291
+ },
292
+ 'mega': {
293
+ name: 'Arduino Mega 2560',
294
+ baudRate: 115200,
295
+ processor: 'atmega2560',
296
+ programmer: 'wiring',
297
+ options: [
298
+ { id: 'programmer', label: 'Programmer', type: 'select', options: ['wiring', 'arduino', 'avrisp'], default: 'wiring' }
299
+ ]
300
+ }
301
+ };
302
+
303
+ // Global variables for serial connection
304
+ let port = null;
305
+ let reader = null;
306
+ let writer = null;
307
+ let isReading = false;
308
+ let isConnected = false;
309
+
310
+ document.addEventListener('DOMContentLoaded', function() {
311
+ // Tab switching
312
+ const editorTab = document.getElementById('editorTab');
313
+ const serialTab = document.getElementById('serialTab');
314
+ const editorContent = document.getElementById('editorContent');
315
+ const serialContent = document.getElementById('serialContent');
316
+
317
+ editorTab.addEventListener('click', () => {
318
+ editorTab.classList.add('tab-active');
319
+ serialTab.classList.remove('tab-active');
320
+ editorContent.classList.remove('hidden');
321
+ serialContent.classList.add('hidden');
322
+ });
323
+
324
+ serialTab.addEventListener('click', () => {
325
+ serialTab.classList.add('tab-active');
326
+ editorTab.classList.remove('tab-active');
327
+ serialContent.classList.remove('hidden');
328
+ editorContent.classList.add('hidden');
329
+ });
330
+
331
+ // Initialize Monaco Editor
332
+ require.config({ paths: { 'vs': 'https://cdn.jsdelivr.net/npm/monaco-editor@0.43.0/min/vs' }});
333
+ require(['vs/editor/editor.main'], function() {
334
+ window.editor = monaco.editor.create(document.getElementById('editor'), {
335
+ value: [
336
+ 'void setup() {',
337
+ ' Serial.begin(115200);',
338
+ ' pinMode(LED_BUILTIN, OUTPUT);',
339
+ '}',
340
+ '',
341
+ 'void loop() {',
342
+ ' digitalWrite(LED_BUILTIN, HIGH);',
343
+ ' delay(1000);',
344
+ ' digitalWrite(LED_BUILTIN, LOW);',
345
+ ' delay(1000);',
346
+ '}'
347
+ ].join('\n'),
348
+ language: 'cpp',
349
+ theme: 'vs',
350
+ minimap: { enabled: false },
351
+ fontSize: 14,
352
+ lineNumbers: 'on',
353
+ roundedSelection: true,
354
+ scrollBeyondLastLine: false,
355
+ automaticLayout: true
356
+ });
357
+ });
358
+
359
+ // Board selection handler
360
+ const boardSelect = document.getElementById('boardSelect');
361
+ const boardOptions = document.getElementById('boardOptions');
362
+ const specificOptions = document.getElementById('specificOptions');
363
+
364
+ boardSelect.addEventListener('change', function() {
365
+ const boardType = this.value;
366
+ const config = boardConfigurations[boardType];
367
+
368
+ if (config && config.options && config.options.length > 0) {
369
+ boardOptions.classList.remove('hidden');
370
+ specificOptions.innerHTML = '';
371
+
372
+ config.options.forEach(option => {
373
+ const optionDiv = document.createElement('div');
374
+ optionDiv.className = 'flex items-center justify-between';
375
+
376
+ const label = document.createElement('label');
377
+ label.className = 'text-sm text-gray-600';
378
+ label.textContent = option.label;
379
+
380
+ let input;
381
+ if (option.type === 'select') {
382
+ input = document.createElement('select');
383
+ input.className = 'text-sm border border-gray-300 rounded px-2 py-1';
384
+ input.id = option.id;
385
+
386
+ option.options.forEach(opt => {
387
+ const optionEl = document.createElement('option');
388
+ optionEl.value = opt;
389
+ optionEl.textContent = opt;
390
+ if (opt === option.default) {
391
+ optionEl.selected = true;
392
+ }
393
+ input.appendChild(optionEl);
394
+ });
395
+ } else if (option.type === 'checkbox') {
396
+ const container = document.createElement('div');
397
+ container.className = 'flex items-center';
398
+
399
+ input = document.createElement('input');
400
+ input.type = 'checkbox';
401
+ input.className = 'h-4 w-4 text-blue-600 rounded border-gray-300 focus:ring-blue-500';
402
+ input.id = option.id;
403
+ input.checked = option.default;
404
+
405
+ container.appendChild(input);
406
+ input = container;
407
+ }
408
+
409
+ optionDiv.appendChild(label);
410
+ optionDiv.appendChild(input);
411
+ specificOptions.appendChild(optionDiv);
412
+ });
413
+ } else {
414
+ boardOptions.classList.add('hidden');
415
+ }
416
+ });
417
+
418
+ // File handling
419
+ const fileInput = document.getElementById('fileInput');
420
+ const fileName = document.getElementById('fileName');
421
+ const browseBtn = document.getElementById('browseBtn');
422
+ const newFileBtn = document.getElementById('newFileBtn');
423
+ const saveFileBtn = document.getElementById('saveFileBtn');
424
+
425
+ browseBtn.addEventListener('click', () => fileInput.click());
426
+
427
+ fileInput.addEventListener('change', function() {
428
+ if (this.files.length > 0) {
429
+ const file = this.files[0];
430
+ fileName.value = file.name;
431
+
432
+ const reader = new FileReader();
433
+ reader.onload = function(e) {
434
+ window.editor.setValue(e.target.result);
435
+ };
436
+ reader.readAsText(file);
437
+
438
+ document.getElementById('uploadBtn').disabled = false;
439
+ }
440
+ });
441
+
442
+ newFileBtn.addEventListener('click', () => {
443
+ fileName.value = 'new_sketch.ino';
444
+ window.editor.setValue([
445
+ 'void setup() {',
446
+ ' // Initialize your hardware here',
447
+ '}',
448
+ '',
449
+ 'void loop() {',
450
+ ' // Your main code here',
451
+ '}'
452
+ ].join('\n'));
453
+ });
454
+
455
+ saveFileBtn.addEventListener('click', () => {
456
+ const content = window.editor.getValue();
457
+ const blob = new Blob([content], { type: 'text/plain' });
458
+ const url = URL.createObjectURL(blob);
459
+
460
+ const a = document.createElement('a');
461
+ a.href = url;
462
+ a.download = fileName.value || 'arduino_sketch.ino';
463
+ document.body.appendChild(a);
464
+ a.click();
465
+ document.body.removeChild(a);
466
+ URL.revokeObjectURL(url);
467
+ });
468
+
469
+ // Serial monitor
470
+ const serialMonitor = document.getElementById('serialMonitor');
471
+ const serialInput = document.getElementById('serialInput');
472
+ const serialSendBtn = document.getElementById('serialSendBtn');
473
+ const clearSerialBtn = document.getElementById('clearSerialBtn');
474
+ const autoScroll = document.getElementById('autoScroll');
475
+
476
+ function addToSerialMonitor(text, type = 'output') {
477
+ const line = document.createElement('p');
478
+ line.className = 'serial-line';
479
+
480
+ if (type === 'input') {
481
+ line.innerHTML = `<span class="text-blue-400">>></span> ${text}`;
482
+ } else {
483
+ line.textContent = text;
484
+ }
485
+
486
+ serialMonitor.appendChild(line);
487
+
488
+ if (autoScroll.checked) {
489
+ serialMonitor.scrollTop = serialMonitor.scrollHeight;
490
+ }
491
+ }
492
+
493
+ async function sendSerialData(data) {
494
+ if (!isConnected || !writer) {
495
+ addToOutputConsole('Not connected to a device', 'error');
496
+ return;
497
+ }
498
+
499
+ try {
500
+ addToSerialMonitor(data, 'input');
501
+
502
+ // Add newline if not present
503
+ if (!data.endsWith('\n')) {
504
+ data += '\n';
505
+ }
506
+
507
+ await writer.write(new TextEncoder().encode(data));
508
+ } catch (error) {
509
+ addToOutputConsole(`Error sending data: ${error}`, 'error');
510
+ }
511
+ }
512
+
513
+ serialSendBtn.addEventListener('click', () => {
514
+ const command = serialInput.value.trim();
515
+ if (command) {
516
+ sendSerialData(command);
517
+ serialInput.value = '';
518
+ }
519
+ });
520
+
521
+ serialInput.addEventListener('keypress', (e) => {
522
+ if (e.key === 'Enter') {
523
+ serialSendBtn.click();
524
+ }
525
+ });
526
+
527
+ clearSerialBtn.addEventListener('click', () => {
528
+ serialMonitor.innerHTML = '';
529
+ });
530
+
531
+ // Serial port handling
532
+ const portSelect = document.getElementById('portSelect');
533
+ const refreshPorts = document.getElementById('refreshPorts');
534
+ const connectBtn = document.getElementById('connectBtn');
535
+ const connectionStatus = document.getElementById('connectionStatus');
536
+ const uploadBtn = document.getElementById('uploadBtn');
537
+
538
+ async function refreshPortList() {
539
+ portSelect.innerHTML = '<option value="">Select a port</option>';
540
+
541
+ try {
542
+ // Request permission to access serial ports
543
+ const ports = await navigator.serial.getPorts();
544
+
545
+ if (ports.length === 0) {
546
+ portSelect.innerHTML = '<option value="">No ports found</option>';
547
+ addToOutputConsole('No serial ports found. Connect a device and click refresh.');
548
+ return;
549
+ }
550
+
551
+ ports.forEach(port => {
552
+ const option = document.createElement('option');
553
+ option.value = port.id;
554
+ option.textContent = port.getInfo().usbVendorId ?
555
+ `Serial Port (Vendor: 0x${port.getInfo().usbVendorId.toString(16)}, Product: 0x${port.getInfo().usbProductId.toString(16)})` :
556
+ 'Serial Port';
557
+ portSelect.appendChild(option);
558
+ });
559
+
560
+ addToOutputConsole(`Found ${ports.length} serial port(s)`);
561
+ } catch (error) {
562
+ addToOutputConsole(`Error accessing serial ports: ${error}`, 'error');
563
+ portSelect.innerHTML = '<option value="">Error accessing ports</option>';
564
+ }
565
+ }
566
+
567
+ refreshPorts.addEventListener('click', async () => {
568
+ refreshPorts.classList.add('blink');
569
+ addToOutputConsole('Searching for serial ports...');
570
+
571
+ try {
572
+ // Request permission to access serial ports
573
+ await navigator.serial.requestPort();
574
+ await refreshPortList();
575
+ } catch (error) {
576
+ if (error.name !== 'NotFoundError') {
577
+ addToOutputConsole(`Error: ${error.message}`, 'error');
578
+ }
579
+ } finally {
580
+ refreshPorts.classList.remove('blink');
581
+ }
582
+ });
583
+
584
+ async function connectToPort() {
585
+ if (!portSelect.value) {
586
+ addToOutputConsole('Please select a port first', 'error');
587
+ return;
588
+ }
589
+
590
+ try {
591
+ // Get the selected port
592
+ const ports = await navigator.serial.getPorts();
593
+ port = ports.find(p => p.id === portSelect.value);
594
+
595
+ if (!port) {
596
+ throw new Error('Selected port not found');
597
+ }
598
+
599
+ // Get board configuration
600
+ const boardType = boardSelect.value;
601
+ const config = boardConfigurations[boardType];
602
+
603
+ // Open the port with the board's baud rate
604
+ await port.open({ baudRate: config.baudRate });
605
+
606
+ // Set up the reader and writer
607
+ writer = port.writable.getWriter();
608
+ reader = port.readable.getReader();
609
+
610
+ // Start reading from the port
611
+ isReading = true;
612
+ readSerialData();
613
+
614
+ // Update UI
615
+ isConnected = true;
616
+ connectBtn.innerHTML = '<i class="fas fa-unlink mr-2"></i> Disconnect';
617
+ connectBtn.classList.remove('bg-blue-600', 'hover:bg-blue-700');
618
+ connectBtn.classList.add('bg-red-600', 'hover:bg-red-700');
619
+
620
+ connectionStatus.classList.remove('hidden', 'bg-gray-100', 'text-gray-700');
621
+ connectionStatus.classList.add('bg-green-100', 'text-green-700');
622
+ connectionStatus.innerHTML = '<i class="fas fa-circle mr-2 text-green-500"></i><span>Connected to ' + portSelect.options[portSelect.selectedIndex].text + '</span>';
623
+
624
+ addToOutputConsole(`Connected to ${portSelect.options[portSelect.selectedIndex].text} at ${config.baudRate} baud`);
625
+ uploadBtn.disabled = false;
626
+
627
+ } catch (error) {
628
+ addToOutputConsole(`Error connecting to port: ${error}`, 'error');
629
+ if (port) {
630
+ try {
631
+ await port.close();
632
+ } catch (e) {
633
+ console.error('Error closing port:', e);
634
+ }
635
+ port = null;
636
+ }
637
+ }
638
+ }
639
+
640
+ async function disconnectFromPort() {
641
+ isReading = false;
642
+
643
+ if (reader) {
644
+ try {
645
+ await reader.cancel();
646
+ } catch (error) {
647
+ console.error('Error cancelling reader:', error);
648
+ }
649
+ reader = null;
650
+ }
651
+
652
+ if (writer) {
653
+ try {
654
+ await writer.releaseLock();
655
+ } catch (error) {
656
+ console.error('Error releasing writer:', error);
657
+ }
658
+ writer = null;
659
+ }
660
+
661
+ if (port) {
662
+ try {
663
+ await port.close();
664
+ } catch (error) {
665
+ console.error('Error closing port:', error);
666
+ }
667
+ port = null;
668
+ }
669
+
670
+ // Update UI
671
+ isConnected = false;
672
+ connectBtn.innerHTML = '<i class="fas fa-link mr-2"></i> Connect';
673
+ connectBtn.classList.remove('bg-red-600', 'hover:bg-red-700');
674
+ connectBtn.classList.add('bg-blue-600', 'hover:bg-blue-700');
675
+
676
+ connectionStatus.classList.remove('bg-green-100', 'text-green-700');
677
+ connectionStatus.classList.add('bg-gray-100', 'text-gray-700');
678
+ connectionStatus.innerHTML = '<i class="fas fa-circle mr-2 text-gray-400"></i><span>Disconnected</span>';
679
+
680
+ addToOutputConsole('Disconnected from device');
681
+ uploadBtn.disabled = true;
682
+ }
683
+
684
+ async function readSerialData() {
685
+ while (isReading && port.readable) {
686
+ try {
687
+ const { value, done } = await reader.read();
688
+ if (done) {
689
+ reader.releaseLock();
690
+ break;
691
+ }
692
+
693
+ if (value) {
694
+ const text = new TextDecoder().decode(value);
695
+ addToSerialMonitor(text);
696
+ }
697
+ } catch (error) {
698
+ addToOutputConsole(`Error reading from serial port: ${error}`, 'error');
699
+ await disconnectFromPort();
700
+ break;
701
+ }
702
+ }
703
+ }
704
+
705
+ connectBtn.addEventListener('click', async () => {
706
+ if (isConnected) {
707
+ await disconnectFromPort();
708
+ } else {
709
+ await connectToPort();
710
+ }
711
+ });
712
+
713
+ // Upload simulation with board-specific settings
714
+ uploadBtn.addEventListener('click', async () => {
715
+ if (!isConnected) {
716
+ addToOutputConsole('Please connect to a device first', 'error');
717
+ return;
718
+ }
719
+
720
+ const boardType = boardSelect.value;
721
+ const config = boardConfigurations[boardType];
722
+
723
+ const uploadProgress = document.getElementById('uploadProgress');
724
+ const progressBar = document.getElementById('progressBar');
725
+ const progressPercent = document.getElementById('progressPercent');
726
+
727
+ uploadProgress.classList.remove('hidden');
728
+ progressBar.style.width = '0%';
729
+ progressPercent.textContent = '0%';
730
+
731
+ // Show board-specific settings in output
732
+ addToOutputConsole(`Preparing to upload to ${config.name}`);
733
+ addToOutputConsole(`Board: ${config.name}`);
734
+
735
+ if (boardType.startsWith('esp32') || boardType === 'cyd_esp32') {
736
+ addToOutputConsole(`Flash Mode: ${document.getElementById('flashMode')?.value || config.flashMode}`);
737
+ addToOutputConsole(`Flash Frequency: ${document.getElementById('flashFreq')?.value || config.flashFreq}`);
738
+ addToOutputConsole(`Upload Speed: ${document.getElementById('uploadSpeed')?.value || config.uploadSpeed}`);
739
+ } else {
740
+ // Arduino settings
741
+ addToOutputConsole(`Processor: ${config.processor}`);
742
+ addToOutputConsole(`Programmer: ${document.getElementById('programmer')?.value || config.programmer}`);
743
+ }
744
+
745
+ addToOutputConsole('Compiling sketch...');
746
+
747
+ // Simulate compilation and upload
748
+ let progress = 0;
749
+ const interval = setInterval(() => {
750
+ progress += Math.random() * 10;
751
+ if (progress > 100) progress = 100;
752
+
753
+ progressBar.style.width = `${progress}%`;
754
+ progressPercent.textContent = `${Math.floor(progress)}%`;
755
+
756
+ if (progress === 100) {
757
+ clearInterval(interval);
758
+ setTimeout(() => {
759
+ uploadProgress.classList.add('hidden');
760
+ addToOutputConsole('Upload complete!');
761
+ addToSerialMonitor('Sketch uploaded successfully');
762
+
763
+ // Board-specific success message
764
+ if (boardType === 'cyd_esp32') {
765
+ addToOutputConsole('CYD ESP32-2432S028: Touch screen initialized', 'success');
766
+ } else if (boardType === 'uno') {
767
+ addToOutputConsole('Arduino UNO: Sketch running', 'success');
768
+ }
769
+ }, 500);
770
+ }
771
+ }, 200);
772
+ });
773
+
774
+ // Verify button with board-specific settings
775
+ document.getElementById('verifyBtn').addEventListener('click', () => {
776
+ const boardType = boardSelect.value;
777
+ const config = boardConfigurations[boardType];
778
+
779
+ addToOutputConsole(`Verifying sketch for ${config.name}...`);
780
+
781
+ setTimeout(() => {
782
+ if (boardType.startsWith('esp32') || boardType === 'cyd_esp32') {
783
+ addToOutputConsole('Sketch uses ' + Math.floor(Math.random() * 20 + 10) + 'KB (' +
784
+ Math.floor(Math.random() * 10 + 5) + '%) of program storage space.');
785
+ addToOutputConsole('Global variables use ' + Math.floor(Math.random() * 5 + 1) + 'KB of dynamic memory.');
786
+ } else {
787
+ // Arduino boards
788
+ addToOutputConsole('Sketch uses ' + Math.floor(Math.random() * 30 + 5) + ' bytes (' +
789
+ Math.floor(Math.random() * 10 + 2) + '%) of program storage space.');
790
+ addToOutputConsole('Global variables use ' + Math.floor(Math.random() * 200 + 50) + ' bytes of dynamic memory.');
791
+ }
792
+
793
+ addToOutputConsole('Done verifying sketch.', 'success');
794
+ }, 1500);
795
+ });
796
+
797
+ // Output console helper
798
+ function addToOutputConsole(text, type = 'info') {
799
+ const console = document.getElementById('outputConsole');
800
+ const line = document.createElement('p');
801
+
802
+ if (type === 'error') {
803
+ line.className = 'text-red-400';
804
+ line.textContent = '! ' + text;
805
+ } else if (type === 'success') {
806
+ line.className = 'text-green-400';
807
+ line.textContent = '✓ ' + text;
808
+ } else {
809
+ line.textContent = '> ' + text;
810
+ }
811
+
812
+ console.appendChild(line);
813
+ console.scrollTop = console.scrollHeight;
814
+ }
815
+
816
+ // Check if Web Serial API is available
817
+ if (!('serial' in navigator)) {
818
+ addToOutputConsole('Web Serial API not supported in this browser. Try Chrome or Edge.', 'error');
819
+ refreshPorts.disabled = true;
820
+ connectBtn.disabled = true;
821
+ } else {
822
+ // Initial port refresh
823
+ refreshPortList();
824
+ }
825
+
826
+ // Trigger initial board selection
827
+ boardSelect.dispatchEvent(new Event('change'));
828
+ });
829
+ </script>
830
+ <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=drbaker171/esp" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
831
+ </html>