From d298f72727abe36433fcbf77b7de6e03da95f156 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 20 Sep 2025 11:29:54 +0000 Subject: [PATCH 001/170] Initial plan From 2a01b5862aded9bdbe787e3f6008fc38bf64f26b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 20 Sep 2025 11:31:57 +0000 Subject: [PATCH 002/170] Initial plan From bb10ec3b75a502dd30365e7964d527d5c20171df Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 20 Sep 2025 11:36:51 +0000 Subject: [PATCH 003/170] Fix ARDUINO_USB_MODE issue: change from 1 to 0 to allow normal boot Co-authored-by: netmindz <442066+netmindz@users.noreply.github.com> --- platformio.ini | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/platformio.ini b/platformio.ini index 96c06b9e..b5f51b1e 100644 --- a/platformio.ini +++ b/platformio.ini @@ -455,7 +455,7 @@ build_flags = -g -D CONFIG_ASYNC_TCP_USE_WDT=0 -D CONFIG_ASYNC_TCP_TASK_STACK_SIZE=9472 ;; WLEDMM increase stack by 1.25Kb, as audioreactive needs bigger SETTINGS_STACK_BUF_SIZE -DCO - -DARDUINO_USB_MODE=1 ;; this flag is mandatory for ESP32-C3 + -DARDUINO_USB_MODE=0 ;; changed from 1 to 0 to allow normal boot without USB debugger ;; please make sure that the following flags are properly set (to 0 or 1) by your board.json, or included in your custom platformio_override.ini entry: ;; ARDUINO_USB_CDC_ON_BOOT @@ -702,7 +702,7 @@ build_unflags = ${common.build_unflags} build_flags = ${common.build_flags} ${esp32s3.build_flags} -D CONFIG_LITTLEFS_FOR_IDF_3_2 -D WLED_WATCHDOG_TIMEOUT=0 ;-D ARDUINO_USB_CDC_ON_BOOT=0 ;; -D ARDUINO_USB_MODE=1 ;; for boards with serial-to-USB chip - -D ARDUINO_USB_CDC_ON_BOOT=1 -D ARDUINO_USB_MODE=1 ;; for boards with USB-OTG connector only (USBCDC or "TinyUSB") + -D ARDUINO_USB_CDC_ON_BOOT=1 -D ARDUINO_USB_MODE=0 ;; changed from 1 to 0 to allow normal boot without USB debugger ; -D WLED_RELEASE_NAME=ESP32-S3_PSRAM -D WLED_USE_PSRAM -DBOARD_HAS_PSRAM ; tells WLED that PSRAM shall be used -D WLED_USE_PSRAM_JSON -DALL_JSON_TO_PSRAM ; WLEDMM --> force all JSON stuff into PSRAM; gives more free heap @@ -1907,7 +1907,7 @@ build_flags = ${common.build_flags} ${esp32s3.build_flags} -Wno-misleading-inden ${common_mm.HUB75_build_flags} ${common_mm.animartrix_build_flags} -D WLED_RELEASE_NAME=esp32S3_4MB_S - -DARDUINO_USB_MODE=1 -DARDUINO_USB_CDC_ON_BOOT=0 -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=0 ;; for Serial-to-USB chip + -DARDUINO_USB_MODE=0 -DARDUINO_USB_CDC_ON_BOOT=0 -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=0 ;; changed from 1 to 0 to allow normal boot without USB debugger ;;-DARDUINO_USB_MODE=1 -DARDUINO_USB_CDC_ON_BOOT=1 -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=1 ;; for Hardware-CDC USB mode -D WLED_DISABLE_ADALIGHT ;; disables serial protocols - recommended for Hardware-CDC USB (Serial RX will receive junk commands when RX pin is unconnected, unless its pulled down by resistor) -D WLED_WATCHDOG_TIMEOUT=0 -D CONFIG_ASYNC_TCP_USE_WDT=0 @@ -1938,7 +1938,7 @@ build_flags = ${common.build_flags} ${esp32s3.build_flags} -Wno-misleading-inden ; -DBOARD_HAS_PSRAM -D WLED_USE_PSRAM_JSON -D WLED_USE_PSRAM ;; un-comment in case your board supports PSRAM ;; -D WLED_USE_PSRAM_JSON -DALL_JSON_TO_PSRAM ; WLEDMM --> force all JSON stuff into PSRAM; gives more free heap -D WLED_RELEASE_NAME=esp32S3_8MB_M - -DARDUINO_USB_MODE=1 -DARDUINO_USB_CDC_ON_BOOT=0 -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=0 ;; for Serial-to-USB chip + -DARDUINO_USB_MODE=0 -DARDUINO_USB_CDC_ON_BOOT=0 -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=0 ;; changed from 1 to 0 to allow normal boot without USB debugger ;;-DARDUINO_USB_MODE=1 -DARDUINO_USB_CDC_ON_BOOT=1 -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=1 ;; for Hardware-CDC USB mode ;;-D WLED_DISABLE_ADALIGHT ;; disables serial protocols - recommended for Hardware-CDC USB (Serial RX will receive junk commands when RX pin is unconnected, unless its pulled down by resistor) -D WLED_WATCHDOG_TIMEOUT=0 -D CONFIG_ASYNC_TCP_USE_WDT=0 @@ -1989,7 +1989,7 @@ build_flags = ${common.build_flags} ${esp32s3.build_flags} -Wno-misleading-inden -DBOARD_HAS_PSRAM ;; -D WLED_USE_PSRAM ;; your board supports PSRAM -D WLED_USE_PSRAM_JSON -DALL_JSON_TO_PSRAM ; WLEDMM --> force all JSON stuff into PSRAM; gives more free heap -D WLED_RELEASE_NAME=esp32S3_8MB_PSRAM_M - -DARDUINO_USB_MODE=1 -DARDUINO_USB_CDC_ON_BOOT=0 -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=0 ;; for Serial-to-USB chip + -DARDUINO_USB_MODE=0 -DARDUINO_USB_CDC_ON_BOOT=0 -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=0 ;; changed from 1 to 0 to allow normal boot without USB debugger ;;-DARDUINO_USB_MODE=1 -DARDUINO_USB_CDC_ON_BOOT=1 -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=1 ;; for Hardware-CDC USB mode ;;-D WLED_DISABLE_ADALIGHT ;; disables serial protocols - recommended for Hardware-CDC USB (Serial RX will receive junk commands when RX pin is unconnected, unless its pulled down by resistor) -D WLED_WATCHDOG_TIMEOUT=0 -D CONFIG_ASYNC_TCP_USE_WDT=0 @@ -2027,7 +2027,7 @@ build_unflags = ${env:esp32S3_8MB_M.build_unflags} ;; use the same as "normal" build_flags = ${common.build_flags} ${esp32s3.build_flags} -Wno-misleading-indentation -Wno-format-truncation ${common_mm.build_flags_S} -D WLED_RELEASE_NAME=esp32S3_8MB_S - -DARDUINO_USB_MODE=1 -DARDUINO_USB_CDC_ON_BOOT=0 -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=0 ;; for Serial-to-USB chip + -DARDUINO_USB_MODE=0 -DARDUINO_USB_CDC_ON_BOOT=0 -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=0 ;; changed from 1 to 0 to allow normal boot without USB debugger ;;-DARDUINO_USB_MODE=1 -DARDUINO_USB_CDC_ON_BOOT=1 -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=1 ;; for Hardware-CDC USB mode ;;-D WLED_DISABLE_ADALIGHT ;; disables serial protocols - recommended for Hardware-CDC USB (Serial RX will receive junk commands when RX pin is unconnected, unless its pulled down by resistor) ${Speed_Flags.build_flags_V4} ;; optimize for speed instead of size @@ -2090,7 +2090,7 @@ build_flags = ${common.build_flags} ${esp32s3.build_flags} -Wno-misleading-inden -D MAX_SEGMENT_DATA=40960 ;; default 32767 -DBOARD_HAS_PSRAM ;; -D WLED_USE_PSRAM ;; your board supports PSRAM -D WLED_USE_PSRAM_JSON -DALL_JSON_TO_PSRAM ; WLEDMM --> force all JSON stuff into PSRAM; gives more free heap - -DARDUINO_USB_MODE=1 -DARDUINO_USB_CDC_ON_BOOT=0 -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=0 ;; for Serial-to-USB chip + -DARDUINO_USB_MODE=0 -DARDUINO_USB_CDC_ON_BOOT=0 -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=0 ;; changed from 1 to 0 to allow normal boot without USB debugger ;; -DARDUINO_USB_MODE=1 -DARDUINO_USB_CDC_ON_BOOT=1 -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=1 ;; for Hardware-CDC USB mode -D WLED_WATCHDOG_TIMEOUT=0 -D CONFIG_ASYNC_TCP_USE_WDT=0 ;; -DUSERMOD_BATTERY_MEASUREMENT_PIN=2 ;; battery voltage pin @@ -2134,7 +2134,7 @@ build_flags = ${common.build_flags} ${esp32s3.build_flags} -Wno-misleading-inden -D WLEDMM_FASTPATH -DBOARD_HAS_PSRAM ;; -D WLED_USE_PSRAM ;; your board supports PSRAM -D WLED_USE_PSRAM_JSON -DALL_JSON_TO_PSRAM ; WLEDMM --> force all JSON stuff into PSRAM; gives more free heap - -DARDUINO_USB_MODE=1 -DARDUINO_USB_CDC_ON_BOOT=0 -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=0 ;; for Serial-to-USB chip + -DARDUINO_USB_MODE=0 -DARDUINO_USB_CDC_ON_BOOT=0 -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=0 ;; changed from 1 to 0 to allow normal boot without USB debugger ;;-DARDUINO_USB_MODE=1 -DARDUINO_USB_CDC_ON_BOOT=1 -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=1 ;; for Hardware-CDC USB mode -D WLED_WATCHDOG_TIMEOUT=0 -D CONFIG_ASYNC_TCP_USE_WDT=0 ;; -D LEDPIN=38 ;; buildin LED @@ -2160,7 +2160,7 @@ build_flags = ${common.build_flags} ${esp32s3.build_flags} -Wno-misleading-inden -D WLED_USE_PSRAM_JSON -DALL_JSON_TO_PSRAM ; WLEDMM --> force all JSON stuff into PSRAM; gives more free heap -DCONFIG_MBEDTLS_DYNAMIC_BUFFER=1 ;; optional - allows some buffers to use PSRAM -DLOLIN_WIFI_FIX -DWLEDMM_WIFI_POWERON_HACK ;; seems to work much better with this - -DARDUINO_USB_MODE=1 -DARDUINO_USB_CDC_ON_BOOT=0 -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=1 ;; for Serial-to-USB chip + -DARDUINO_USB_MODE=0 -DARDUINO_USB_CDC_ON_BOOT=0 -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=1 ;; changed from 1 to 0 to allow normal boot without USB debugger ;;-DARDUINO_USB_MODE=1 -DARDUINO_USB_CDC_ON_BOOT=1 -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=1 ;; for Hardware-CDC USB mode -D WLED_DISABLE_ADALIGHT ;; disables serial protocols - recommended for Hardware-CDC USB (Serial RX will receive junk commands when RX pin is unconnected, unless its pulled down by resistor) ${Speed_Flags.build_flags_V4} ;; optimize for speed instead of size @@ -2205,7 +2205,7 @@ build_flags = ${common.build_flags} ${esp32s3.build_flags} -Wno-misleading-inden -D WLED_USE_PSRAM_JSON -DALL_JSON_TO_PSRAM ; WLEDMM --> force all JSON stuff into PSRAM; gives more free heap -DCONFIG_MBEDTLS_DYNAMIC_BUFFER=1 ;; optional - allows some buffers to use PSRAM -DLOLIN_WIFI_FIX -DWLEDMM_WIFI_POWERON_HACK ;; seems to work much better with this - -DARDUINO_USB_MODE=1 -DARDUINO_USB_CDC_ON_BOOT=0 -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=1 ;; for Serial-to-USB chip + -DARDUINO_USB_MODE=0 -DARDUINO_USB_CDC_ON_BOOT=0 -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=1 ;; changed from 1 to 0 to allow normal boot without USB debugger ;;-DARDUINO_USB_MODE=1 -DARDUINO_USB_CDC_ON_BOOT=1 -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=1 ;; for Hardware-CDC USB mode -D WLED_DISABLE_ADALIGHT ;; disables serial protocols - recommended for Hardware-CDC USB (Serial RX will receive junk commands when RX pin is unconnected, unless its pulled down by resistor) ;; ${common_mm.animartrix_build_flags} ;; not enough flash From 49a1399ed676d4b87eeb3275ecf84b495b1452a1 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 20 Sep 2025 11:38:25 +0000 Subject: [PATCH 004/170] Fix AutoPlaylist race condition: use CALL_MODE_NOTIFICATION for AutoChange presets Co-authored-by: netmindz <442066+netmindz@users.noreply.github.com> --- usermods/usermod_v2_auto_playlist/usermod_v2_auto_playlist.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usermods/usermod_v2_auto_playlist/usermod_v2_auto_playlist.h b/usermods/usermod_v2_auto_playlist/usermod_v2_auto_playlist.h index a4c557dd..15a55e27 100644 --- a/usermods/usermod_v2_auto_playlist/usermod_v2_auto_playlist.h +++ b/usermods/usermod_v2_auto_playlist/usermod_v2_auto_playlist.h @@ -257,7 +257,7 @@ class AutoPlaylistUsermod : public Usermod { // after change_lockout. Better for smaller change_lockout values. suspendPlaylist(); // suspend the playlist engine before changing to another preset - applyPreset(newpreset); + applyPreset(newpreset, CALL_MODE_NOTIFICATION); #ifdef USERMOD_AUTO_PLAYLIST_DEBUG USER_PRINTF("*** CHANGE distance = %4lu - change_interval was %5ldms - next change_threshold is %4u (%4u diff aprox)\n",(unsigned long)distance,change_interval,change_threshold,change_threshold_change); From e094d60552c98583249ccf374b55c842158aaa1f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 20 Sep 2025 12:06:19 +0000 Subject: [PATCH 005/170] Implement conditional ARDUINO_USB_MODE: dev=1, release=0 Co-authored-by: netmindz <442066+netmindz@users.noreply.github.com> --- pio-scripts/conditional_usb_mode.py | 73 +++++++++++++++++++++++++++++ platformio.ini | 21 +++++---- 2 files changed, 84 insertions(+), 10 deletions(-) create mode 100644 pio-scripts/conditional_usb_mode.py diff --git a/pio-scripts/conditional_usb_mode.py b/pio-scripts/conditional_usb_mode.py new file mode 100644 index 00000000..170eb923 --- /dev/null +++ b/pio-scripts/conditional_usb_mode.py @@ -0,0 +1,73 @@ +#!/usr/bin/env python3 +""" +Conditional USB Mode Script for WLED-MM + +This script automatically sets ARDUINO_USB_MODE based on the build context: +- For development builds: ARDUINO_USB_MODE=1 (allows USB debugging) +- For release builds (CI): ARDUINO_USB_MODE=0 (allows normal boot without USB debugger) + +The script detects release builds by checking for the WLED_RELEASE environment variable +which is set to True in the GitHub Actions CI workflow. +""" + +Import('env') +import os + +def conditional_usb_mode(env): + """ + Conditionally set ARDUINO_USB_MODE based on build context. + + For ESP32-C3, ESP32-S2, and ESP32-S3 variants: + - Development builds: ARDUINO_USB_MODE=1 (default, good for debugging) + - Release builds: ARDUINO_USB_MODE=0 (prevents hanging without USB debugger) + """ + + # Check if this is a release build (CI sets WLED_RELEASE=True) + is_release_build = os.environ.get('WLED_RELEASE', '').lower() in ('true', '1', 'yes') + + if is_release_build: + print("WLED Release build detected - setting ARDUINO_USB_MODE=0 for production") + + # Find and modify ARDUINO_USB_MODE in build flags + build_flags = env.get('BUILD_FLAGS', []) + cpp_defines = env.get('CPPDEFINES', []) + + # Look through CPPDEFINES and modify ARDUINO_USB_MODE if found + modified = False + new_defines = [] + + for define in cpp_defines: + if isinstance(define, (list, tuple)) and len(define) == 2: + if define[0] == 'ARDUINO_USB_MODE' and define[1] == '1': + # Change ARDUINO_USB_MODE from 1 to 0 for release builds + new_defines.append(('ARDUINO_USB_MODE', '0')) + modified = True + print(f" Changed ARDUINO_USB_MODE from 1 to 0") + else: + new_defines.append(define) + else: + new_defines.append(define) + + if modified: + env.Replace(CPPDEFINES=new_defines) + + # Also check raw build flags for -DARDUINO_USB_MODE=1 + new_build_flags = [] + for flag in build_flags: + if isinstance(flag, str) and 'ARDUINO_USB_MODE=1' in flag: + # Replace ARDUINO_USB_MODE=1 with ARDUINO_USB_MODE=0 + new_flag = flag.replace('ARDUINO_USB_MODE=1', 'ARDUINO_USB_MODE=0') + new_build_flags.append(new_flag) + modified = True + print(f" Modified build flag: {flag} -> {new_flag}") + else: + new_build_flags.append(flag) + + if modified: + env.Replace(BUILD_FLAGS=new_build_flags) + + else: + print("Development build detected - keeping ARDUINO_USB_MODE=1 for debugging") + +# Apply the conditional USB mode logic +conditional_usb_mode(env) \ No newline at end of file diff --git a/platformio.ini b/platformio.ini index b5f51b1e..ecdb65ce 100644 --- a/platformio.ini +++ b/platformio.ini @@ -220,6 +220,7 @@ ldscript_16m14m = eagle.flash.16m14m.ld extra_scripts = pre:pio-scripts/set_version.py pre:pio-scripts/build-html.py + pre:pio-scripts/conditional_usb_mode.py post:pio-scripts/output_bins.py post:pio-scripts/strip-floats.py pre:pio-scripts/user_config_copy.py @@ -455,7 +456,7 @@ build_flags = -g -D CONFIG_ASYNC_TCP_USE_WDT=0 -D CONFIG_ASYNC_TCP_TASK_STACK_SIZE=9472 ;; WLEDMM increase stack by 1.25Kb, as audioreactive needs bigger SETTINGS_STACK_BUF_SIZE -DCO - -DARDUINO_USB_MODE=0 ;; changed from 1 to 0 to allow normal boot without USB debugger + -DARDUINO_USB_MODE=1 ;; this flag is mandatory for ESP32-C3 ;; please make sure that the following flags are properly set (to 0 or 1) by your board.json, or included in your custom platformio_override.ini entry: ;; ARDUINO_USB_CDC_ON_BOOT @@ -702,7 +703,7 @@ build_unflags = ${common.build_unflags} build_flags = ${common.build_flags} ${esp32s3.build_flags} -D CONFIG_LITTLEFS_FOR_IDF_3_2 -D WLED_WATCHDOG_TIMEOUT=0 ;-D ARDUINO_USB_CDC_ON_BOOT=0 ;; -D ARDUINO_USB_MODE=1 ;; for boards with serial-to-USB chip - -D ARDUINO_USB_CDC_ON_BOOT=1 -D ARDUINO_USB_MODE=0 ;; changed from 1 to 0 to allow normal boot without USB debugger + -D ARDUINO_USB_CDC_ON_BOOT=1 -D ARDUINO_USB_MODE=1 ;; for boards with USB-OTG connector only (USBCDC or "TinyUSB") ; -D WLED_RELEASE_NAME=ESP32-S3_PSRAM -D WLED_USE_PSRAM -DBOARD_HAS_PSRAM ; tells WLED that PSRAM shall be used -D WLED_USE_PSRAM_JSON -DALL_JSON_TO_PSRAM ; WLEDMM --> force all JSON stuff into PSRAM; gives more free heap @@ -1907,7 +1908,7 @@ build_flags = ${common.build_flags} ${esp32s3.build_flags} -Wno-misleading-inden ${common_mm.HUB75_build_flags} ${common_mm.animartrix_build_flags} -D WLED_RELEASE_NAME=esp32S3_4MB_S - -DARDUINO_USB_MODE=0 -DARDUINO_USB_CDC_ON_BOOT=0 -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=0 ;; changed from 1 to 0 to allow normal boot without USB debugger + -DARDUINO_USB_MODE=1 -DARDUINO_USB_CDC_ON_BOOT=0 -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=0 ;; for Serial-to-USB chip ;;-DARDUINO_USB_MODE=1 -DARDUINO_USB_CDC_ON_BOOT=1 -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=1 ;; for Hardware-CDC USB mode -D WLED_DISABLE_ADALIGHT ;; disables serial protocols - recommended for Hardware-CDC USB (Serial RX will receive junk commands when RX pin is unconnected, unless its pulled down by resistor) -D WLED_WATCHDOG_TIMEOUT=0 -D CONFIG_ASYNC_TCP_USE_WDT=0 @@ -1938,7 +1939,7 @@ build_flags = ${common.build_flags} ${esp32s3.build_flags} -Wno-misleading-inden ; -DBOARD_HAS_PSRAM -D WLED_USE_PSRAM_JSON -D WLED_USE_PSRAM ;; un-comment in case your board supports PSRAM ;; -D WLED_USE_PSRAM_JSON -DALL_JSON_TO_PSRAM ; WLEDMM --> force all JSON stuff into PSRAM; gives more free heap -D WLED_RELEASE_NAME=esp32S3_8MB_M - -DARDUINO_USB_MODE=0 -DARDUINO_USB_CDC_ON_BOOT=0 -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=0 ;; changed from 1 to 0 to allow normal boot without USB debugger + -DARDUINO_USB_MODE=1 -DARDUINO_USB_CDC_ON_BOOT=0 -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=0 ;; for Serial-to-USB chip ;;-DARDUINO_USB_MODE=1 -DARDUINO_USB_CDC_ON_BOOT=1 -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=1 ;; for Hardware-CDC USB mode ;;-D WLED_DISABLE_ADALIGHT ;; disables serial protocols - recommended for Hardware-CDC USB (Serial RX will receive junk commands when RX pin is unconnected, unless its pulled down by resistor) -D WLED_WATCHDOG_TIMEOUT=0 -D CONFIG_ASYNC_TCP_USE_WDT=0 @@ -1989,7 +1990,7 @@ build_flags = ${common.build_flags} ${esp32s3.build_flags} -Wno-misleading-inden -DBOARD_HAS_PSRAM ;; -D WLED_USE_PSRAM ;; your board supports PSRAM -D WLED_USE_PSRAM_JSON -DALL_JSON_TO_PSRAM ; WLEDMM --> force all JSON stuff into PSRAM; gives more free heap -D WLED_RELEASE_NAME=esp32S3_8MB_PSRAM_M - -DARDUINO_USB_MODE=0 -DARDUINO_USB_CDC_ON_BOOT=0 -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=0 ;; changed from 1 to 0 to allow normal boot without USB debugger + -DARDUINO_USB_MODE=1 -DARDUINO_USB_CDC_ON_BOOT=0 -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=0 ;; for Serial-to-USB chip ;;-DARDUINO_USB_MODE=1 -DARDUINO_USB_CDC_ON_BOOT=1 -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=1 ;; for Hardware-CDC USB mode ;;-D WLED_DISABLE_ADALIGHT ;; disables serial protocols - recommended for Hardware-CDC USB (Serial RX will receive junk commands when RX pin is unconnected, unless its pulled down by resistor) -D WLED_WATCHDOG_TIMEOUT=0 -D CONFIG_ASYNC_TCP_USE_WDT=0 @@ -2027,7 +2028,7 @@ build_unflags = ${env:esp32S3_8MB_M.build_unflags} ;; use the same as "normal" build_flags = ${common.build_flags} ${esp32s3.build_flags} -Wno-misleading-indentation -Wno-format-truncation ${common_mm.build_flags_S} -D WLED_RELEASE_NAME=esp32S3_8MB_S - -DARDUINO_USB_MODE=0 -DARDUINO_USB_CDC_ON_BOOT=0 -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=0 ;; changed from 1 to 0 to allow normal boot without USB debugger + -DARDUINO_USB_MODE=1 -DARDUINO_USB_CDC_ON_BOOT=0 -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=0 ;; for Serial-to-USB chip ;;-DARDUINO_USB_MODE=1 -DARDUINO_USB_CDC_ON_BOOT=1 -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=1 ;; for Hardware-CDC USB mode ;;-D WLED_DISABLE_ADALIGHT ;; disables serial protocols - recommended for Hardware-CDC USB (Serial RX will receive junk commands when RX pin is unconnected, unless its pulled down by resistor) ${Speed_Flags.build_flags_V4} ;; optimize for speed instead of size @@ -2090,7 +2091,7 @@ build_flags = ${common.build_flags} ${esp32s3.build_flags} -Wno-misleading-inden -D MAX_SEGMENT_DATA=40960 ;; default 32767 -DBOARD_HAS_PSRAM ;; -D WLED_USE_PSRAM ;; your board supports PSRAM -D WLED_USE_PSRAM_JSON -DALL_JSON_TO_PSRAM ; WLEDMM --> force all JSON stuff into PSRAM; gives more free heap - -DARDUINO_USB_MODE=0 -DARDUINO_USB_CDC_ON_BOOT=0 -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=0 ;; changed from 1 to 0 to allow normal boot without USB debugger + -DARDUINO_USB_MODE=1 -DARDUINO_USB_CDC_ON_BOOT=0 -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=0 ;; for Serial-to-USB chip ;; -DARDUINO_USB_MODE=1 -DARDUINO_USB_CDC_ON_BOOT=1 -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=1 ;; for Hardware-CDC USB mode -D WLED_WATCHDOG_TIMEOUT=0 -D CONFIG_ASYNC_TCP_USE_WDT=0 ;; -DUSERMOD_BATTERY_MEASUREMENT_PIN=2 ;; battery voltage pin @@ -2134,7 +2135,7 @@ build_flags = ${common.build_flags} ${esp32s3.build_flags} -Wno-misleading-inden -D WLEDMM_FASTPATH -DBOARD_HAS_PSRAM ;; -D WLED_USE_PSRAM ;; your board supports PSRAM -D WLED_USE_PSRAM_JSON -DALL_JSON_TO_PSRAM ; WLEDMM --> force all JSON stuff into PSRAM; gives more free heap - -DARDUINO_USB_MODE=0 -DARDUINO_USB_CDC_ON_BOOT=0 -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=0 ;; changed from 1 to 0 to allow normal boot without USB debugger + -DARDUINO_USB_MODE=1 -DARDUINO_USB_CDC_ON_BOOT=0 -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=0 ;; for Serial-to-USB chip ;;-DARDUINO_USB_MODE=1 -DARDUINO_USB_CDC_ON_BOOT=1 -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=1 ;; for Hardware-CDC USB mode -D WLED_WATCHDOG_TIMEOUT=0 -D CONFIG_ASYNC_TCP_USE_WDT=0 ;; -D LEDPIN=38 ;; buildin LED @@ -2160,7 +2161,7 @@ build_flags = ${common.build_flags} ${esp32s3.build_flags} -Wno-misleading-inden -D WLED_USE_PSRAM_JSON -DALL_JSON_TO_PSRAM ; WLEDMM --> force all JSON stuff into PSRAM; gives more free heap -DCONFIG_MBEDTLS_DYNAMIC_BUFFER=1 ;; optional - allows some buffers to use PSRAM -DLOLIN_WIFI_FIX -DWLEDMM_WIFI_POWERON_HACK ;; seems to work much better with this - -DARDUINO_USB_MODE=0 -DARDUINO_USB_CDC_ON_BOOT=0 -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=1 ;; changed from 1 to 0 to allow normal boot without USB debugger + -DARDUINO_USB_MODE=1 -DARDUINO_USB_CDC_ON_BOOT=0 -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=1 ;; for Serial-to-USB chip ;;-DARDUINO_USB_MODE=1 -DARDUINO_USB_CDC_ON_BOOT=1 -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=1 ;; for Hardware-CDC USB mode -D WLED_DISABLE_ADALIGHT ;; disables serial protocols - recommended for Hardware-CDC USB (Serial RX will receive junk commands when RX pin is unconnected, unless its pulled down by resistor) ${Speed_Flags.build_flags_V4} ;; optimize for speed instead of size @@ -2205,7 +2206,7 @@ build_flags = ${common.build_flags} ${esp32s3.build_flags} -Wno-misleading-inden -D WLED_USE_PSRAM_JSON -DALL_JSON_TO_PSRAM ; WLEDMM --> force all JSON stuff into PSRAM; gives more free heap -DCONFIG_MBEDTLS_DYNAMIC_BUFFER=1 ;; optional - allows some buffers to use PSRAM -DLOLIN_WIFI_FIX -DWLEDMM_WIFI_POWERON_HACK ;; seems to work much better with this - -DARDUINO_USB_MODE=0 -DARDUINO_USB_CDC_ON_BOOT=0 -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=1 ;; changed from 1 to 0 to allow normal boot without USB debugger + -DARDUINO_USB_MODE=1 -DARDUINO_USB_CDC_ON_BOOT=0 -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=1 ;; for Serial-to-USB chip ;;-DARDUINO_USB_MODE=1 -DARDUINO_USB_CDC_ON_BOOT=1 -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=1 ;; for Hardware-CDC USB mode -D WLED_DISABLE_ADALIGHT ;; disables serial protocols - recommended for Hardware-CDC USB (Serial RX will receive junk commands when RX pin is unconnected, unless its pulled down by resistor) ;; ${common_mm.animartrix_build_flags} ;; not enough flash From 8067f1f70c9c773b60b4b4ccf376488052209fa0 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Mon, 20 Oct 2025 21:49:09 +0200 Subject: [PATCH 006/170] bus.setPicelColor optimization: move colorBalanceFromKelvin into busmanager.cpp colorBalanceFromKelvin() is only called from inside bus_manager.cpp, so we can help the compiler optimize by making it a local (static) fuction --- wled00/bus_manager.cpp | 18 ++++++++++++++++++ wled00/colors.cpp | 3 +++ wled00/fcn_declare.h | 2 +- 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/wled00/bus_manager.cpp b/wled00/bus_manager.cpp index e4e70507..73072e97 100644 --- a/wled00/bus_manager.cpp +++ b/wled00/bus_manager.cpp @@ -79,6 +79,24 @@ uint8_t realtimeBroadcast(uint8_t type, IPAddress client, uint16_t length, byte #include "wled.h" #endif +// WLEDMM moved here (from colors.cpp) for better optimization +static inline uint32_t __attribute__((hot)) colorBalanceFromKelvin(uint16_t kelvin, uint32_t rgb) // WLEDMM: IRAM_ATTR removed, inline for speed +{ + //remember so that slow colorKtoRGB() doesn't have to run for every setPixelColor() + static byte correctionRGB[4] = {255,255,255,0}; // default to neutral + static uint16_t lastKelvin = 0; + if (lastKelvin != kelvin) { + colorKtoRGB(kelvin, correctionRGB); // convert Kelvin to RGB (slow) + lastKelvin = kelvin; + } + byte rgbw[4]; + rgbw[0] = ((uint_fast16_t) correctionRGB[0] * R(rgb)) /255; // correct R //WLEDMM changed to fast type + rgbw[1] = ((uint_fast16_t) correctionRGB[1] * G(rgb)) /255; // correct G + rgbw[2] = ((uint_fast16_t) correctionRGB[2] * B(rgb)) /255; // correct B + rgbw[3] = W(rgb); + return RGBW32(rgbw[0],rgbw[1],rgbw[2],rgbw[3]); +} + void ColorOrderMap::add(uint16_t start, uint16_t len, uint8_t colorOrder) { if (_count >= WLED_MAX_COLOR_ORDER_MAPPINGS) { diff --git a/wled00/colors.cpp b/wled00/colors.cpp index 37241959..8e72d46b 100644 --- a/wled00/colors.cpp +++ b/wled00/colors.cpp @@ -310,6 +310,8 @@ static float maxf (float v, float w) // WLEDMM better use standard library fmax // adjust RGB values based on color temperature in K (range [2800-10200]) (https://en.wikipedia.org/wiki/Color_balance) // called from bus manager when color correction is enabled! +#if 0 +// WLEDMM moved into bus_manager.cpp for better optimization uint32_t __attribute__((hot)) IRAM_ATTR_YN colorBalanceFromKelvin(uint16_t kelvin, uint32_t rgb) // WLEDMM: IRAM_ATTR_YN { //remember so that slow colorKtoRGB() doesn't have to run for every setPixelColor() @@ -324,6 +326,7 @@ uint32_t __attribute__((hot)) IRAM_ATTR_YN colorBalanceFromKelvin(uint16_t kelvi rgbw[3] = W(rgb); return RGBW32(rgbw[0],rgbw[1],rgbw[2],rgbw[3]); } +#endif //approximates a Kelvin color temperature from an RGB color. //this does no check for the "whiteness" of the color, diff --git a/wled00/fcn_declare.h b/wled00/fcn_declare.h index 1a9247a2..188c10ee 100644 --- a/wled00/fcn_declare.h +++ b/wled00/fcn_declare.h @@ -66,7 +66,7 @@ void colorXYtoRGB(float x, float y, byte* rgb); // only defined if huesync disab void colorRGBtoXY(byte* rgb, float* xy); // only defined if huesync disabled TODO void colorFromDecOrHexString(byte* rgb, char* in); bool colorFromHexString(byte* rgb, const char* in); -uint32_t colorBalanceFromKelvin(uint16_t kelvin, uint32_t rgb); +//uint32_t colorBalanceFromKelvin(uint16_t kelvin, uint32_t rgb); // WLEDMM function moved into bus_manager.cpp for better optimization uint16_t __attribute__((const)) approximateKelvinFromRGB(uint32_t rgb); // WLEDMM: added attribute const void setRandomColor(byte* rgb); uint8_t gamma8_cal(uint8_t b, float gamma); From 6e8ab94ee9d102c4a5d780eef2a8c9339639c33d Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Mon, 20 Oct 2025 21:53:37 +0200 Subject: [PATCH 007/170] colorKtoRGB optimization and bugfix * bug: logf(temp-10) result becomes NaN when kelvin < 1200 * bug (RISC-V only): parameter of Bus::setCCT must be signed, to avoid undefined behaviour * minor optimization by replacing constrain() with min(max()) --- wled00/bus_manager.h | 2 +- wled00/colors.cpp | 22 +++++++++++++++++----- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/wled00/bus_manager.h b/wled00/bus_manager.h index 04062215..e49238d6 100644 --- a/wled00/bus_manager.h +++ b/wled00/bus_manager.h @@ -175,7 +175,7 @@ class Bus { _type == TYPE_ANALOG_2CH || _type == TYPE_ANALOG_5CH) return true; return false; } - static void setCCT(uint16_t cct) { + static void setCCT(int16_t cct) { // WLEDMM bugfix: parameter must be signed, otherwise "-1" becomes 65535 --> undefined behaviour on RISC-V _cct = cct; } static void setCCTBlend(uint8_t b) { diff --git a/wled00/colors.cpp b/wled00/colors.cpp index 8e72d46b..36cb1b4b 100644 --- a/wled00/colors.cpp +++ b/wled00/colors.cpp @@ -142,25 +142,37 @@ void colorHStoRGB(uint16_t hue, byte sat, byte* rgb) //hue, sat to rgb //get RGB values from color temperature in K (https://tannerhelland.com/2012/09/18/convert-temperature-rgb-algorithm-code.html) void colorKtoRGB(uint16_t kelvin, byte* rgb) //white spectrum to rgb, calc { + // WLEDMM safe exit (do nothing) to avoid logf domain errors. argument to logf must be >= 1.0f to avoid bad result 0 or -inf; + // kelvin >65k might be a signed/unsigned conversion error + if ((kelvin < 1200) || (kelvin > 65000)) { + rgb[0] = 255; + rgb[1] = 255; + rgb[2] = 255; + rgb[3] = 0; + return; + } + int r = 0, g = 0, b = 0; - float temp = kelvin / 100.0f; + float temp = float(kelvin) / 100.0f; // WLEDMM "float()" added - to make sure its done in float, not in double or int if (temp <= 66.0f) { r = 255; g = roundf(99.4708025861f * logf(temp) - 161.1195681661f); if (temp <= 19.0f) { b = 0; } else { - b = roundf(138.5177312231f * logf((temp - 10.0f)) - 305.0447927307f); + b = roundf(138.5177312231f * logf((temp - 10.0f)) - 305.0447927307f); // safe because temp > 19.0f } } else { + // temp-60.0f is always > 0 here (since temp>66) r = roundf(329.698727446f * powf((temp - 60.0f), -0.1332047592f)); g = roundf(288.1221695283f * powf((temp - 60.0f), -0.0755148492f)); b = 255; } //g += 12; //mod by Aircoookie, a bit less accurate but visibly less pinkish - rgb[0] = (uint8_t) constrain(r, 0, 255); - rgb[1] = (uint8_t) constrain(g, 0, 255); - rgb[2] = (uint8_t) constrain(b, 0, 255); + // WLEDMM min(max()) is faster than constrain() + rgb[0] = (uint8_t) min(max(r, 0), 255); + rgb[1] = (uint8_t) min(max(g, 0), 255); + rgb[2] = (uint8_t) min(max(b, 0), 255); rgb[3] = 0; } From 541b2018558fd00afec6f7dc09fca11a1d124433 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Mon, 20 Oct 2025 21:58:23 +0200 Subject: [PATCH 008/170] bus.setPicelColor optimization: optimizing some CPU cycles out of the hot path in sPC and gPC * optimize loops that scan through all busses * small speedups for Bus::autoWhiteCalc() * small speedups for ColorOrderMap::getPixelColorOrder() thanks to github Copilot for giving me the right ideas for this optimization --- wled00/bus_manager.cpp | 107 ++++++++++++++++++++++++----------------- wled00/bus_manager.h | 7 +-- 2 files changed, 67 insertions(+), 47 deletions(-) diff --git a/wled00/bus_manager.cpp b/wled00/bus_manager.cpp index 73072e97..d843f4e6 100644 --- a/wled00/bus_manager.cpp +++ b/wled00/bus_manager.cpp @@ -114,31 +114,40 @@ void ColorOrderMap::add(uint16_t start, uint16_t len, uint8_t colorOrder) { _count++; } -uint8_t IRAM_ATTR ColorOrderMap::getPixelColorOrder(uint16_t pix, uint8_t defaultColorOrder) const { +uint8_t __attribute__((hot)) ColorOrderMap::getPixelColorOrder(uint16_t pix, uint8_t defaultColorOrder) const { if (_count == 0) return defaultColorOrder; - // upper nibble contains W swap information - uint8_t swapW = defaultColorOrder >> 4; - for (uint8_t i = 0; i < _count; i++) { - if (pix >= _mappings[i].start && pix < (_mappings[i].start + _mappings[i].len)) { - return _mappings[i].colorOrder | (swapW << 4); + // upper nibble contains W swap information // WLEDMM optimization: avoid shifting >>4 and later undo by <<4 + uint8_t swapW = defaultColorOrder & 0xF0; + // Scan mappings, using unsigned range test: pix in [start, start+len) + for (uint_fast8_t i = 0, n = _count; i < n; i++) { // WLEDMM small speedup, by avoiding repeated class member access + const auto &m = _mappings[i]; // WLEDMM help the compiler to optimize + if ((uint16_t)(pix - m.start) < m.len) { // True iff m.len > 0 and pix >= m.start and pix < m.start + m.len + return (m.colorOrder & 0x0F) | swapW; // add W swap information } } return defaultColorOrder; } -uint32_t Bus::autoWhiteCalc(uint32_t c) const { - uint8_t aWM = _autoWhiteMode; - if (_gAWM != AW_GLOBAL_DISABLED) aWM = _gAWM; +uint32_t __attribute__((hot)) Bus::autoWhiteCalc(uint32_t c) const { + uint8_t aWM = (_gAWM != AW_GLOBAL_DISABLED) ? _gAWM : _autoWhiteMode; if (aWM == RGBW_MODE_MANUAL_ONLY) return c; - uint8_t w = W(c); + uint_fast8_t w = W(c); //ignore auto-white calculation if w>0 and mode DUAL (DUAL behaves as BRIGHTER if w==0) if (w > 0 && aWM == RGBW_MODE_DUAL) return c; - uint8_t r = R(c); - uint8_t g = G(c); - uint8_t b = B(c); - if (aWM == RGBW_MODE_MAX) return RGBW32(r, g, b, r > g ? (r > b ? r : b) : (g > b ? g : b)); // brightest RGB channel - w = r < g ? (r < b ? r : b) : (g < b ? g : b); + + uint_fast8_t r = R(c); + uint_fast8_t g = G(c); + uint_fast8_t b = B(c); + // brightest RGB channel + if (aWM == RGBW_MODE_MAX) { // WLEDMM use max() instead of several nested conditions + w = max(r, g); + w = max(w, b); + return RGBW32(r, g, b, w); + } + // Other modes: smallest RGB channel // WLEDMM use min() instead of several nested conditions + w = min(r, g); + w = min(w, b); if (aWM == RGBW_MODE_AUTO_ACCURATE) { r -= w; g -= w; b -= w; } //subtract w in ACCURATE mode return RGBW32(r, g, b, w); } @@ -1231,7 +1240,7 @@ uint32_t BusManager::memUsage(BusConfig &bc) { int BusManager::add(BusConfig &bc) { if (getNumBusses() - getNumVirtualBusses() >= WLED_MAX_BUSSES) return -1; // WLEDMM clear cached Bus info first - lastend = 0; + lastlen = 0; laststart = 0; lastBus = nullptr; slowMode = false; @@ -1272,7 +1281,7 @@ void BusManager::removeAll() { // WLEDMM clear cached Bus info lastBus = nullptr; laststart = 0; - lastend = 0; + lastlen = 0; slowMode = false; } @@ -1293,24 +1302,28 @@ void BusManager::setStatusPixel(uint32_t c) { } } -void IRAM_ATTR __attribute__((hot)) BusManager::setPixelColor(uint16_t pix, uint32_t c, int16_t cct) { - if (!slowMode && (pix >= laststart) && (pix < lastend ) && lastBus->isOk()) { - // WLEDMM same bus as last time - no need to search again +void IRAM_ATTR __attribute__((hot)) BusManager::setPixelColor(uint16_t pix, uint32_t c) { + // Fast path: check cached bus first (with proper nullptr check) + // optimization: below is True iff lastlen > 0 and pix >= laststart and pix < laststart + lastlen + if (!slowMode && lastBus && ((uint_fast16_t)(pix - laststart) < lastlen) && lastBus->isOk()) { // WLEDMM saves us a few cycles for each pixel lastBus->setPixelColor(pix - laststart, c); return; } - for (uint_fast8_t i = 0; i < numBusses; i++) { // WLEDMM use fast native types - Bus* b = busses[i]; - if (b->isOk() == false) continue; // WLEDMM ignore invalid (=not ready) busses + // Slow path: search through all buses + uint_fast8_t count = numBusses; // Cache to avoid repeated member access + for (uint_fast8_t i = 0; i < count; i++) { + Bus* const b = busses[i]; // Use const pointer for optimization hint + if ((!b) || (b->isOk() == false)) continue; // WLEDMM ignore invalid (=not ready) busses uint_fast16_t bstart = b->getStart(); - if (pix < bstart || pix >= bstart + b->getLength()) continue; - else { + uint_fast16_t blen = b->getLength(); + + if ((uint_fast16_t)(pix - bstart) < blen) { // Unsigned arithmetic trick for fast range check if (!slowMode) { - // WLEDMM remember last Bus we took + // Cache bus info for next call lastBus = b; laststart = bstart; - lastend = bstart + b->getLength(); + lastlen = blen; } b->setPixelColor(pix - bstart, c); if (!slowMode) break; // WLEDMM found the right Bus -> so we can stop searching - unless we have busses that overlap @@ -1334,46 +1347,52 @@ void __attribute__((cold)) BusManager::setSegmentCCT(int16_t cct, bool allowWBCo } uint32_t IRAM_ATTR __attribute__((hot)) BusManager::getPixelColor(uint_fast16_t pix) { // WLEDMM use fast native types, IRAM_ATTR - if ((pix >= laststart) && (pix < lastend ) && (lastBus != nullptr) && lastBus->isOk()) { + // Fast path: check cached bus first (with proper null check, and unsigned arithmetic trick for faster range check) + if (lastBus && ((uint_fast16_t)(pix - laststart) < lastlen) && lastBus->isOk()) { // WLEDMM same bus as last time - no need to search again return lastBus->getPixelColor(pix - laststart); } - for (uint_fast8_t i = 0; i < numBusses; i++) { - Bus* b = busses[i]; - if (b->isOk() == false) continue; // WLEDMM ignore invalid (=not ready) busses + uint_fast8_t count = numBusses; // Cache to avoid repeated member access + for (uint_fast8_t i = 0; i < count; i++) { + Bus* const b = busses[i]; // Use const pointer for optimization hint + if ((!b) || (b->isOk() == false)) continue; // WLEDMM ignore invalid (=not ready) busses uint_fast16_t bstart = b->getStart(); - if (pix < bstart || pix >= bstart + b->getLength()) continue; - else { + uint_fast16_t blen = b->getLength(); + + if ((uint_fast16_t)(pix - bstart) < blen) { // Unsigned arithmetic trick for fast range check if (!slowMode) { - // WLEDMM remember last Bus we took + // Cache bus info for next call lastBus = b; laststart = bstart; - lastend = bstart + b->getLength(); + lastlen = blen; } - return b->getPixelColor(pix - bstart); + return b->getPixelColor(pix - bstart); // done - found one } } return 0; } uint32_t IRAM_ATTR __attribute__((hot)) BusManager::getPixelColorRestored(uint_fast16_t pix) { // WLEDMM uses bus::getPixelColorRestored() - if ((pix >= laststart) && (pix < lastend ) && (lastBus != nullptr) && lastBus->isOk()) { + // Fast path: check cached bus first (with proper null check, and unsigned arithmetic trick for faster range check) + if (lastBus && ((uint_fast16_t)(pix - laststart) < lastlen) && lastBus->isOk()) { // WLEDMM same bus as last time - no need to search again return lastBus->getPixelColorRestored(pix - laststart); } - for (uint_fast8_t i = 0; i < numBusses; i++) { - Bus* b = busses[i]; - if (b->isOk() == false) continue; // WLEDMM ignore invalid (=not ready) busses + uint_fast8_t count = numBusses; // Cache to avoid repeated member access + for (uint_fast8_t i = 0; i < count; i++) { + Bus* const b = busses[i]; // Use const pointer for optimization hint + if ((!b) || (b->isOk() == false)) continue; // WLEDMM ignore invalid (=not ready) busses uint_fast16_t bstart = b->getStart(); - if (pix < bstart || pix >= bstart + b->getLength()) continue; - else { + uint_fast16_t blen = b->getLength(); + + if ((uint_fast16_t)(pix - bstart) < blen) { // Unsigned arithmetic trick for range check if (!slowMode) { - // WLEDMM remember last Bus we took + // Cache bus info for next call lastBus = b; laststart = bstart; - lastend = bstart + b->getLength(); + lastlen = blen; } return b->getPixelColorRestored(pix - bstart); } diff --git a/wled00/bus_manager.h b/wled00/bus_manager.h index e49238d6..ea886eaf 100644 --- a/wled00/bus_manager.h +++ b/wled00/bus_manager.h @@ -463,13 +463,14 @@ class BusManager { // WLEDMM clear cached Bus info lastBus = nullptr; laststart = 0; - lastend = 0; + lastlen= 0; slowMode = isRTMode; } void setStatusPixel(uint32_t c); - void setPixelColor(uint16_t pix, uint32_t c, int16_t cct=-1); + void setPixelColor(uint16_t pix, uint32_t c); // WLEDMM third parameter "cct" is never used - removed + //void setPixelColor(uint16_t pix, uint32_t c, int16_t cct) {Bus::setCCT(cct); setPixelColor(pix, c);}; // WLEDMM legacy support - slow, avoid using it void setBrightness(uint8_t b, bool immediate=false); // immediate=true is for use in ABL, it applies brightness immediately (warning: inefficient) @@ -504,7 +505,7 @@ class BusManager { // WLEDMM cache last used Bus -> 20% to 30% speedup when using many LED pins Bus *lastBus = nullptr; unsigned laststart = 0; - unsigned lastend = 0; + unsigned lastlen = 0; bool slowMode = false; // WLEDMM not sure why we need this. But its necessary. inline uint8_t getNumVirtualBusses() const { From e6b15a1c84df9a0c04cc97c4d11878de9dc81feb Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Thu, 23 Oct 2025 01:18:18 +0200 Subject: [PATCH 009/170] Add .vscode/extensions.json to .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 5a928325..41341648 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,7 @@ .pioenvs .piolibdeps .vscode +.vscode/extensions.json esp01-update.sh platformio_override.ini From e6876caba1bea95d9025607563d56f7feccd5a6e Mon Sep 17 00:00:00 2001 From: MoonModules <91013628+MoonModules@users.noreply.github.com> Date: Thu, 23 Oct 2025 19:24:45 +0200 Subject: [PATCH 010/170] Update GitHub links to MM-Effects repository WLED-Effects repo has been renamed to MM-Effects. ArtiFX links to this repo so updated in artifx.js --- usermods/artifx/artifx.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/usermods/artifx/artifx.js b/usermods/artifx/artifx.js index f2386448..19819ca6 100644 --- a/usermods/artifx/artifx.js +++ b/usermods/artifx/artifx.js @@ -78,7 +78,7 @@ function populateCEEditor(name, segID)

- +

Compile and Run Log

@@ -100,10 +100,10 @@ function populateCEEditor(name, segID) } function downloadGHFile(url, name, save=false, warn=false) { //Githubfile - if (url == "CE") url = "https://raw.githubusercontent.com/MoonModules/WLED-Effects/master/ARTIFX/wled/"; - if (url == "HBB") url = "https://raw.githubusercontent.com/MoonModules/WLED-Effects/master/Presets/HB_PresetPack210808_32x32_16seg/Base%20pack/"; - if (url == "HBE") url = "https://raw.githubusercontent.com/MoonModules/WLED-Effects/master/Presets/HB_PresetPack210808_32x32_16seg/Effects%20pack/"; - if (url == "LM") url = "https://raw.githubusercontent.com/MoonModules/WLED-Effects/master/Ledmaps/"; + if (url == "CE") url = "https://raw.githubusercontent.com/MoonModules/MM-Effects/master/ARTIFX/wled/"; + if (url == "HBB") url = "https://raw.githubusercontent.com/MoonModules/MM-Effects/master/Presets/HB_PresetPack210808_32x32_16seg/Base%20pack/"; + if (url == "HBE") url = "https://raw.githubusercontent.com/MoonModules/MM-Effects/master/Presets/HB_PresetPack210808_32x32_16seg/Effects%20pack/"; + if (url == "LM") url = "https://raw.githubusercontent.com/MoonModules/MM-Effects/master/Ledmaps/"; fetchAndExecute(url, name, null, function(parms,text) { if (save) { @@ -153,4 +153,4 @@ function loadCETemplate(name) { } }`; -} \ No newline at end of file +} From 1f99aeb5067bced846903048b6b7e9e66458d086 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Fri, 24 Oct 2025 00:05:44 +0200 Subject: [PATCH 011/170] small optimization: always allow gPC to use cached busses previously gPC cached busses were disabled in slowMode (one pixel mapped to several outputs). However this should not be needed, because the first copy found should be like all other. --- wled00/bus_manager.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/wled00/bus_manager.cpp b/wled00/bus_manager.cpp index d843f4e6..ddd53483 100644 --- a/wled00/bus_manager.cpp +++ b/wled00/bus_manager.cpp @@ -1361,12 +1361,12 @@ uint32_t IRAM_ATTR __attribute__((hot)) BusManager::getPixelColor(uint_fast16_t uint_fast16_t blen = b->getLength(); if ((uint_fast16_t)(pix - bstart) < blen) { // Unsigned arithmetic trick for fast range check - if (!slowMode) { + //if (!slowMode) { // Cache bus info for next call lastBus = b; laststart = bstart; lastlen = blen; - } + //} return b->getPixelColor(pix - bstart); // done - found one } } @@ -1388,12 +1388,12 @@ uint32_t IRAM_ATTR __attribute__((hot)) BusManager::getPixelColorRestored(uint_ uint_fast16_t blen = b->getLength(); if ((uint_fast16_t)(pix - bstart) < blen) { // Unsigned arithmetic trick for range check - if (!slowMode) { + //if (!slowMode) { // Cache bus info for next call lastBus = b; laststart = bstart; lastlen = blen; - } + //} return b->getPixelColorRestored(pix - bstart); } } From 6ce663784d431f293fde39cded0e7fa9d4e5dcc0 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Fri, 24 Oct 2025 16:24:33 +0200 Subject: [PATCH 012/170] bugfix to prevent random corruption of presets.json accroding to the docs of setBufferSize() and svbuf(): > setBufferSize() has to be called right after opening file before any other operation! so changing buffer sizes on an already opened and partially read file can cause file corruption as the internal buffer is exchanged "mid-flight". Fix: move all f.setBufferSize() so they appear directly after f.open(). --- wled00/file.cpp | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/wled00/file.cpp b/wled00/file.cpp index 39813ba0..43458a6b 100644 --- a/wled00/file.cpp +++ b/wled00/file.cpp @@ -18,7 +18,7 @@ * 1. File must be a string representation of a valid JSON object * 2. File must have '{' as first character * 3. There must not be any additional characters between a root-level key and its value object (e.g. space, tab, newline) - * 4. There must not be any characters between an root object-separating ',' and the next object key string + * 4. There must not be any characters between a root object-separating ',' and the next object key string * 5. There may be any number of spaces, tabs, and/or newlines before such object-separating ',' * 6. There must not be more than 5 consecutive spaces at any point except for those permitted in condition 5 * 7. If it is desired to delete the first usable object (e.g. preset file), a dummy object '"0":{}' is inserted at the beginning. @@ -66,9 +66,6 @@ static bool bufferedFind(const char *target, bool fromStart = true) { size_t index = 0; byte buf[FS_BUFSIZE]; - #if ESP_IDF_VERSION_MAJOR >= 4 - f.setBufferSize(FS_BUFSIZE); - #endif if (fromStart) f.seek(0); while (f.position() < f.size() -1) { @@ -110,9 +107,6 @@ static bool bufferedFindSpace(size_t targetLen, bool fromStart = true) { size_t index = 0; // better to use size_t instead if uint16_t byte buf[FS_BUFSIZE]; - #if ESP_IDF_VERSION_MAJOR >= 4 - f.setBufferSize(FS_BUFSIZE); - #endif if (fromStart) f.seek(0); while (f.position() < f.size() -1) { @@ -156,9 +150,6 @@ static bool bufferedFindObjectEnd() { uint16_t objDepth = 0; //num of '{' minus num of '}'. return once 0 //size_t start = f.position(); byte buf[FS_BUFSIZE]; - #if ESP_IDF_VERSION_MAJOR >= 4 - f.setBufferSize(FS_BUFSIZE); - #endif while (f.position() < f.size() -1) { size_t bufsize = f.read(buf, FS_BUFSIZE); // better to use size_t instead of uint16_t size_t count = 0; @@ -183,9 +174,6 @@ static void writeSpace(size_t l) { byte buf[FS_BUFSIZE]; memset(buf, ' ', FS_BUFSIZE); - #if ESP_IDF_VERSION_MAJOR >= 4 - f.setBufferSize(FS_BUFSIZE); - #endif while (l > 0) { size_t block = (l>FS_BUFSIZE) ? FS_BUFSIZE : l; f.write(buf, block); @@ -299,6 +287,9 @@ bool writeObjectToFile(const char* file, const char* key, JsonDocument* content) DEBUGFS_PRINTLN(F("Failed to open!")); return false; } + #if ESP_IDF_VERSION_MAJOR >= 4 + f.setBufferSize(FS_BUFSIZE); // reduced internal buffer leads to shorter blocking delay, and might prevent LED glitches + #endif if (!bufferedFind(key)) //key does not exist in file { @@ -366,6 +357,10 @@ bool readObjectFromFile(const char* file, const char* key, JsonDocument* dest) if (!f) return false; else { DEBUG_PRINTF(PSTR("FILE '%s' open to read, size %d bytes\n"), file, (int)f.size());} // WLEDMM additional debug message + #if ESP_IDF_VERSION_MAJOR >= 4 + f.setBufferSize(FS_BUFSIZE*2); // reduced internal buffer leads to shorter blocking delay, and might prevent LED glitches + #endif + if (key != nullptr && !bufferedFind(key)) //key does not exist in file { f.close(); @@ -444,6 +439,10 @@ static const uint8_t *getPresetCache(size_t &size) { if (!presetsCached) { File file = WLED_FS.open("/presets.json", "r"); + + #if ESP_IDF_VERSION_MAJOR >= 4 + if (file) f.setBufferSize(FS_BUFSIZE*2); // reduced internal buffer leads to shorter blocking delay, and might prevent LED glitches + #endif if (file) { presetsCachedTime = presetsModifiedTime; presetsCachedValidate = cacheInvalidate; From 80a6866f16dd5d7ce38c7d0e58daf3cc1f5f3fb1 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Fri, 24 Oct 2025 16:35:11 +0200 Subject: [PATCH 013/170] small bugfix for previous commit (PSRAM caching) --- wled00/file.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wled00/file.cpp b/wled00/file.cpp index 43458a6b..d3727d16 100644 --- a/wled00/file.cpp +++ b/wled00/file.cpp @@ -441,7 +441,7 @@ static const uint8_t *getPresetCache(size_t &size) { File file = WLED_FS.open("/presets.json", "r"); #if ESP_IDF_VERSION_MAJOR >= 4 - if (file) f.setBufferSize(FS_BUFSIZE*2); // reduced internal buffer leads to shorter blocking delay, and might prevent LED glitches + if (file) file.setBufferSize(FS_BUFSIZE*2); // reduced internal buffer leads to shorter blocking delay, and might prevent LED glitches #endif if (file) { presetsCachedTime = presetsModifiedTime; From 1af94dc9a22d418ec16d14bf85aa894b45622b88 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Fri, 24 Oct 2025 19:11:06 +0200 Subject: [PATCH 014/170] add error message when effects cannot be added --- wled00/FX.cpp | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index 138e9690..88626635 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -11773,18 +11773,35 @@ static const char _data_RESERVED[] PROGMEM = "RSVD"; // use id==255 to find unallocated gaps (with "Reserved" data string) // if vector size() is smaller than id (single) data is appended at the end (regardless of id) void WS2812FX::addEffect(uint8_t id, mode_ptr mode_fn, const char *mode_name) { + if ((id < _mode.size()) && (_modeData[id] != _data_RESERVED)) { + DEBUG_PRINTF("addEffect(%d) -> ", id); + DEBUG_PRINTF(" already in use, finding a new slot for -> %s\n", mode_name); + id = 255; + } + if ((id >= _mode.size()) && (id != 255)) { + DEBUG_PRINTF("!addEffect(%d) -> slot not existing, finding new slot\n", id); + } if (id == 255) { // find empty slot for (size_t i=1; i<_mode.size(); i++) if (_modeData[i] == _data_RESERVED) { id = i; break; } } + if (id < _mode.size()) { - if (_modeData[id] != _data_RESERVED) return; // do not overwrite alerady added effect + if (_modeData[id] != _data_RESERVED) { + USER_PRINTF("!addEffect(%d) failed - existing effect cannot be replaced. <=> %s\n", id, mode_name); + return; // do not overwrite alerady added effect + } _mode[id] = mode_fn; _modeData[id] = mode_name; } else { + if (_modeCount > 253) { + USER_PRINTF("!addEffect(%d) failed - mode list is full! %s\n", id, mode_name); + return; // mode list is full - cannot add + } _mode.push_back(mode_fn); _modeData.push_back(mode_name); if (_modeCount < _mode.size()) _modeCount++; } + DEBUG_PRINTF("addEffect(%d) => %s\n", id, mode_name); } void WS2812FX::setupEffectData() { From 22d142942ae531054a5e1577990f1a4d25f13d81 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Fri, 24 Oct 2025 19:15:20 +0200 Subject: [PATCH 015/170] build 2510241, version 14.7.0-dev ongoing development --- package-lock.json | 4 ++-- package.json | 2 +- wled00/data/index.js | 2 ++ wled00/wled.h | 2 +- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index 74a18035..796f683b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "wled", - "version": "14.5.1-dev", + "version": "14.7.0-dev", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "wled", - "version": "14.5.1-dev", + "version": "14.7.0-dev", "license": "EUPL-1.2", "dependencies": { "clean-css": "^4.2.3", diff --git a/package.json b/package.json index 2e826712..0e0d78d7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wled", - "version": "14.5.1-dev", + "version": "14.7.0-dev", "description": "Tools for WLED project", "main": "tools/cdata.js", "directories": { diff --git a/wled00/data/index.js b/wled00/data/index.js index 2c1f143a..29cd854a 100644 --- a/wled00/data/index.js +++ b/wled00/data/index.js @@ -697,6 +697,8 @@ function populateInfo(i) //if (i.ver.includes("0.14.1-b")) vcn = "Fried Chicken"; // final line of "One Vision" by Queen if (i.ver.includes("0.14.3-b")) vcn = "Fried Chicken"; if (i.ver.includes("14.5.")) vcn = "Small Step"; + if (i.ver.includes("14.6.")) vcn = "New Light"; + if (i.ver.includes("14.7.")) vcn = "Next Step"; cn += `v${i.ver}  "${vcn}"

(WLEDMM ${i.rel}.bin)

build ${i.vid}

${urows} diff --git a/wled00/wled.h b/wled00/wled.h index 442473da..ffd179fd 100644 --- a/wled00/wled.h +++ b/wled00/wled.h @@ -7,7 +7,7 @@ */ // version code in format yymmddb (b = daily build) -#define VERSION 2501170 +#define VERSION 2510241 // WLEDMM - you can check for this define in usermods, to only enabled WLEDMM specific code in the "right" fork. Its not defined in AC WLED. #define _MoonModules_WLED_ From 60878305fb866eb8ebcd66c6a94285bfdb0b265f Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sat, 25 Oct 2025 00:53:25 +0200 Subject: [PATCH 016/170] debug code updates & fixes better output when using WLED_DEBUG_HEAP without WLED_DEBUG --- wled00/FXparticleSystem.cpp | 2 +- wled00/wled.cpp | 10 +++++----- wled00/wled.h | 2 +- wled00/wled00.ino | 13 +++++++------ 4 files changed, 14 insertions(+), 13 deletions(-) diff --git a/wled00/FXparticleSystem.cpp b/wled00/FXparticleSystem.cpp index 9e5162c8..908a1d46 100644 --- a/wled00/FXparticleSystem.cpp +++ b/wled00/FXparticleSystem.cpp @@ -1789,7 +1789,7 @@ uint32_t calculateNumberOfParticles1D(const uint32_t fraction, const bool isadva numberofParticles = numberofParticles < 20 ? 20 : numberofParticles; // 20 minimum //make sure it is a multiple of 4 for proper memory alignment (easier than using padding bytes) numberofParticles = (numberofParticles+3) & ~0x03; // note: with a separate particle buffer, this is probably unnecessary - PSPRINTLN(" calc numparticles:" + String(numberofParticles)) + PSPRINTLN(" calc numparticles:" + String(numberofParticles)); return numberofParticles; } diff --git a/wled00/wled.cpp b/wled00/wled.cpp index 47826138..1842d6ad 100644 --- a/wled00/wled.cpp +++ b/wled00/wled.cpp @@ -382,13 +382,13 @@ void WLED::loop() #endif #ifdef WLED_DEBUG_HEAP if (millis() - debugTime > 4999 ) { // WLEDMM: Special case for debugging heap faster - DEBUG_PRINT(F("*** Free heap: ")); DEBUG_PRINT(heap_caps_get_free_size(0x1800)); - DEBUG_PRINT(F("\tLargest free block: ")); DEBUG_PRINT(heap_caps_get_largest_free_block(0x1800)); - DEBUG_PRINT(F(" *** \t\tArduino min free stack: ")); DEBUG_PRINT(uxTaskGetStackHighWaterMark(NULL)); + USER_PRINT(F("*** Free heap: ")); USER_PRINT(heap_caps_get_free_size(0x1800)); + USER_PRINT(F("\tLargest free block: ")); USER_PRINT(heap_caps_get_largest_free_block(0x1800)); + USER_PRINT(F(" *** \t\tArduino min free stack: ")); USER_PRINT(uxTaskGetStackHighWaterMark(NULL)); #if INCLUDE_xTaskGetHandle - DEBUG_PRINT(F(" TCP min free stack: ")); DEBUG_PRINT(wledmm_get_tcp_stacksize()); + USER_PRINT(F(" TCP min free stack: ")); USER_PRINT(wledmm_get_tcp_stacksize()); #endif - DEBUG_PRINTLN(F(" ***")); + USER_PRINTLN(F(" ***")); debugTime = millis(); } #endif // WLED_DEBUG_HEAP diff --git a/wled00/wled.h b/wled00/wled.h index ffd179fd..dd1ba6da 100644 --- a/wled00/wled.h +++ b/wled00/wled.h @@ -880,7 +880,7 @@ WLED_GLOBAL volatile uint8_t jsonBufferLock _INIT(0); #endif // debug macro variable definitions -#ifdef WLED_DEBUG +#if defined(WLED_DEBUG) || defined(WLED_DEBUG_HEAP) WLED_GLOBAL unsigned long debugTime _INIT(0); WLED_GLOBAL int lastWifiState _INIT(3); WLED_GLOBAL unsigned long wifiStateChangedTime _INIT(0); diff --git a/wled00/wled00.ino b/wled00/wled00.ino index 83d3f959..087607ab 100644 --- a/wled00/wled00.ino +++ b/wled00/wled00.ino @@ -76,19 +76,20 @@ void setup() { void loop() __attribute__((used)); // needed for -flto void loop() { //WLEDMM show loops per second -#ifdef WLED_DEBUG +#if defined(WLED_DEBUG) || defined(WLED_DEBUG_HEAP) loopCounter++; //if (millis() - lastMillis >= 10000) { if (millis() - lastMillis >= 8000) { long delta = millis() - lastMillis; - if (delta > 0) { + if ((delta > 0) && (loopCounter > 0)) { lps = (loopCounter*1000U) / delta; //if (delta > (showtime / 1000)) lps2 = (loopCounter*1000U) / (delta - (showtime / 1000)); - USER_PRINTF("%lu lps\t", lps); - USER_PRINTF("%u fps\t", strip.getFps()); + USER_PRINTF("%3lu lps %5.1fms \t", lps, float(delta) / float(loopCounter)); + USER_PRINTF("%3u fps\t\t", strip.getFps()); //USER_PRINTF("%lu lps without show\t\t", lps2); - USER_PRINTF("target frametime %dms\t", int(strip.getFrameTime())); - USER_PRINTF("target FPS %d\n", int(strip.getTargetFps())); + //USER_PRINTF("target frametime %dms\t", int(strip.getFrameTime())); + //USER_PRINTF("target FPS %d", int(strip.getTargetFps())); + USER_PRINTLN(""); } lastMillis = millis(); loopCounter = 0; From f78edc43dcab1cbc67c6c6cf6ebe405dd54c92a0 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sat, 25 Oct 2025 16:52:42 +0200 Subject: [PATCH 017/170] bugfix for #272 (only affects rotary usermod) Refactor name copying logic to avoid use-after-free issue. --- wled00/util.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/wled00/util.cpp b/wled00/util.cpp index c31b20b6..a913feed 100644 --- a/wled00/util.cpp +++ b/wled00/util.cpp @@ -340,10 +340,14 @@ uint8_t extractModeSlider(uint8_t mode, uint8_t slider, char *dest, uint8_t maxL strncpy_P(dest, tmpstr, maxLen); // copy the name into buffer (replacing previous) dest[maxLen-1] = '\0'; } else { - if (nameEnd<0) tmpstr = names.substring(nameBegin).c_str(); // did not find ",", last name? - else tmpstr = names.substring(nameBegin, nameEnd).c_str(); - strlcpy(dest, tmpstr, maxLen); // copy the name into buffer (replacing previous) - } + // WLEDMM bugfix for WLED-MM #272 + // names.substring(...).c_str() returns a pointer to a temporary; it’s invalid by the next statement. Added result buffer "sub" to avoid use-after-free + // if (nameEnd<0) tmpstr = names.substring(nameBegin).c_str(); // did not find ",", last name? + // else tmpstr = names.substring(nameBegin, nameEnd).c_str(); + // strlcpy(dest, tmpstr, maxLen); // copy the name into buffer (replacing previous) + String sub = (nameEnd<0) ? names.substring(nameBegin) : names.substring(nameBegin, nameEnd); + strlcpy(dest, sub.c_str(), maxLen); // copy the name into buffer (replacing previous) + } } nameBegin = nameEnd+1; // next name (if "," is not found it will be 0) } // next slider From 12b3bedba78d53fd3fe1bbee7e5c3d7f7db2671c Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sat, 25 Oct 2025 16:55:52 +0200 Subject: [PATCH 018/170] cleanup - removed old code in comments --- wled00/util.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/wled00/util.cpp b/wled00/util.cpp index a913feed..8ae062ae 100644 --- a/wled00/util.cpp +++ b/wled00/util.cpp @@ -342,10 +342,7 @@ uint8_t extractModeSlider(uint8_t mode, uint8_t slider, char *dest, uint8_t maxL } else { // WLEDMM bugfix for WLED-MM #272 // names.substring(...).c_str() returns a pointer to a temporary; it’s invalid by the next statement. Added result buffer "sub" to avoid use-after-free - // if (nameEnd<0) tmpstr = names.substring(nameBegin).c_str(); // did not find ",", last name? - // else tmpstr = names.substring(nameBegin, nameEnd).c_str(); - // strlcpy(dest, tmpstr, maxLen); // copy the name into buffer (replacing previous) - String sub = (nameEnd<0) ? names.substring(nameBegin) : names.substring(nameBegin, nameEnd); + String sub = (nameEnd<0) ? names.substring(nameBegin) : names.substring(nameBegin, nameEnd); // special handling in case we did not find "," (last name) strlcpy(dest, sub.c_str(), maxLen); // copy the name into buffer (replacing previous) } } From 8fbaf63565fb8a77cb09d8301745fe1be4c003cf Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sat, 25 Oct 2025 19:57:59 +0200 Subject: [PATCH 019/170] decodeIRJson bugfix: avoid buffer overrun #272 Increase the size of objKey to accommodate 32bit code number. The previous buffer size was too small. --- wled00/ir.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wled00/ir.cpp b/wled00/ir.cpp index bfb79264..c3d2c531 100644 --- a/wled00/ir.cpp +++ b/wled00/ir.cpp @@ -673,7 +673,7 @@ Sample: */ void decodeIRJson(uint32_t code) { - char objKey[10]; + char objKey[16] = {'\0'}; // WLEDMM: 13 chars, not 9! '"0x' + 'FFFFFFFF' + '":' + '\0' String cmdStr; JsonObject fdo; JsonObject jsonCmdObj; From f373044e77a7656093a65a4ae64b7f8c4a5a459c Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sat, 25 Oct 2025 20:30:55 +0200 Subject: [PATCH 020/170] Update repository link to upstream --- readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.md b/readme.md index a44a82b3..37258c3e 100644 --- a/readme.md +++ b/readme.md @@ -14,7 +14,7 @@ image -MoonModules/WLED is a fork of [Aircoookie/WLED](https://github.com/Aircoookie/WLED) which contains latest merge of v0.14 of WLED with [additional features](https://mm.kno.wled.ge/moonmodules/what-is-moonmodules/). +MoonModules/WLED is a fork of [wled/WLED](https://github.com/wled/WLED) which contains latest merge of v0.14 of WLED with [additional features](https://mm.kno.wled.ge/moonmodules/what-is-moonmodules/). This fork is created by members of the [Atuline/WLED](https://github.com/atuline/WLED) team to make development against v0.14 possible while still preserving [Atuline/WLED v0.13.x](https://github.com/atuline/WLED/tree/dev) as a stable and supported version. The Atuline/WLED fork is also called WLED SR (Sound Reactive). From d856749bea3de2dfaab9a6ebf5ebddf7a83fbc80 Mon Sep 17 00:00:00 2001 From: Damian Schneider Date: Thu, 24 Jul 2025 18:30:51 +0200 Subject: [PATCH 021/170] fix change that got lost --- wled00/FX.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index 88626635..bff8ac3f 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -9744,7 +9744,7 @@ uint16_t mode_particleimpact(void) { PartSys->setBounceY(true); // always use ground bounce PartSys->setWallRoughness(220); // high roughness numMeteors = min(PartSys->numSources, (uint32_t)NUMBEROFSOURCES); - for (i = 0; i < numMeteors; i++) { + for (uint32_t i = 0; i < numMeteors; i++) { PartSys->sources[i].source.ttl = hw_random16(10 * i); // set initial delay for meteors PartSys->sources[i].source.vy = 10; // at positive speeds, no particles are emitted and if particle dies, it will be relaunched } From 86dda32d11a8a023fe03f9ff0890e92478c86d71 Mon Sep 17 00:00:00 2001 From: Will Miles Date: Wed, 30 Jul 2025 22:17:44 -0400 Subject: [PATCH 022/170] Update AsyncWebServer and AsyncTCP This should fix (or at least improve) some of the crash cases under excessive web server load. --- platformio.ini | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/platformio.ini b/platformio.ini index 96c06b9e..a1b8e5b0 100644 --- a/platformio.ini +++ b/platformio.ini @@ -251,7 +251,7 @@ lib_deps = ;; https://github.com/softhack007/FastLED.git#ESP32-C6 ;; patched version needed for -C6 IRremoteESP8266 @ 2.8.2 ;;makuna/NeoPixelBus @ 2.7.5 ;; WLEDMM will be added in board specific sections - https://github.com/Aircoookie/ESPAsyncWebServer.git#v2.4.0 + https://github.com/Aircoookie/ESPAsyncWebServer.git#v2.4.1 bitbank2/AnimatedGIF@^1.4.7 https://github.com/Aircoookie/GifDecoder#bc3af18 #For use of the TTGO T-Display ESP32 Module with integrated TFT display uncomment the following line @@ -373,7 +373,7 @@ build_flagsV4 = -g ;;; V4.4.x libraries (without LOROL_LITTLEFS; with newer NeoPixelBus) lib_depsV4 = - https://github.com/pbolduc/AsyncTCP.git @ 1.2.0 ;; WLEDMM this must be first in the list, otherwise Aircoookie/ESPAsyncWebServer pulls in an older version of AsyncTCP !! + esp32async/AsyncTCP @ 3.4.6 makuna/NeoPixelBus @ 2.7.5 ;; makuna/NeoPixelBus @ 2.7.9 ;; experimental ${common_mm.HUB75_lib_deps} @@ -404,7 +404,7 @@ build_flags = -g ; -D WLEDMM_SLOWPATH ;; don't use I2S for LED bus default_partitions = tools/WLED_ESP32_4MB_1MB_FS.csv lib_deps = - https://github.com/pbolduc/AsyncTCP.git @ 1.2.0 + esp32async/AsyncTCP @ 3.4.6 makuna/NeoPixelBus @ 2.7.5 ;; makuna/NeoPixelBus @ 2.7.9 ;; experimental ${env.lib_deps} @@ -437,7 +437,7 @@ build_flags = -g ;; ARDUINO_USB_CDC_ON_BOOT lib_deps = - https://github.com/pbolduc/AsyncTCP.git @ 1.2.0 + esp32async/AsyncTCP @ 3.4.6 ;; makuna/NeoPixelBus @ 2.7.5 ;; standard makuna/NeoPixelBus @ 2.7.9 ;; experimental - reduces LED glitches on -S2 ${env.lib_deps} @@ -460,7 +460,7 @@ build_flags = -g ;; ARDUINO_USB_CDC_ON_BOOT lib_deps = - https://github.com/pbolduc/AsyncTCP.git @ 1.2.0 + esp32async/AsyncTCP @ 3.4.6 makuna/NeoPixelBus @ 2.7.5 ;; makuna/NeoPixelBus @ 2.7.9 ;; experimental ${env.lib_deps} @@ -484,7 +484,7 @@ build_flags = -g ;; please make sure that the following flags are properly set (to 0 or 1) by your board.json, or included in your custom platformio_override.ini entry: ;; ARDUINO_USB_MODE, ARDUINO_USB_CDC_ON_BOOT lib_deps = - https://github.com/pbolduc/AsyncTCP.git @ 1.2.0 + esp32async/AsyncTCP @ 3.4.6 makuna/NeoPixelBus @ 2.7.5 ;; makuna/NeoPixelBus @ 2.7.9 ;; experimental ${env.lib_deps} From 832c0c4bf4fa6625f8abac74d1dbbb1de6a7a776 Mon Sep 17 00:00:00 2001 From: Will Miles Date: Sat, 2 Aug 2025 15:49:47 -0400 Subject: [PATCH 023/170] Update to AsyncTCP 3.4.7 Bugfix on 3.4.6 --- platformio.ini | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/platformio.ini b/platformio.ini index a1b8e5b0..1aaaeb0c 100644 --- a/platformio.ini +++ b/platformio.ini @@ -251,7 +251,7 @@ lib_deps = ;; https://github.com/softhack007/FastLED.git#ESP32-C6 ;; patched version needed for -C6 IRremoteESP8266 @ 2.8.2 ;;makuna/NeoPixelBus @ 2.7.5 ;; WLEDMM will be added in board specific sections - https://github.com/Aircoookie/ESPAsyncWebServer.git#v2.4.1 + https://github.com/Aircoookie/ESPAsyncWebServer.git#v2.4.2 bitbank2/AnimatedGIF@^1.4.7 https://github.com/Aircoookie/GifDecoder#bc3af18 #For use of the TTGO T-Display ESP32 Module with integrated TFT display uncomment the following line @@ -373,7 +373,7 @@ build_flagsV4 = -g ;;; V4.4.x libraries (without LOROL_LITTLEFS; with newer NeoPixelBus) lib_depsV4 = - esp32async/AsyncTCP @ 3.4.6 + esp32async/AsyncTCP @ 3.4.7 makuna/NeoPixelBus @ 2.7.5 ;; makuna/NeoPixelBus @ 2.7.9 ;; experimental ${common_mm.HUB75_lib_deps} @@ -404,7 +404,7 @@ build_flags = -g ; -D WLEDMM_SLOWPATH ;; don't use I2S for LED bus default_partitions = tools/WLED_ESP32_4MB_1MB_FS.csv lib_deps = - esp32async/AsyncTCP @ 3.4.6 + esp32async/AsyncTCP @ 3.4.7 makuna/NeoPixelBus @ 2.7.5 ;; makuna/NeoPixelBus @ 2.7.9 ;; experimental ${env.lib_deps} @@ -437,7 +437,7 @@ build_flags = -g ;; ARDUINO_USB_CDC_ON_BOOT lib_deps = - esp32async/AsyncTCP @ 3.4.6 + esp32async/AsyncTCP @ 3.4.7 ;; makuna/NeoPixelBus @ 2.7.5 ;; standard makuna/NeoPixelBus @ 2.7.9 ;; experimental - reduces LED glitches on -S2 ${env.lib_deps} @@ -460,7 +460,7 @@ build_flags = -g ;; ARDUINO_USB_CDC_ON_BOOT lib_deps = - esp32async/AsyncTCP @ 3.4.6 + esp32async/AsyncTCP @ 3.4.7 makuna/NeoPixelBus @ 2.7.5 ;; makuna/NeoPixelBus @ 2.7.9 ;; experimental ${env.lib_deps} @@ -484,7 +484,7 @@ build_flags = -g ;; please make sure that the following flags are properly set (to 0 or 1) by your board.json, or included in your custom platformio_override.ini entry: ;; ARDUINO_USB_MODE, ARDUINO_USB_CDC_ON_BOOT lib_deps = - esp32async/AsyncTCP @ 3.4.6 + esp32async/AsyncTCP @ 3.4.7 makuna/NeoPixelBus @ 2.7.5 ;; makuna/NeoPixelBus @ 2.7.9 ;; experimental ${env.lib_deps} From b215c8209dd9376f9b9376af330f3ff5cfa15756 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sat, 25 Oct 2025 21:48:55 +0200 Subject: [PATCH 024/170] post-merge updates CONFIG_ASYNC_TCP_TASK_STACK_SIZE => CONFIG_ASYNC_TCP_STACK_SIZE --- platformio.ini | 5 +++++ usermods/audioreactive/audio_reactive.h | 6 +++--- wled00/const.h | 2 +- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/platformio.ini b/platformio.ini index 1aaaeb0c..f5e96051 100644 --- a/platformio.ini +++ b/platformio.ini @@ -366,6 +366,7 @@ build_flagsV4 = -g -DCONFIG_LITTLEFS_FOR_IDF_3_2 -DLFS_THREADSAFE -D CONFIG_ASYNC_TCP_USE_WDT=0 -D CONFIG_ASYNC_TCP_TASK_STACK_SIZE=9472 ;; WLEDMM increase stack by 1.25Kb, as audioreactive needs bigger SETTINGS_STACK_BUF_SIZE + -D CONFIG_ASYNC_TCP_STACK_SIZE=9472 ;; *sigh* newer asyncTCP uses this instead of .._TASK_.. ; -D WLEDMM_TWOPATH ;; use I2S1 as the second bus --> slightly faster on some setups ; -D WLEDMM_SLOWPATH ;; don't use I2S for LED bus ; -DARDUINO_USB_CDC_ON_BOOT=0 ;; mandatory for "classic ESP32" when building with arduino-esp32 >=2.0.3 @@ -399,6 +400,7 @@ build_flags = -g #-DCONFIG_LITTLEFS_FOR_IDF_3_2 -D CONFIG_ASYNC_TCP_USE_WDT=0 -D CONFIG_ASYNC_TCP_TASK_STACK_SIZE=9472 ;; WLEDMM increase stack by 1.25Kb, as audioreactive needs bigger SETTINGS_STACK_BUF_SIZE + -D CONFIG_ASYNC_TCP_STACK_SIZE=9472 ;; *sigh* newer asyncTCP uses this instead of .._TASK_.. -DARDUINO_USB_CDC_ON_BOOT=0 ;; this flag is mandatory for "classic ESP32" when building with arduino-esp32 >=2.0.3 ; -D WLEDMM_TWOPATH ;; use I2S1 as the second bus --> slightly faster on some setups ; -D WLEDMM_SLOWPATH ;; don't use I2S for LED bus @@ -430,6 +432,7 @@ build_flags = -g -DCONFIG_LITTLEFS_FOR_IDF_3_2 -DLFS_THREADSAFE ;; WLEDMM -D CONFIG_ASYNC_TCP_USE_WDT=0 -D CONFIG_ASYNC_TCP_TASK_STACK_SIZE=8614 ;; WLEDMM increase stack by 1Kb, as audioreactive needs bigger SETTINGS_STACK_BUF_SIZE + -D CONFIG_ASYNC_TCP_STACK_SIZE=8614 ;; *sigh* newer asyncTCP uses this instead of .._TASK_.. -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=0 -DCO -DARDUINO_USB_MODE=0 ;; this flag is mandatory for ESP32-S2 ! @@ -454,6 +457,7 @@ build_flags = -g -DCONFIG_LITTLEFS_FOR_IDF_3_2 -DLFS_THREADSAFE ;; WLEDMM -D CONFIG_ASYNC_TCP_USE_WDT=0 -D CONFIG_ASYNC_TCP_TASK_STACK_SIZE=9472 ;; WLEDMM increase stack by 1.25Kb, as audioreactive needs bigger SETTINGS_STACK_BUF_SIZE + -D CONFIG_ASYNC_TCP_STACK_SIZE=9472 ;; *sigh* newer asyncTCP uses this instead of .._TASK_.. -DCO -DARDUINO_USB_MODE=1 ;; this flag is mandatory for ESP32-C3 ;; please make sure that the following flags are properly set (to 0 or 1) by your board.json, or included in your custom platformio_override.ini entry: @@ -479,6 +483,7 @@ build_flags = -g -DWLEDMM_NO_SERIAL_WAIT ;; WLEDMM don't wait for serial on -S3 (unless WLED_DEBUG is set) -D CONFIG_ASYNC_TCP_USE_WDT=0 -D CONFIG_ASYNC_TCP_TASK_STACK_SIZE=9472 ;; WLEDMM increase stack by 1.25Kb, as audioreactive needs bigger SETTINGS_STACK_BUF_SIZE + -D CONFIG_ASYNC_TCP_STACK_SIZE=9472 ;; *sigh* newer asyncTCP uses this instead of .._TASK_.. -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_DFU_ON_BOOT=0 -DCO ;; please make sure that the following flags are properly set (to 0 or 1) by your board.json, or included in your custom platformio_override.ini entry: diff --git a/usermods/audioreactive/audio_reactive.h b/usermods/audioreactive/audio_reactive.h index 0be1bd79..cf34b547 100644 --- a/usermods/audioreactive/audio_reactive.h +++ b/usermods/audioreactive/audio_reactive.h @@ -111,12 +111,12 @@ // sanity checks #ifdef ARDUINO_ARCH_ESP32 - // we need more space in for oappend() stack buffer -> SETTINGS_STACK_BUF_SIZE and CONFIG_ASYNC_TCP_TASK_STACK_SIZE + // we need more space in for oappend() stack buffer -> SETTINGS_STACK_BUF_SIZE and CONFIG_ASYNC_TCP_STACK_SIZE #if SETTINGS_STACK_BUF_SIZE < 3904 // 3904 is required for WLEDMM-0.14.0-b28 #warning please increase SETTINGS_STACK_BUF_SIZE >= 3904 #endif - #if (CONFIG_ASYNC_TCP_TASK_STACK_SIZE - SETTINGS_STACK_BUF_SIZE) < 4352 // at least 4096+256 words of free task stack is needed by async_tcp alone - #error remaining async_tcp stack will be too low - please increase CONFIG_ASYNC_TCP_TASK_STACK_SIZE + #if (CONFIG_ASYNC_TCP_STACK_SIZE - SETTINGS_STACK_BUF_SIZE) < 4352 // at least 4096+256 words of free task stack is needed by async_tcp alone + #error remaining async_tcp stack will be too low - please increase CONFIG_ASYNC_TCP_STACK_SIZE #endif #endif diff --git a/wled00/const.h b/wled00/const.h index f2247512..3257bc62 100644 --- a/wled00/const.h +++ b/wled00/const.h @@ -435,7 +435,7 @@ #if !defined(USERMOD_AUDIOREACTIVE) #define SETTINGS_STACK_BUF_SIZE 3834 // WLEDMM added 696+32 bytes of margin (was 3096) #else - #define SETTINGS_STACK_BUF_SIZE 4000 // WLEDMM more buffer for audioreactive UI (add '-D CONFIG_ASYNC_TCP_TASK_STACK_SIZE=9216' to your build_flags) + #define SETTINGS_STACK_BUF_SIZE 4000 // WLEDMM more buffer for audioreactive UI (add '-D CONFIG_ASYNC_TCP_STACK_SIZE=9216' to your build_flags) #endif #endif From 82ba119402adef3febfcf23be601e02b21829fd8 Mon Sep 17 00:00:00 2001 From: Damian Schneider Date: Sun, 12 Oct 2025 15:18:48 +0200 Subject: [PATCH 025/170] fix low brightness gradient "jumpyness" during testing at low brightness I noticed that gradients can be "jumping" in colors quite wildly, turning a smooth gradient into a flickering mess. This is due to the color hue preservation being inaccurate and a bit too aggressive. This can be seen for example using a gradient palette and "Running" FX. Removing the hue preservation completely fixes it but leaves color artefacts for example visible in PS Fire at very low brightness: the bright part of the flames gets a pink hue. This change is a compromise to fix both problems to a "good enough" state --- wled00/colorTools.hpp | 40 ++++++++++++++++------------------------ wled00/colors.cpp | 43 +++++++++++++++++-------------------------- 2 files changed, 33 insertions(+), 50 deletions(-) diff --git a/wled00/colorTools.hpp b/wled00/colorTools.hpp index c47f1934..9d600b3e 100644 --- a/wled00/colorTools.hpp +++ b/wled00/colorTools.hpp @@ -100,32 +100,24 @@ inline __attribute__((hot,const)) uint32_t color_add(uint32_t c1, uint32_t c2, b inline __attribute__((hot,const)) uint32_t color_fade(uint32_t c1, uint8_t amount, bool video=false) { - if (amount == 255) return c1; // WLEDMM small optimization - plus it avoids over-fading in "video" mode - if (amount == 0) return 0; // WLEDMM shortcut + if (c1 == 0 || amount == 0) return 0; // black or no change + if (amount == 255) return c1; + uint32_t addRemains = 0; - uint32_t scaledcolor = 0; // color order is: W R G B from MSB to LSB - uint16_t w = W(c1); // WLEDMM 16bit to make sure the compiler uses 32bit (not 64bit) for the math - uint16_t r = R(c1); - uint16_t g = G(c1); - uint16_t b = B(c1); - if (video) { - uint16_t scale = amount; // 32bit for faster calculation - // bugfix: doing "+1" after shifting is obviously wrong - // optimization: ((r && scale) ? 1 : 0) can be simplified to "if (r > 0) +1" ; if we arive here, then scale != 0 and scale < 255 - if (w>0) scaledcolor |= (((w * scale) >> 8) +1) << 24; // WLEDMM small speedup when no white channel - if (r>0) scaledcolor |= (((r * scale) >> 8) +1) << 16; - if (g>0) scaledcolor |= (((g * scale) >> 8) +1) << 8; - if (b>0) scaledcolor |= ((b * scale) >> 8) +1; - return scaledcolor; - } - else { - uint16_t scale = 1 + amount; - if (w>0) scaledcolor |= ((w * scale) >> 8) << 24; // WLEDMM small speedup when no white channel - scaledcolor |= ((r * scale) >> 8) << 16; - scaledcolor |= (g * scale) & 0x0000FF00; // WLEDMM faster than right-left shift "" >>8 ) <<8" - scaledcolor |= (b * scale) >> 8; - return scaledcolor; + if (!video) amount++; // add one for correct scaling using bitshifts + else { + // video scaling: make sure colors do not dim to zero if they started non-zero unless they distort the hue + uint8_t r = byte(c1>>16), g = byte(c1>>8), b = byte(c1), w = byte(c1>>24); // extract r, g, b, w channels + uint8_t maxc = (r > g) ? ((r > b) ? r : b) : ((g > b) ? g : b); // determine dominant channel for hue preservation + addRemains = r && (r<<5) > maxc ? 0x00010000 : 0; // note: setting color preservation threshold too high results in flickering and + addRemains |= g && (g<<5) > maxc ? 0x00000100 : 0; // jumping colors in low brightness gradients. Multiplying the color preserves + addRemains |= b && (b<<5) > maxc ? 0x00000001 : 0; // better accuracy than dividing the maxc. Shifting by 5 is a good compromise + addRemains |= w ? 0x01000000 : 0; // i.e. remove color channel if <13% of max } + const uint32_t TWO_CHANNEL_MASK = 0x00FF00FF; + uint32_t rb = (((c1 & TWO_CHANNEL_MASK) * amount) >> 8) & TWO_CHANNEL_MASK; // scale red and blue + uint32_t wg = (((c1 >> 8) & TWO_CHANNEL_MASK) * amount) & ~TWO_CHANNEL_MASK; // scale white and green + return (rb | wg) + addRemains; } //scales the brightness with the briMultiplier factor (from led.cpp) diff --git a/wled00/colors.cpp b/wled00/colors.cpp index 37241959..07d4020f 100644 --- a/wled00/colors.cpp +++ b/wled00/colors.cpp @@ -82,34 +82,25 @@ IRAM_ATTR_YN uint32_t color_add(uint32_t c1, uint32_t c2, bool fast) // WLEDMM IRAM_ATTR_YN __attribute__((hot)) uint32_t color_fade(uint32_t c1, uint8_t amount, bool video) { - if (amount == 255) return c1; // WLEDMM small optimization - plus it avoids over-fading in "video" mode - if (amount == 0) return 0; // WLEDMM shortcut + if (c1 == 0 || amount == 0) return 0; // black or no change + if (amount == 255) return c1; + uint32_t addRemains = 0; - uint32_t scaledcolor = 0; // color order is: W R G B from MSB to LSB - uint16_t w = W(c1); // WLEDMM 16bit to make sure the compiler uses 32bit (not 64bit) for the math - uint16_t r = R(c1); - uint16_t g = G(c1); - uint16_t b = B(c1); - if (video) { - uint16_t scale = amount; // 32bit for faster calculation - // bugfix: doing "+1" after shifting is obviously wrong - // optimization: ((r && scale) ? 1 : 0) can be simplified to "if (r > 0) +1" ; if we arive here, then scale != 0 and scale < 255 - if (w>0) scaledcolor |= (((w * scale) >> 8) +1) << 24; // WLEDMM small speedup when no white channel - if (r>0) scaledcolor |= (((r * scale) >> 8) +1) << 16; - if (g>0) scaledcolor |= (((g * scale) >> 8) +1) << 8; - if (b>0) scaledcolor |= ((b * scale) >> 8) +1; - return scaledcolor; + if (!video) amount++; // add one for correct scaling using bitshifts + else { + // video scaling: make sure colors do not dim to zero if they started non-zero unless they distort the hue + uint8_t r = byte(c1>>16), g = byte(c1>>8), b = byte(c1), w = byte(c1>>24); // extract r, g, b, w channels + uint8_t maxc = (r > g) ? ((r > b) ? r : b) : ((g > b) ? g : b); // determine dominant channel for hue preservation + addRemains = r && (r<<5) > maxc ? 0x00010000 : 0; // note: setting color preservation threshold too high results in flickering and + addRemains |= g && (g<<5) > maxc ? 0x00000100 : 0; // jumping colors in low brightness gradients. Multiplying the color preserves + addRemains |= b && (b<<5) > maxc ? 0x00000001 : 0; // better accuracy than dividing the maxc. Shifting by 5 is a good compromise + addRemains |= w ? 0x01000000 : 0; // i.e. remove color channel if <13% of max } - else { - uint16_t scale = 1 + amount; - if (w>0) scaledcolor |= ((w * scale) >> 8) << 24; // WLEDMM small speedup when no white channel - scaledcolor |= ((r * scale) >> 8) << 16; - scaledcolor |= (g * scale) & 0x0000FF00; // WLEDMM faster than right-left shift "" >>8 ) <<8" - scaledcolor |= (b * scale) >> 8; - return scaledcolor; - } -} -#endif + const uint32_t TWO_CHANNEL_MASK = 0x00FF00FF; + uint32_t rb = (((c1 & TWO_CHANNEL_MASK) * amount) >> 8) & TWO_CHANNEL_MASK; // scale red and blue + uint32_t wg = (((c1 >> 8) & TWO_CHANNEL_MASK) * amount) & ~TWO_CHANNEL_MASK; // scale white and green + return (rb | wg) + addRemains; +}#endif void setRandomColor(byte* rgb) { From 9968ed9a22d5e31b24ae3b0b11f4babceb9ab68c Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sat, 25 Oct 2025 22:17:13 +0200 Subject: [PATCH 026/170] fix merge error --- wled00/colors.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/wled00/colors.cpp b/wled00/colors.cpp index 07d4020f..23151ecb 100644 --- a/wled00/colors.cpp +++ b/wled00/colors.cpp @@ -100,7 +100,8 @@ IRAM_ATTR_YN __attribute__((hot)) uint32_t color_fade(uint32_t c1, uint8_t amoun uint32_t rb = (((c1 & TWO_CHANNEL_MASK) * amount) >> 8) & TWO_CHANNEL_MASK; // scale red and blue uint32_t wg = (((c1 >> 8) & TWO_CHANNEL_MASK) * amount) & ~TWO_CHANNEL_MASK; // scale white and green return (rb | wg) + addRemains; -}#endif +} +#endif void setRandomColor(byte* rgb) { From 4eb9f0855dcd72ebd76b706673c2b574e2f1744e Mon Sep 17 00:00:00 2001 From: Damian Schneider Date: Sun, 7 Sep 2025 20:34:57 +0200 Subject: [PATCH 027/170] Merge pull request #4913 from DedeHai/percentFX_UI_fix fix ancient UI bug that hides the speed slider in percent FX --- wled00/FX.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index bff8ac3f..ae2d4a1a 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -4102,7 +4102,7 @@ uint16_t mode_percent(void) { return FRAMETIME; } -static const char _data_FX_MODE_PERCENT[] PROGMEM = "Percent@,% of fill,,,,One color;!,!;!"; +static const char _data_FX_MODE_PERCENT[] PROGMEM = "Percent@!,% of fill,,,,One color;!,!;!"; /* From 4713f26bb86aa11058580c552f0468ada4976a47 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sat, 25 Oct 2025 23:43:44 +0200 Subject: [PATCH 028/170] additional constants to improve upstream compatibility * a few new error constants * WLED_O2_ATTR - ask the compiler for stronger optimization of a single function * WLED_O3_ATTR (WLEDMM) optimize even more --- wled00/FX_fcn.cpp | 4 ++-- wled00/FXparticleSystem.cpp | 8 +++---- wled00/colors.cpp | 6 ++--- wled00/const.h | 47 +++++++++++++++++++++++++++++++++---- wled00/data/index.js | 3 +++ 5 files changed, 54 insertions(+), 14 deletions(-) diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index 4941529f..688596eb 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -938,7 +938,7 @@ static void xyFromBlock(uint16_t &x,uint16_t &y, uint16_t i, uint16_t vW, uint16 } -void IRAM_ATTR_YN __attribute__((hot)) Segment::setPixelColor(int i, uint32_t col) //WLEDMM: IRAM_ATTR conditionally +void WLED_O2_ATTR __attribute__((hot)) Segment::setPixelColor(int i, uint32_t col) //WLEDMM: IRAM_ATTR conditionally { if (!isActive()) return; // not active #ifndef WLED_DISABLE_2D @@ -1212,7 +1212,7 @@ void Segment::setPixelColor(float i, uint32_t col, bool aa) } } -uint32_t __attribute__((hot)) Segment::getPixelColor(int i) const +uint32_t WLED_O2_ATTR __attribute__((hot)) Segment::getPixelColor(int i) const { if (!isActive()) return 0; // not active #ifndef WLED_DISABLE_2D diff --git a/wled00/FXparticleSystem.cpp b/wled00/FXparticleSystem.cpp index 908a1d46..cd537e8c 100644 --- a/wled00/FXparticleSystem.cpp +++ b/wled00/FXparticleSystem.cpp @@ -628,7 +628,7 @@ void ParticleSystem2D::render() { } // calculate pixel positions and brightness distribution and render the particle to local buffer or global buffer -__attribute__((optimize("O2"))) void ParticleSystem2D::renderParticle(const uint32_t particleindex, const uint8_t brightness, const CRGB& color, const bool wrapX, const bool wrapY) { +void WLED_O3_ATTR ParticleSystem2D::renderParticle(const uint32_t particleindex, const uint8_t brightness, const CRGB& color, const bool wrapX, const bool wrapY) { uint32_t size = particlesize; if (advPartProps && advPartProps[particleindex].size > 0) // use advanced size properties (0 means use global size including single pixel rendering) size = advPartProps[particleindex].size; @@ -846,7 +846,7 @@ void ParticleSystem2D::handleCollisions() { // handle a collision if close proximity is detected, i.e. dx and/or dy smaller than 2*PS_P_RADIUS // takes two pointers to the particles to collide and the particle hardness (softer means more energy lost in collision, 255 means full hard) -__attribute__((optimize("O2"))) void ParticleSystem2D::collideParticles(PSparticle &particle1, PSparticle &particle2, int32_t dx, int32_t dy, const uint32_t collDistSq) { +void WLED_O3_ATTR ParticleSystem2D::collideParticles(PSparticle &particle1, PSparticle &particle2, int32_t dx, int32_t dy, const uint32_t collDistSq) { int32_t distanceSquared = dx * dx + dy * dy; // Calculate relative velocity note: could zero check but that does not improve overall speed but deminish it as that is rarely the case and pushing is still required int32_t relativeVx = (int32_t)particle2.vx - (int32_t)particle1.vx; @@ -1494,7 +1494,7 @@ void ParticleSystem1D::render() { } // calculate pixel positions and brightness distribution and render the particle to local buffer or global buffer -__attribute__((optimize("O2"))) void ParticleSystem1D::renderParticle(const uint32_t particleindex, const uint8_t brightness, const CRGB &color, const bool wrap) { +void WLED_O2_ATTR ParticleSystem1D::renderParticle(const uint32_t particleindex, const uint8_t brightness, const CRGB &color, const bool wrap) { uint32_t size = particlesize; if (advPartProps) // use advanced size properties (1D system has no large size global rendering TODO: add large global rendering?) size = advPartProps[particleindex].size; @@ -1658,7 +1658,7 @@ void ParticleSystem1D::handleCollisions() { } // handle a collision if close proximity is detected, i.e. dx and/or dy smaller than 2*PS_P_RADIUS // takes two pointers to the particles to collide and the particle hardness (softer means more energy lost in collision, 255 means full hard) -__attribute__((optimize("O2"))) void ParticleSystem1D::collideParticles(PSparticle1D &particle1, const PSparticleFlags1D &particle1flags, PSparticle1D &particle2, const PSparticleFlags1D &particle2flags, const int32_t dx, const uint32_t dx_abs, const uint32_t collisiondistance) { +void WLED_O2_ATTR ParticleSystem1D::collideParticles(PSparticle1D &particle1, const PSparticleFlags1D &particle1flags, PSparticle1D &particle2, const PSparticleFlags1D &particle2flags, const int32_t dx, const uint32_t dx_abs, const uint32_t collisiondistance) { int32_t dv = particle2.vx - particle1.vx; int32_t dotProduct = (dx * dv); // is always negative if moving towards each other diff --git a/wled00/colors.cpp b/wled00/colors.cpp index 23151ecb..379afecf 100644 --- a/wled00/colors.cpp +++ b/wled00/colors.cpp @@ -8,7 +8,7 @@ /* * color blend function */ -IRAM_ATTR_YN __attribute__((hot)) uint32_t color_blend(uint32_t color1, uint32_t color2, uint_fast16_t blend, bool b16) { +uint32_t WLED_O2_ATTR IRAM_ATTR __attribute__((hot)) color_blend(uint32_t color1, uint32_t color2, uint_fast16_t blend, bool b16) { if ((color1 == color2) || (blend == 0)) return color1; // WLEDMM const uint_fast16_t blendmax = b16 ? 0xFFFF : 0xFF; if(blend >= blendmax) return color2; @@ -46,7 +46,7 @@ IRAM_ATTR_YN __attribute__((hot)) uint32_t color_blend(uint32_t color1, uint32_t * color add function that preserves ratio * idea: https://github.com/Aircoookie/WLED/pull/2465 by https://github.com/Proto-molecule */ -IRAM_ATTR_YN uint32_t color_add(uint32_t c1, uint32_t c2, bool fast) // WLEDMM added IRAM_ATTR_YN +uint32_t WLED_O2_ATTR color_add(uint32_t c1, uint32_t c2, bool fast) // WLEDMM added IRAM_ATTR_YN { if (c2 == 0) return c1; // WLEDMM shortcut if (c1 == 0) return c2; // WLEDMM shortcut @@ -80,7 +80,7 @@ IRAM_ATTR_YN uint32_t color_add(uint32_t c1, uint32_t c2, bool fast) // WLEDMM * if using "video" method the resulting color will never become black unless it is already black */ -IRAM_ATTR_YN __attribute__((hot)) uint32_t color_fade(uint32_t c1, uint8_t amount, bool video) +uint32_t IRAM_ATTR_YN __attribute__((hot)) color_fade(uint32_t c1, uint8_t amount, bool video) { if (c1 == 0 || amount == 0) return 0; // black or no change if (amount == 255) return c1; diff --git a/wled00/const.h b/wled00/const.h index 3257bc62..00facc76 100644 --- a/wled00/const.h +++ b/wled00/const.h @@ -149,14 +149,17 @@ #define AP_BEHAVIOR_NO_CONN 1 //Open when no connection (either after boot or if connection is lost) #define AP_BEHAVIOR_ALWAYS 2 //Always open #define AP_BEHAVIOR_BUTTON_ONLY 3 //Only when button pressed for 6 sec - +#define AP_BEHAVIOR_TEMPORARY 4 //Open AP when no connection after boot but only temporary //WLEDMM not yet supported +#ifndef WLED_AP_TIMEOUT + #define WLED_AP_TIMEOUT 300000 //Temporary AP timeout +#endif //Notifier callMode #define CALL_MODE_INIT 0 //no updates on init, can be used to disable updates #define CALL_MODE_DIRECT_CHANGE 1 #define CALL_MODE_BUTTON 2 //default button actions applied to selected segments -#define CALL_MODE_NOTIFICATION 3 -#define CALL_MODE_NIGHTLIGHT 4 -#define CALL_MODE_NO_NOTIFY 5 +#define CALL_MODE_NOTIFICATION 3 //caused by incoming notification (UDP or DMX preset) +#define CALL_MODE_NIGHTLIGHT 4 //nightlight progress +#define CALL_MODE_NO_NOTIFY 5 //change state but do not send notifications (UDP) #define CALL_MODE_FX_CHANGED 6 //no longer used #define CALL_MODE_HUE 7 #define CALL_MODE_PRESET_CYCLE 8 //no longer used @@ -272,6 +275,10 @@ #define COL_ORDER_GBR 5 #define COL_ORDER_MAX 5 +//ESP-NOW //WLEDMM not yet supported +#define ESP_NOW_STATE_UNINIT 0 +#define ESP_NOW_STATE_ON 1 +#define ESP_NOW_STATE_ERROR 2 //Button type #define BTN_TYPE_NONE 0 @@ -283,6 +290,7 @@ #define BTN_TYPE_TOUCH 6 #define BTN_TYPE_ANALOG 7 #define BTN_TYPE_ANALOG_INVERTED 8 +#define BTN_TYPE_TOUCH_SWITCH 9 //WLEDMM not yet supported //Ethernet board types #define WLED_NUM_ETH_TYPES 12 //WLEDMM +1 for Olimex ESP32-Gateway @@ -332,6 +340,7 @@ //Playlist option byte #define PL_OPTION_SHUFFLE 0x01 +#define PL_OPTION_RESTORE 0x02 //WLEDMM not yet supported // Segment capability byte #define SEG_CAPABILITY_RGB 0x01 @@ -341,8 +350,11 @@ // WLED Error modes #define ERR_NONE 0 // All good :) #define ERR_DENIED 1 // Permission denied -#define ERR_EEP_COMMIT 2 // Could not commit to EEPROM (wrong flash layout?) OBSOLETE +#define ERR_CONCURRENCY 2 // Conurrency (client active) //WLEDMM was ERR_EEP_COMMIT (obsolete) #define ERR_NOBUF 3 // JSON buffer was not released in time, request cannot be handled at this time +#define ERR_NOT_IMPL 4 // Not implemented +#define ERR_NORAM_PX 7 // not enough RAM for pixels +#define ERR_NORAM 8 // effect RAM depleted #define ERR_JSON 9 // JSON parsing failed (input too large?) #define ERR_FS_BEGIN 10 // Could not init filesystem (no partition?) #define ERR_FS_QUOTA 11 // The FS is full or the maximum file size is reached @@ -497,6 +509,23 @@ #endif #endif +// Web server limits +#ifdef ESP8266 +// Minimum heap to consider handling a request +#define WLED_REQUEST_MIN_HEAP (8*1024) +// Estimated maximum heap required by any one request +#define WLED_REQUEST_HEAP_USAGE (6*1024) +#else +// ESP32 TCP stack needs much more RAM than ESP8266 +// Minimum heap remaining before queuing a request +#define WLED_REQUEST_MIN_HEAP (12*1024) +// Estimated maximum heap required by any one request +#define WLED_REQUEST_HEAP_USAGE (12*1024) +#endif +// Maximum number of requests in queue; absolute cap on web server resource usage. +// Websockets do not count against this limit. +#define WLED_REQUEST_MAX_QUEUE 6 + //#define MIN_HEAP_SIZE (8k for AsyncWebServer) #if !defined(MIN_HEAP_SIZE) #define MIN_HEAP_SIZE 8192 @@ -569,4 +598,12 @@ #define IRAM_ATTR_YN #endif +#define WLED_O2_ATTR __attribute__((optimize("O2"))) + +#if !defined(WLEDMM_SAVE_FLASH) // WLEDMM +#define WLED_O3_ATTR __attribute__((optimize("O3,fast_math"))) +#else +#define WLED_O3_ATTR WLED_O2_ATTR // -O3 increases flash size due to loop unrolling +#endif + #endif diff --git a/wled00/data/index.js b/wled00/data/index.js index 29cd854a..3581442d 100644 --- a/wled00/data/index.js +++ b/wled00/data/index.js @@ -1976,6 +1976,9 @@ function readState(s,command=false) case 3: errstr = "Buffer locked!"; break; + case 7: + errstr = "No RAM for buffer!"; + break; case 8: errstr = "Effect RAM depleted!"; break; From 0071677340601dbee8690318bcc4f5141bdecc5a Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sat, 25 Oct 2025 23:59:29 +0200 Subject: [PATCH 029/170] (experimental) tweak optimization level of color functions --- wled00/colorTools.hpp | 9 +++++---- wled00/colors.cpp | 7 ++++--- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/wled00/colorTools.hpp b/wled00/colorTools.hpp index 9d600b3e..27249e31 100644 --- a/wled00/colorTools.hpp +++ b/wled00/colorTools.hpp @@ -25,8 +25,9 @@ /* * color blend function (from colors.cpp) */ -inline __attribute__((hot,const)) uint32_t color_blend(uint32_t color1, uint32_t color2, uint_fast16_t blend, bool b16=false) { - if ((color1 == color2) || (blend == 0)) return color1; // WLEDMM +inline WLED_O3_ATTR __attribute__((hot,const)) uint32_t color_blend(uint32_t color1, uint32_t color2, uint_fast16_t blend, bool b16=false) { + // min / max blend checking is omitted: calls with 0 or 255 are rare, checking lowers overall performance + // if ((color1 == color2) || (blend == 0)) return color1; // WLEDMM const uint_fast16_t blendmax = b16 ? 0xFFFF : 0xFF; if(blend >= blendmax) return color2; const uint_fast8_t shift = b16 ? 16 : 8; @@ -64,7 +65,7 @@ inline __attribute__((hot,const)) uint32_t color_blend(uint32_t color1, uint32_t * idea: https://github.com/Aircoookie/WLED/pull/2465 by https://github.com/Proto-molecule */ -inline __attribute__((hot,const)) uint32_t color_add(uint32_t c1, uint32_t c2, bool fast=false) +inline WLED_O3_ATTR __attribute__((hot,const)) uint32_t color_add(uint32_t c1, uint32_t c2, bool fast=false) { if (c2 == 0) return c1; // WLEDMM shortcut if (c1 == 0) return c2; // WLEDMM shortcut @@ -98,7 +99,7 @@ inline __attribute__((hot,const)) uint32_t color_add(uint32_t c1, uint32_t c2, b * if using "video" method the resulting color will never become black unless it is already black */ -inline __attribute__((hot,const)) uint32_t color_fade(uint32_t c1, uint8_t amount, bool video=false) +inline WLED_O2_ATTR __attribute__((hot,const)) uint32_t color_fade(uint32_t c1, uint8_t amount, bool video=false) { if (c1 == 0 || amount == 0) return 0; // black or no change if (amount == 255) return c1; diff --git a/wled00/colors.cpp b/wled00/colors.cpp index 379afecf..9b5a03d3 100644 --- a/wled00/colors.cpp +++ b/wled00/colors.cpp @@ -8,8 +8,9 @@ /* * color blend function */ -uint32_t WLED_O2_ATTR IRAM_ATTR __attribute__((hot)) color_blend(uint32_t color1, uint32_t color2, uint_fast16_t blend, bool b16) { - if ((color1 == color2) || (blend == 0)) return color1; // WLEDMM +uint32_t WLED_O3_ATTR IRAM_ATTR_YN __attribute__((hot)) color_blend(uint32_t color1, uint32_t color2, uint_fast16_t blend, bool b16) { + // min / max blend checking is omitted: calls with 0 or 255 are rare, checking lowers overall performance + //if ((color1 == color2) || (blend == 0)) return color1; // WLEDMM const uint_fast16_t blendmax = b16 ? 0xFFFF : 0xFF; if(blend >= blendmax) return color2; const uint_fast8_t shift = b16 ? 16 : 8; @@ -80,7 +81,7 @@ uint32_t WLED_O2_ATTR color_add(uint32_t c1, uint32_t c2, bool fast) // WLEDMM * if using "video" method the resulting color will never become black unless it is already black */ -uint32_t IRAM_ATTR_YN __attribute__((hot)) color_fade(uint32_t c1, uint8_t amount, bool video) +uint32_t WLED_O2_ATTR IRAM_ATTR_YN __attribute__((hot)) color_fade(uint32_t c1, uint8_t amount, bool video) { if (c1 == 0 || amount == 0) return 0; // black or no change if (amount == 255) return c1; From 3e99bb8643444736fa686c49e7d3881c4ed9efe4 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sun, 26 Oct 2025 00:35:06 +0200 Subject: [PATCH 030/170] Fix fast-math attribute syntax in const.h a fatal typo --- wled00/const.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wled00/const.h b/wled00/const.h index 00facc76..bf0e62ad 100644 --- a/wled00/const.h +++ b/wled00/const.h @@ -601,7 +601,7 @@ #define WLED_O2_ATTR __attribute__((optimize("O2"))) #if !defined(WLEDMM_SAVE_FLASH) // WLEDMM -#define WLED_O3_ATTR __attribute__((optimize("O3,fast_math"))) +#define WLED_O3_ATTR __attribute__((optimize("O3,fast-math"))) #else #define WLED_O3_ATTR WLED_O2_ATTR // -O3 increases flash size due to loop unrolling #endif From 56380ce04c4620fdd069ef433b60387a2c930891 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sun, 26 Oct 2025 01:41:30 +0200 Subject: [PATCH 031/170] slightly faster to keep IRAM_ATTR for sPC and color_add --- wled00/FX_fcn.cpp | 2 +- wled00/colors.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index 688596eb..e3c30c68 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -938,7 +938,7 @@ static void xyFromBlock(uint16_t &x,uint16_t &y, uint16_t i, uint16_t vW, uint16 } -void WLED_O2_ATTR __attribute__((hot)) Segment::setPixelColor(int i, uint32_t col) //WLEDMM: IRAM_ATTR conditionally +void IRAM_ATTR_YN WLED_O2_ATTR __attribute__((hot)) Segment::setPixelColor(int i, uint32_t col) //WLEDMM: IRAM_ATTR conditionally { if (!isActive()) return; // not active #ifndef WLED_DISABLE_2D diff --git a/wled00/colors.cpp b/wled00/colors.cpp index 9b5a03d3..41028092 100644 --- a/wled00/colors.cpp +++ b/wled00/colors.cpp @@ -47,7 +47,7 @@ uint32_t WLED_O3_ATTR IRAM_ATTR_YN __attribute__((hot)) color_blend(uint32_t col * color add function that preserves ratio * idea: https://github.com/Aircoookie/WLED/pull/2465 by https://github.com/Proto-molecule */ -uint32_t WLED_O2_ATTR color_add(uint32_t c1, uint32_t c2, bool fast) // WLEDMM added IRAM_ATTR_YN +uint32_t WLED_O2_ATTR IRAM_ATTR_YN color_add(uint32_t c1, uint32_t c2, bool fast) // WLEDMM added IRAM_ATTR_YN { if (c2 == 0) return c1; // WLEDMM shortcut if (c1 == 0) return c2; // WLEDMM shortcut From bb84f859242f55c3a9f6d4817490877574cc631c Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Mon, 27 Oct 2025 01:12:30 +0100 Subject: [PATCH 032/170] FxParticlesystem Fix memory calculation of framebuffer size #275 Updated memory calculation for CRGB to use virtual width and height. Somehow virtualLength is not reliable, so use vWidth * vHeight --- wled00/FXparticleSystem.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wled00/FXparticleSystem.cpp b/wled00/FXparticleSystem.cpp index cd537e8c..d5342f04 100644 --- a/wled00/FXparticleSystem.cpp +++ b/wled00/FXparticleSystem.cpp @@ -1103,7 +1103,7 @@ bool allocateParticleSystemMemory2D(uint32_t numparticles, uint32_t numsources, if (sizecontrol) requiredmemory += sizeof(PSsizeControl) * numparticles; requiredmemory += sizeof(PSsource) * numsources; - requiredmemory += sizeof(CRGB) * SEGMENT.virtualLength(); // virtualLength is witdh * height + requiredmemory += sizeof(CRGB) * uint32_t(SEGMENT.calc_virtualWidth()) * uint32_t(SEGMENT.calc_virtualHeight()); // virtualLength not reliable, better to use vWidth * vHeight requiredmemory += additionalbytes + 3; // add 3 to ensure there is room for stuffing bytes //requiredmemory = (requiredmemory + 3) & ~0x03; // align memory block to next 4-byte boundary PSPRINTLN("mem alloc: " + String(requiredmemory)); @@ -1938,4 +1938,4 @@ static bool checkBoundsAndWrap(int32_t &position, const int32_t max, const int32 c.b = ((c.b * scale) >> 8); } -#endif // !(defined(WLED_DISABLE_PARTICLESYSTEM2D) && defined(WLED_DISABLE_PARTICLESYSTEM1D)) \ No newline at end of file +#endif // !(defined(WLED_DISABLE_PARTICLESYSTEM2D) && defined(WLED_DISABLE_PARTICLESYSTEM1D)) From 3752409b46d6d4f3333619d892d0e7d4985ce006 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Mon, 27 Oct 2025 11:24:12 +0100 Subject: [PATCH 033/170] no more ORANGE on effect memory failure For maintainers of custom effects: replace "return mode_solid()" with "return mode_oops()" Effect errors fall back to Akemi (2D) or Rainbow(1D) instead of SOLID ORANGE. --- wled00/FX.cpp | 379 +++++++++++++++++++++++-------------------- wled00/FX_fcn.cpp | 4 +- wled00/data/index.js | 2 +- 3 files changed, 207 insertions(+), 178 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index ae2d4a1a..63a1f154 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -118,8 +118,35 @@ static um_data_t* getAudioData() { } return um_data; } + // effect functions +// forward declarations +static uint16_t mode_oops(void); +uint16_t mode_rainbow_cycle(void); +static uint16_t mode_2DAkemi_core(bool withSound = true); +uint16_t mode_static(void); + +/* + * replacement for mode_static in case of out-of-memory. + */ +static uint16_t mode_oops(void) { + strip._colors_t[0] = RED; + strip._colors_t[1] = BLUE; + strip._colors_t[2] = GREEN; + errorFlag = ERR_NORAM_PX; + if (SEGLEN <= 1) return mode_oops(); + const uint16_t width = SEGMENT.is2D() ? SEGMENT.virtualWidth() : SEGMENT.virtualLength(); + const uint16_t height = SEGMENT.virtualHeight(); + + // 2D fallback: akemi in blue + if (SEGMENT.is2D() && (width > 3) && (height > 3)) + return mode_2DAkemi_core(false); + + // 1D fallback: rainbow + return mode_rainbow_cycle(); +} + /* * No blinking. Just plain old static light. */ @@ -331,7 +358,7 @@ static const char _data_FX_MODE_RANDOM_COLOR[] PROGMEM = "Random Colors@!,Fade t * to new random colors. */ uint16_t mode_dynamic(void) { - if (!SEGENV.allocateData(SEGLEN)) return mode_static(); //allocation failed + if (!SEGENV.allocateData(SEGLEN)) return mode_oops(); //allocation failed if(SEGENV.call == 0) { SEGMENT.setUpLeds(); // WLEDMM use lossless getPixelColor() @@ -806,7 +833,7 @@ static const char _data_FX_MODE_MULTI_STROBE[] PROGMEM = "Strobe Mega@!,!;!,!;!; * Android loading circle */ uint16_t mode_android(void) { - if (SEGLEN <= 1) return mode_static(); // WLEDMM to prevent division by zero + if (SEGLEN <= 1) return mode_oops(); // WLEDMM to prevent division by zero for (int i = 0; i < SEGLEN; i++) { SEGMENT.setPixelColor(i, SEGMENT.color_from_palette(i, true, PALETTE_SOLID_WRAP, 1)); } @@ -1021,7 +1048,7 @@ static const char _data_FX_MODE_COLORFUL[] PROGMEM = "Colorful@!,Saturation;1,2, * Emulates a traffic light. */ uint16_t mode_traffic_light(void) { - if (SEGLEN == 1) return mode_static(); + if (SEGLEN == 1) return mode_oops(); for (int i=0; i < SEGLEN; i++) SEGMENT.setPixelColor(i, SEGMENT.color_from_palette(i, true, PALETTE_SOLID_WRAP, 1)); uint32_t mdelay = 500; @@ -1054,7 +1081,7 @@ static const char _data_FX_MODE_TRAFFIC_LIGHT[] PROGMEM = "Traffic Light@!,US st */ #define FLASH_COUNT 4 uint16_t mode_chase_flash(void) { - if (SEGLEN <= 1) return mode_static(); + if (SEGLEN <= 1) return mode_oops(); uint8_t flash_step = SEGENV.call % ((FLASH_COUNT * 2) + 1); for (int i = 0; i < SEGLEN; i++) { @@ -1084,7 +1111,7 @@ static const char _data_FX_MODE_CHASE_FLASH[] PROGMEM = "Chase Flash@!;Bg,Fx;!"; * Prim flashes running, followed by random color. */ uint16_t mode_chase_flash_random(void) { - if (SEGLEN == 1) return mode_static(); + if (SEGLEN == 1) return mode_oops(); uint8_t flash_step = SEGENV.call % ((FLASH_COUNT * 2) + 1); for (int i = 0; i < SEGENV.aux1; i++) { @@ -1219,7 +1246,7 @@ static const char _data_FX_MODE_DUAL_LARSON_SCANNER[] PROGMEM = "Scanner Dual@!, * Firing comets from one end. "Lighthouse" */ uint16_t mode_comet(void) { - if (SEGLEN == 1) return mode_static(); + if (SEGLEN == 1) return mode_oops(); uint16_t counter = strip.now * ((SEGMENT.speed >>2) +1); uint16_t index = (counter * SEGLEN) >> 16; if (SEGENV.call == 0) { @@ -1251,7 +1278,7 @@ static const char _data_FX_MODE_COMET[] PROGMEM = "Lighthouse@!,Fade rate;!,!;!" * Fireworks function. */ static uint16_t mode_fireworks_core(bool useaudio) { - if (SEGLEN == 1) return mode_static(); + if (SEGLEN == 1) return mode_oops(); const uint16_t width = SEGMENT.is2D() ? SEGMENT.virtualWidth() : SEGMENT.virtualLength(); const uint16_t height = SEGMENT.virtualHeight(); @@ -1326,7 +1353,7 @@ static const char _data_FX_MODE_FIREWORKS_AR[] PROGMEM = "Fireworks audio ☾@,F //Twinkling LEDs running. Inspired by https://github.com/kitesurfer1404/WS2812FX/blob/master/src/custom/Rain.h uint16_t mode_rain() { - if (SEGLEN == 1) return mode_static(); + if (SEGLEN == 1) return mode_oops(); const uint16_t width = SEGMENT.virtualWidth(); const uint16_t height = SEGMENT.virtualHeight(); if(SEGENV.call == 0) { @@ -1441,7 +1468,7 @@ static const char _data_FX_MODE_LOADING[] PROGMEM = "Loading@!,Fade;!,!;!;;ix=16 //American Police Light with all LEDs Red and Blue uint16_t police_base(uint32_t color1, uint32_t color2) { - if (SEGLEN == 1) return mode_static(); + if (SEGLEN == 1) return mode_oops(); uint16_t delay = 1 + (FRAMETIME<<3) / SEGLEN; // longer segments should change faster uint32_t it = strip.now / map(SEGMENT.speed, 0, 255, delay<<4, delay); uint16_t offset = it % SEGLEN; @@ -1570,7 +1597,7 @@ static const char _data_FX_MODE_FAIRY[] PROGMEM = "Fairy@!,# of flashers;!,!;!"; */ uint16_t mode_fairytwinkle() { uint16_t dataSize = sizeof(flasher) * SEGLEN; - if (!SEGENV.allocateData(dataSize)) return mode_static(); //allocation failed + if (!SEGENV.allocateData(dataSize)) return mode_oops(); //allocation failed Flasher* flashers = reinterpret_cast(SEGENV.data); uint16_t now16 = strip.now & 0xFFFF; uint16_t PRNG16 = 5100 + strip.getCurrSegmentId(); @@ -1778,7 +1805,7 @@ uint16_t mode_multi_comet(void) { uint32_t cycleTime = 10 + (uint32_t)(255 - SEGMENT.speed); uint32_t it = strip.now / cycleTime; if (SEGENV.step == it) return FRAMETIME; - if (!SEGENV.allocateData(sizeof(uint16_t) * 8)) return mode_static(); //allocation failed + if (!SEGENV.allocateData(sizeof(uint16_t) * 8)) return mode_oops(); //allocation failed if (SEGENV.call == 0) {SEGENV.setUpLeds(); SEGMENT.fill(BLACK);} // WLEDMM use lossless getPixelColor() SEGMENT.fade_out(SEGMENT.intensity); @@ -1815,7 +1842,7 @@ uint16_t mode_multi_comet_ar(void) { uint32_t it = strip.now / cycleTime; if (SEGENV.step == it) return FRAMETIME; // too early - if (!SEGENV.allocateData(sizeof(uint16_t) * MAX_COMETS)) return mode_static(); //allocation failed + if (!SEGENV.allocateData(sizeof(uint16_t) * MAX_COMETS)) return mode_oops(); //allocation failed uint16_t* comets = reinterpret_cast(SEGENV.data); if (SEGENV.call == 0) { // do some initializations SEGMENT.setUpLeds(); SEGMENT.fill(BLACK); @@ -1914,7 +1941,7 @@ uint16_t mode_oscillate(void) { uint8_t numOscillators = 3; uint16_t dataSize = sizeof(oscillator) * numOscillators; - if (!SEGENV.allocateData(dataSize)) return mode_static(); //allocation failed + if (!SEGENV.allocateData(dataSize)) return mode_oops(); //allocation failed Oscillator* oscillators = reinterpret_cast(SEGENV.data); @@ -1963,7 +1990,7 @@ static const char _data_FX_MODE_OSCILLATE[] PROGMEM = "Oscillate"; //TODO uint16_t mode_lightning(void) { - if (SEGLEN == 1) return mode_static(); + if (SEGLEN == 1) return mode_oops(); uint16_t ledstart = random16(SEGLEN); // Determine starting location of flash uint16_t ledlen = 1 + random16(SEGLEN -ledstart); // Determine length of flash (not to go beyond NUM_LEDS-1) uint8_t bri = 255/random8(1, 3); @@ -2114,7 +2141,7 @@ static const char _data_FX_MODE_PARTYJERK[] PROGMEM = "Party jerk@Effect speed,S //eight colored dots, weaving in and out of sync with each other uint16_t mode_juggle(void) { - if (SEGLEN == 1) return mode_static(); + if (SEGLEN == 1) return mode_oops(); if (SEGENV.call == 0) { SEGMENT.setUpLeds(); //lossless getPixelColor() SEGMENT.fill(BLACK); @@ -2184,9 +2211,9 @@ static const char _data_FX_MODE_PALETTE[] PROGMEM = "Palette@Cycle speed;;!;;c3= // feel of your fire: COOLING (used in step 1 above) (Speed = COOLING), and SPARKING (used // in step 3 above) (Effect Intensity = Sparking). uint16_t mode_fire_2012() { - if (SEGLEN == 1) return mode_static(); + if (SEGLEN == 1) return mode_oops(); const uint16_t strips = SEGMENT.nrOfVStrips(); - if (!SEGENV.allocateData(strips * SEGLEN)) return mode_static(); //allocation failed + if (!SEGENV.allocateData(strips * SEGLEN)) return mode_oops(); //allocation failed byte* heat = SEGENV.data; if (SEGENV.call == 0) {SEGENV.setUpLeds(); SEGMENT.fill(BLACK);} // WLEDMM use lossless getPixelColor() @@ -2418,7 +2445,7 @@ static const char _data_FX_MODE_NOISE16_4[] PROGMEM = "Noise 4@!;!;!"; //based on https://gist.github.com/kriegsman/5408ecd397744ba0393e uint16_t mode_colortwinkle() { uint16_t dataSize = (SEGLEN+7) >> 3; //1 bit per LED - if (!SEGENV.allocateData(dataSize)) return mode_static(); //allocation failed + if (!SEGENV.allocateData(dataSize)) return mode_oops(); //allocation failed if(SEGENV.call == 0) { SEGMENT.setUpLeds(); // WLEDMM use lossless getPixelColor() SEGMENT.fill(BLACK); @@ -2500,8 +2527,8 @@ static const char _data_FX_MODE_LAKE[] PROGMEM = "Lake@!;Fx;!"; // send a meteor from begining to to the end of the strip with a trail that randomly decays. // adapted from https://www.tweaking4all.com/hardware/arduino/adruino-led-strip-effects/#LEDStripEffectMeteorRain uint16_t mode_meteor() { - if (SEGLEN == 1) return mode_static(); - if (!SEGENV.allocateData(SEGLEN)) return mode_static(); //allocation failed + if (SEGLEN == 1) return mode_oops(); + if (!SEGENV.allocateData(SEGLEN)) return mode_oops(); //allocation failed byte* trail = SEGENV.data; @@ -2540,8 +2567,8 @@ static const char _data_FX_MODE_METEOR[] PROGMEM = "Meteor@!,Trail,,,,Gradient;; // send a meteor from begining to to the end of the strip with a trail that randomly decays. // adapted from https://www.tweaking4all.com/hardware/arduino/adruino-led-strip-effects/#LEDStripEffectMeteorRain uint16_t mode_meteor_smooth() { - if (SEGLEN == 1) return mode_static(); - if (!SEGENV.allocateData(SEGLEN)) return mode_static(); //allocation failed + if (SEGLEN == 1) return mode_oops(); + if (!SEGENV.allocateData(SEGLEN)) return mode_oops(); //allocation failed byte* trail = SEGENV.data; @@ -2578,7 +2605,7 @@ static const char _data_FX_MODE_METEOR_SMOOTH[] PROGMEM = "Meteor Smooth@!,Trail //Railway Crossing / Christmas Fairy lights uint16_t mode_railway() { - if (SEGLEN == 1) return mode_static(); + if (SEGLEN == 1) return mode_oops(); uint16_t dur = (256 - SEGMENT.speed) * 40; uint16_t rampdur = (dur * SEGMENT.intensity) >> 8; if (SEGENV.step > dur) @@ -2636,7 +2663,7 @@ uint16_t ripple_base() random16_add_entropy(esp_random() & 0xFFFF); // improve randomness (esp32) #endif - if (!SEGENV.allocateData(dataSize)) return mode_static(); //allocation failed + if (!SEGENV.allocateData(dataSize)) return mode_oops(); //allocation failed if (SEGENV.call == 0) {SEGENV.setUpLeds(); SEGMENT.fill(BLACK);} // WLEDMM use lossless getPixelColor() Ripple* ripples = reinterpret_cast(SEGENV.data); @@ -2692,7 +2719,7 @@ uint16_t ripple_base() uint16_t mode_ripple(void) { - if (SEGLEN == 1) return mode_static(); + if (SEGLEN == 1) return mode_oops(); if (!SEGMENT.check2) SEGMENT.fill(SEGCOLOR(1)); else SEGMENT.fade_out(250); return ripple_base(); @@ -2701,7 +2728,7 @@ static const char _data_FX_MODE_RIPPLE[] PROGMEM = "Ripple@!,Wave #,,,,,Overlay; uint16_t mode_ripple_rainbow(void) { - if (SEGLEN == 1) return mode_static(); + if (SEGLEN == 1) return mode_oops(); if (SEGENV.call ==0) { SEGENV.aux0 = random8(); SEGENV.aux1 = random8(); @@ -2866,12 +2893,12 @@ static const char _data_FX_MODE_TWINKLECAT[] PROGMEM = "Twinklecat@!,Twinkle rat //inspired by https://www.tweaking4all.com/hardware/arduino/adruino-led-strip-effects/#LEDStripEffectBlinkingHalloweenEyes uint16_t mode_halloween_eyes() { - if (SEGLEN == 1) return mode_static(); + if (SEGLEN == 1) return mode_oops(); const uint16_t maxWidth = strip.isMatrix ? SEGMENT.virtualWidth() : SEGLEN; const uint16_t HALLOWEEN_EYE_SPACE = MAX(2, strip.isMatrix ? SEGMENT.virtualWidth()>>4: SEGLEN>>5); const uint16_t HALLOWEEN_EYE_WIDTH = HALLOWEEN_EYE_SPACE/2; uint16_t eyeLength = (2*HALLOWEEN_EYE_WIDTH) + HALLOWEEN_EYE_SPACE; - if (eyeLength >= maxWidth) return mode_static(); //bail if segment too short + if (eyeLength >= maxWidth) return mode_oops(); //bail if segment too short if (!SEGMENT.check2) SEGMENT.fill(SEGCOLOR(1)); //fill background @@ -2976,7 +3003,7 @@ static const char _data_FX_MODE_TRI_STATIC_PATTERN[] PROGMEM = "Solid Pattern Tr uint16_t spots_base(uint16_t threshold) { - if (SEGLEN == 1) return mode_static(); + if (SEGLEN == 1) return mode_oops(); if (!SEGMENT.check2) SEGMENT.fill(SEGCOLOR(1)); uint16_t maxZones = SEGLEN >> 2; @@ -3032,12 +3059,12 @@ typedef struct Ball { * Bouncing Balls Effect */ uint16_t mode_bouncing_balls(void) { - if (SEGLEN == 1) return mode_static(); + if (SEGLEN == 1) return mode_oops(); //allocate segment data const uint16_t strips = SEGMENT.nrOfVStrips(); // adapt for 2D constexpr size_t maxNumBalls = 16; uint16_t dataSize = sizeof(ball) * maxNumBalls; - if (!SEGENV.allocateData(dataSize * strips)) return mode_static(); //allocation failed + if (!SEGENV.allocateData(dataSize * strips)) return mode_oops(); //allocation failed Ball* balls = reinterpret_cast(SEGENV.data); @@ -3118,7 +3145,7 @@ static uint16_t rolling_balls(void) { //allocate segment data const uint16_t maxNumBalls = 16; // 255/16 + 1 uint16_t dataSize = sizeof(rball_t) * maxNumBalls; - if (!SEGENV.allocateData(dataSize)) return mode_static(); //allocation failed + if (!SEGENV.allocateData(dataSize)) return mode_oops(); //allocation failed rball_t *balls = reinterpret_cast(SEGENV.data); @@ -3203,7 +3230,7 @@ static const char _data_FX_MODE_ROLLINGBALLS[] PROGMEM = "Rolling Balls@!,# of b * Sinelon stolen from FASTLED examples */ uint16_t sinelon_base(bool dual, bool rainbow=false) { - if (SEGLEN == 1) return mode_static(); + if (SEGLEN == 1) return mode_oops(); if (SEGENV.call == 0) { SEGENV.setUpLeds(); SEGMENT.fill(BLACK); } // WLEDMM use lossless getPixelColor() SEGMENT.fade_out(SEGMENT.intensity); uint16_t pos = beatsin16_t(SEGMENT.speed/10,0,SEGLEN-1); @@ -3302,7 +3329,7 @@ typedef struct Spark { * modified from https://github.com/kitesurfer1404/WS2812FX/blob/master/src/custom/Popcorn.h */ static uint16_t mode_popcorn_core(bool useaudio) { - if (SEGLEN == 1) return mode_static(); + if (SEGLEN == 1) return mode_oops(); //allocate segment data uint16_t strips = SEGMENT.nrOfVStrips(); size_t dataSize = sizeof(spark) * maxNumPopcorn; @@ -3312,7 +3339,7 @@ static uint16_t mode_popcorn_core(bool useaudio) { neededPopcorn = min(max(neededPopcorn, uint8_t(2)), uint8_t(maxNumPopcorn)); dataSize = sizeof(spark) * neededPopcorn; } - if (!SEGENV.allocateData(dataSize * strips)) return mode_static(); //allocation failed + if (!SEGENV.allocateData(dataSize * strips)) return mode_oops(); //allocation failed Spark* popcorn = reinterpret_cast(SEGENV.data); @@ -3527,7 +3554,7 @@ typedef struct particle { } star; static uint16_t mode_starburst_core(bool useaudio) { - if (SEGLEN == 1) return mode_static(); + if (SEGLEN == 1) return mode_oops(); uint16_t maxData = FAIR_DATA_PER_SEG; //ESP8266: 256 ESP32: 640 uint8_t segs = strip.getActiveSegmentsNum(); if (segs <= (strip.getMaxSegments() /2)) maxData *= 2; //ESP8266: 512 if <= 8 segs ESP32: 1280 if <= 16 segs @@ -3538,7 +3565,7 @@ static uint16_t mode_starburst_core(bool useaudio) { if (numStars > maxStars) numStars = maxStars; uint16_t dataSize = sizeof(star) * numStars; - if (!SEGENV.allocateData(dataSize)) return mode_static(); //allocation failed + if (!SEGENV.allocateData(dataSize)) return mode_oops(); //allocation failed uint32_t it = strip.now; @@ -3677,7 +3704,7 @@ static const char _data_FX_MODE_STARBURST_AR[] PROGMEM = "Fw Starburst audio ☾ */ uint16_t mode_exploding_fireworks(void) { - if (SEGLEN == 1) return mode_static(); + if (SEGLEN == 1) return mode_oops(); const uint16_t cols = strip.isMatrix ? SEGMENT.virtualWidth() : 1; const uint16_t rows = strip.isMatrix ? SEGMENT.virtualHeight() : SEGMENT.virtualLength(); if (SEGENV.call == 0) { @@ -3694,7 +3721,7 @@ uint16_t mode_exploding_fireworks(void) unsigned numSparks = min(5 + ((rows*cols) >> 1), maxSparks); unsigned dataSize = sizeof(spark) * numSparks; - if (!SEGENV.allocateData(dataSize + sizeof(float))) return mode_static(); //allocation failed + if (!SEGENV.allocateData(dataSize + sizeof(float))) return mode_oops(); //allocation failed float *dying_gravity = reinterpret_cast(SEGENV.data + dataSize); if (dataSize != SEGENV.aux1) { //reset to flare if sparks were reallocated (it may be good idea to reset segment if bounds change) @@ -3831,12 +3858,12 @@ typedef struct __attribute__ ((packed)) SparkDrop { */ uint16_t mode_drip(void) { - if (SEGLEN == 1) return mode_static(); + if (SEGLEN == 1) return mode_oops(); //allocate segment data uint16_t strips = SEGMENT.nrOfVStrips(); constexpr int maxNumDrops = 4; uint16_t dataSize = sizeof(sparkdrop) * maxNumDrops; - if (!SEGENV.allocateData(dataSize * strips)) return mode_static(); //allocation failed + if (!SEGENV.allocateData(dataSize * strips)) return mode_oops(); //allocation failed SparkDrop* drops = reinterpret_cast(SEGENV.data); if (SEGENV.call == 0) { @@ -3950,10 +3977,10 @@ typedef struct Tetris { } tetris; uint16_t mode_tetrix(void) { - if (SEGLEN == 1) return mode_static(); + if (SEGLEN == 1) return mode_oops(); uint16_t strips = SEGMENT.nrOfVStrips(); // allow running on virtual strips (columns in 2D segment) uint16_t dataSize = sizeof(tetris); - if (!SEGENV.allocateData(dataSize * strips)) return mode_static(); //allocation failed + if (!SEGENV.allocateData(dataSize * strips)) return mode_oops(); //allocation failed Tetris* drops = reinterpret_cast(SEGENV.data); //if (SEGENV.call == 0) SEGMENT.fill(SEGCOLOR(1)); // will fill entire segment (1D or 2D), then use drop->step = 0 below @@ -4259,7 +4286,7 @@ static const char _data_FX_MODE_PACIFICA[] PROGMEM = "Pacifica@!,Angle;;!;;pal=5 * Mode simulates a gradual sunrise */ uint16_t mode_sunrise() { - if (SEGLEN == 1) return mode_static(); + if (SEGLEN == 1) return mode_oops(); //speed 0 - static sun //speed 1 - 60: sunrise time in minutes //speed 60 - 120 : sunset time in minutes - 60; @@ -4373,7 +4400,7 @@ uint16_t mode_noisepal(void) { // Slow noise //#define scale 30 uint16_t dataSize = sizeof(CRGBPalette16) * 2; //allocate space for 2 Palettes (2 * 16 * 3 = 96 bytes) - if (!SEGENV.allocateData(dataSize)) return mode_static(); //allocation failed + if (!SEGENV.allocateData(dataSize)) return mode_oops(); //allocation failed CRGBPalette16* palettes = reinterpret_cast(SEGENV.data); @@ -4472,7 +4499,7 @@ static const char _data_FX_MODE_FLOW[] PROGMEM = "Flow@!,Zones;;!;;m12=1"; //ver */ uint16_t mode_chunchun(void) { - if (SEGLEN <= 1) return mode_static(); + if (SEGLEN <= 1) return mode_oops(); if (SEGENV.call == 0) {SEGENV.setUpLeds(); SEGMENT.fill(BLACK);} // WLEDMM use lossless getPixelColor() SEGMENT.fade_out(253); // add a bit of trail // WLEDMM fade rate above 253 has no effect uint32_t counter = ((strip.now * (96 + SEGMENT.speed)) >> 4); // WLEDMM same result, better resolution @@ -4525,13 +4552,13 @@ typedef struct Spotlight { */ uint16_t mode_dancing_shadows(void) { - if (SEGLEN == 1) return mode_static(); + if (SEGLEN == 1) return mode_oops(); uint8_t numSpotlights = map(SEGMENT.intensity, 0, 255, 2, SPOT_MAX_COUNT); // 49 on 32 segment ESP32, 17 on 16 segment ESP8266 bool initialize = SEGENV.aux0 != numSpotlights; SEGENV.aux0 = numSpotlights; uint16_t dataSize = sizeof(spotlight) * numSpotlights; - if (!SEGENV.allocateData(dataSize)) return mode_static(); //allocation failed + if (!SEGENV.allocateData(dataSize)) return mode_oops(); //allocation failed Spotlight* spotlights = reinterpret_cast(SEGENV.data); if (SEGENV.call == 0) SEGENV.setUpLeds(); // WLEDMM use lossless getPixelColor() @@ -4667,7 +4694,7 @@ static const char _data_FX_MODE_WASHING_MACHINE[] PROGMEM = "Washing Machine@!,! */ uint16_t mode_image(void) { #ifndef WLED_ENABLE_GIF - return mode_static(); + return mode_oops(); #else renderImageToSegment(SEGMENT); return FRAMETIME; @@ -4686,7 +4713,7 @@ static const char _data_FX_MODE_IMAGE[] PROGMEM = "Image@!,;;;12;sx=128"; uint16_t mode_blends(void) { uint16_t pixelLen = SEGLEN > UINT8_MAX ? UINT8_MAX : SEGLEN; uint16_t dataSize = sizeof(uint32_t) * (pixelLen + 1); // max segment length of 56 pixels on 16 segment ESP8266 - if (!SEGENV.allocateData(dataSize)) return mode_static(); //allocation failed + if (!SEGENV.allocateData(dataSize)) return mode_oops(); //allocation failed uint32_t* pixels = reinterpret_cast(SEGENV.data); uint8_t blendSpeed = map(SEGMENT.intensity, 0, UINT8_MAX, 10, 128); uint8_t shift = (strip.now * ((SEGMENT.speed >> 3) +1)) >> 8; @@ -4736,7 +4763,7 @@ uint16_t mode_tv_simulator(void) { uint16_t nr, ng, nb, r, g, b, i, hue; uint8_t sat, bri, j; - if (!SEGENV.allocateData(sizeof(tvSim))) return mode_static(); //allocation failed + if (!SEGENV.allocateData(sizeof(tvSim))) return mode_oops(); //allocation failed TvSim* tvSimulator = reinterpret_cast(SEGENV.data); uint8_t colorSpeed = map(SEGMENT.speed, 0, UINT8_MAX, 1, 20); @@ -4951,7 +4978,7 @@ uint16_t mode_aurora(void) { SEGENV.aux0 = SEGMENT.intensity; if(!SEGENV.allocateData(sizeof(AuroraWave) * SEGENV.aux1)) { // 26 on 32 segment ESP32, 9 on 16 segment ESP8266 - return mode_static(); //allocation failed + return mode_oops(); //allocation failed } waves = reinterpret_cast(SEGENV.data); @@ -5006,7 +5033,7 @@ static const char _data_FX_MODE_AURORA[] PROGMEM = "Aurora@!,!;1,2,3;!;;sx=24,pa // 16 bit perlinmove. Use Perlin Noise instead of sinewaves for movement. By Andrew Tuline. // Controls are speed, # of pixels, faderate. uint16_t mode_perlinmove(void) { - if (SEGLEN == 1) return mode_static(); + if (SEGLEN == 1) return mode_oops(); if (SEGENV.call == 0) {SEGENV.setUpLeds(); SEGMENT.fill(BLACK);} // WLEDMM use lossless getPixelColor() SEGMENT.fade_out(255-SEGMENT.custom1); for (int i = 0; i < SEGMENT.intensity/16 + 1; i++) { @@ -5069,7 +5096,7 @@ static const char _data_FX_MODE_FLOWSTRIPE[] PROGMEM = "Flow Stripe@Hue speed,Ef // Black hole uint16_t mode_2DBlackHole(void) { // By: Stepko https://editor.soulmatelights.com/gallery/1012 , Modified by: Andrew Tuline - if (!strip.isMatrix) return mode_static(); // not a 2D set-up + if (!strip.isMatrix) return mode_oops(); // not a 2D set-up const uint16_t cols = SEGMENT.virtualWidth(); const uint16_t rows = SEGMENT.virtualHeight(); @@ -5110,7 +5137,7 @@ static const char _data_FX_MODE_2DBLACKHOLE[] PROGMEM = "Black Hole@Fade rate,Ou // 2D Colored Bursts // //////////////////////////// uint16_t mode_2DColoredBursts() { // By: ldirko https://editor.soulmatelights.com/gallery/819-colored-bursts , modified by: Andrew Tuline - if (!strip.isMatrix) return mode_static(); // not a 2D set-up + if (!strip.isMatrix) return mode_oops(); // not a 2D set-up const uint16_t cols = SEGMENT.virtualWidth(); const uint16_t rows = SEGMENT.virtualHeight(); @@ -5164,7 +5191,7 @@ static const char _data_FX_MODE_2DCOLOREDBURSTS[] PROGMEM = "Colored Bursts@Spee // 2D DNA // ///////////////////// uint16_t mode_2Ddna(void) { // dna originally by by ldirko at https://pastebin.com/pCkkkzcs. Updated by Preyy. WLED conversion by Andrew Tuline. Phases added by @ewoudwijma - if (!strip.isMatrix) return mode_static(); // not a 2D set-up + if (!strip.isMatrix) return mode_oops(); // not a 2D set-up const uint16_t cols = SEGMENT.virtualWidth(); const uint16_t rows = SEGMENT.virtualHeight(); @@ -5209,7 +5236,7 @@ static const char _data_FX_MODE_2DDNA[] PROGMEM = "DNA@Scroll speed,Blur,Phases; // 2D DNA Spiral // ///////////////////////// uint16_t mode_2DDNASpiral() { // By: ldirko https://editor.soulmatelights.com/gallery/512-dna-spiral-variation , modified by: Andrew Tuline - if (!strip.isMatrix) return mode_static(); // not a 2D set-up + if (!strip.isMatrix) return mode_oops(); // not a 2D set-up const uint16_t cols = SEGMENT.virtualWidth(); const uint16_t rows = SEGMENT.virtualHeight(); @@ -5258,7 +5285,7 @@ static const char _data_FX_MODE_2DDNASPIRAL[] PROGMEM = "DNA Spiral@Scroll speed ///////////////////////// uint16_t mode_2DDrift() { // By: Stepko https://editor.soulmatelights.com/gallery/884-drift , Modified by: Andrew Tuline // optimized for large panels by @softhack007 - if (!strip.isMatrix) return mode_static(); // not a 2D set-up + if (!strip.isMatrix) return mode_oops(); // not a 2D set-up const uint16_t cols = SEGMENT.virtualWidth(); const uint16_t rows = SEGMENT.virtualHeight(); @@ -5312,7 +5339,7 @@ static const char _data_FX_MODE_2DDRIFT[] PROGMEM = "Drift@Rotation speed,Blur,, // 2D Firenoise // ////////////////////////// uint16_t mode_2Dfirenoise(void) { // firenoise2d. By Andrew Tuline. Yet another short routine. - if (!strip.isMatrix) return mode_static(); // not a 2D set-up + if (!strip.isMatrix) return mode_oops(); // not a 2D set-up const uint16_t cols = SEGMENT.virtualWidth(); const uint16_t rows = SEGMENT.virtualHeight(); @@ -5347,7 +5374,7 @@ static const char _data_FX_MODE_2DFIRENOISE[] PROGMEM = "Firenoise@X scale,Y sca // 2D Frizzles // ////////////////////////////// uint16_t mode_2DFrizzles(void) { // By: Stepko https://editor.soulmatelights.com/gallery/640-color-frizzles , Modified by: Andrew Tuline - if (!strip.isMatrix) return mode_static(); // not a 2D set-up + if (!strip.isMatrix) return mode_oops(); // not a 2D set-up const uint16_t cols = SEGMENT.virtualWidth(); const uint16_t rows = SEGMENT.virtualHeight(); @@ -5437,14 +5464,14 @@ class GameOfLifeGrid { uint16_t mode_2Dgameoflife(void) { // Written by Ewoud Wijma, inspired by https://natureofcode.com/book/chapter-7-cellular-automata/ // and https://github.com/DougHaber/nlife-color , Modified By: Brandon Butler - if (!strip.isMatrix) return mode_static(); // not a 2D set-up + if (!strip.isMatrix) return mode_oops(); // not a 2D set-up const uint16_t cols = SEGMENT.virtualWidth(); const uint16_t rows = SEGMENT.virtualHeight(); const size_t dataSize = SEGMENT.length() * sizeof(Cell); // Cell = 2 bytes const size_t totalSize = dataSize + 6; // 6 bytes for prevRows(2), prevCols(2), prevPalette, prevWrap - if (!SEGENV.allocateData(totalSize)) return mode_static(); //allocation failed + if (!SEGENV.allocateData(totalSize)) return mode_oops(); //allocation failed uint16_t *prevRows = reinterpret_cast(SEGENV.data); uint16_t *prevCols = reinterpret_cast(SEGENV.data + 2); uint8_t *prevPalette = reinterpret_cast (SEGENV.data + 4); @@ -5659,12 +5686,12 @@ static void setBitValue(uint8_t* byteArray, size_t n, bool value) { } uint16_t mode_2DSnowFall(void) { // By: Brandon Butler // Uses bit array to track snow/particles - if (!strip.isMatrix) return mode_static(); // Not a 2D set-up + if (!strip.isMatrix) return mode_oops(); // Not a 2D set-up const uint16_t cols = SEGMENT.virtualWidth(); const uint16_t rows = SEGMENT.virtualHeight(); const size_t dataSize = (SEGMENT.length() + 7) / 8; // Round up to nearest byte - if (!SEGENV.allocateData(dataSize)) return mode_static(); // Allocation failed + if (!SEGENV.allocateData(dataSize)) return mode_oops(); // Allocation failed byte *grid = reinterpret_cast(SEGENV.data); bool overlay = SEGMENT.check2; // Overlay is inverted. Only draws non-snow. Layer 1 controls snow color @@ -5771,7 +5798,7 @@ static const char _data_FX_MODE_2DSNOWFALL[] PROGMEM = "Snow Fall ☾@!,Spawn Ra // 2D Hiphotic // ///////////////////////// uint16_t mode_2DHiphotic() { // By: ldirko https://editor.soulmatelights.com/gallery/810 , Modified by: Andrew Tuline - if (!strip.isMatrix) return mode_static(); // not a 2D set-up + if (!strip.isMatrix) return mode_oops(); // not a 2D set-up const uint16_t cols = SEGMENT.virtualWidth(); const uint16_t rows = SEGMENT.virtualHeight(); @@ -5803,12 +5830,12 @@ typedef struct Julia { } julia; uint16_t mode_2DJulia(void) { // An animated Julia set by Andrew Tuline. - if (!strip.isMatrix) return mode_static(); // not a 2D set-up + if (!strip.isMatrix) return mode_oops(); // not a 2D set-up const uint16_t cols = SEGMENT.virtualWidth(); const uint16_t rows = SEGMENT.virtualHeight(); - if (!SEGENV.allocateData(sizeof(julia))) return mode_static(); + if (!SEGENV.allocateData(sizeof(julia))) return mode_oops(); Julia* julias = reinterpret_cast(SEGENV.data); float reAl; @@ -5927,7 +5954,7 @@ static const char _data_FX_MODE_2DJULIA[] PROGMEM = "Julia@,Max iterations per p // 2D Lissajous // ////////////////////////////// uint16_t mode_2DLissajous(void) { // By: Andrew Tuline - if (!strip.isMatrix) return mode_static(); // not a 2D set-up + if (!strip.isMatrix) return mode_oops(); // not a 2D set-up const uint16_t cols = SEGMENT.virtualWidth(); const uint16_t rows = SEGMENT.virtualHeight(); @@ -5969,7 +5996,7 @@ static const char _data_FX_MODE_2DLISSAJOUS[] PROGMEM = "Lissajous ☾@X frequen // 2D Matrix // /////////////////////// uint16_t mode_2Dmatrix(void) { // Matrix2D. By Jeremy Williams. Adapted by Andrew Tuline & improved by merkisoft and ewowi, and softhack007. - if (!strip.isMatrix) return mode_static(); // not a 2D set-up + if (!strip.isMatrix) return mode_oops(); // not a 2D set-up const uint16_t cols = SEGMENT.virtualWidth(); const uint16_t rows = SEGMENT.virtualHeight(); @@ -6045,7 +6072,7 @@ static const char _data_FX_MODE_2DMATRIX[] PROGMEM = "Matrix@!,Spawning rate,Tra // 2D Metaballs // ///////////////////////// uint16_t mode_2Dmetaballs(void) { // Metaballs by Stefan Petrick. Cannot have one of the dimensions be 2 or less. Adapted by Andrew Tuline. - if (!strip.isMatrix) return mode_static(); // not a 2D set-up + if (!strip.isMatrix) return mode_oops(); // not a 2D set-up const uint16_t cols = SEGMENT.virtualWidth(); const uint16_t rows = SEGMENT.virtualHeight(); @@ -6104,7 +6131,7 @@ static const char _data_FX_MODE_2DMETABALLS[] PROGMEM = "Metaballs@!;;!;2"; // 2D Noise // ////////////////////// uint16_t mode_2Dnoise(void) { // By Andrew Tuline - if (!strip.isMatrix) return mode_static(); // not a 2D set-up + if (!strip.isMatrix) return mode_oops(); // not a 2D set-up const uint16_t cols = SEGMENT.virtualWidth(); const uint16_t rows = SEGMENT.virtualHeight(); @@ -6127,7 +6154,7 @@ static const char _data_FX_MODE_2DNOISE[] PROGMEM = "Noise2D@!,Scale;;!;2"; // 2D Plasma Ball // ////////////////////////////// uint16_t mode_2DPlasmaball(void) { // By: Stepko https://editor.soulmatelights.com/gallery/659-plasm-ball , Modified by: Andrew Tuline - if (!strip.isMatrix) return mode_static(); // not a 2D set-up + if (!strip.isMatrix) return mode_oops(); // not a 2D set-up const uint16_t cols = SEGMENT.virtualWidth(); const uint16_t rows = SEGMENT.virtualHeight(); @@ -6173,7 +6200,7 @@ static const char _data_FX_MODE_2DPLASMABALL[] PROGMEM = "Plasma Ball@Speed,,Fad // return (out_max - out_min) * (x - in_min) / (in_max - in_min) + out_min; //} uint16_t mode_2DPolarLights(void) { // By: Kostyantyn Matviyevskyy https://editor.soulmatelights.com/gallery/762-polar-lights , Modified by: Andrew Tuline - if (!strip.isMatrix) return mode_static(); // not a 2D set-up + if (!strip.isMatrix) return mode_oops(); // not a 2D set-up const uint16_t cols = SEGMENT.virtualWidth(); const uint16_t rows = SEGMENT.virtualHeight(); @@ -6249,7 +6276,7 @@ static const char _data_FX_MODE_2DPOLARLIGHTS[] PROGMEM = "Polar Lights@!,Scale, // 2D Pulser // ///////////////////////// uint16_t mode_2DPulser(void) { // By: ldirko https://editor.soulmatelights.com/gallery/878-pulse-test , modifed by: Andrew Tuline - if (!strip.isMatrix) return mode_static(); // not a 2D set-up + if (!strip.isMatrix) return mode_oops(); // not a 2D set-up const uint16_t cols = SEGMENT.virtualWidth(); const uint16_t rows = SEGMENT.virtualHeight(); @@ -6277,7 +6304,7 @@ static const char _data_FX_MODE_2DPULSER[] PROGMEM = "Pulser@!,Blur;;!;2"; // 2D Sindots // ///////////////////////// uint16_t mode_2DSindots(void) { // By: ldirko https://editor.soulmatelights.com/gallery/597-sin-dots , modified by: Andrew Tuline - if (!strip.isMatrix) return mode_static(); // not a 2D set-up + if (!strip.isMatrix) return mode_oops(); // not a 2D set-up const uint16_t cols = SEGMENT.virtualWidth(); const uint16_t rows = SEGMENT.virtualHeight(); @@ -6309,7 +6336,7 @@ static const char _data_FX_MODE_2DSINDOTS[] PROGMEM = "Sindots@!,Dot distance,Fa // custom3 affects the blur amount. uint16_t mode_2Dsquaredswirl(void) { // By: Mark Kriegsman. https://gist.github.com/kriegsman/368b316c55221134b160 // Modifed by: Andrew Tuline - if (!strip.isMatrix) return mode_static(); // not a 2D set-up + if (!strip.isMatrix) return mode_oops(); // not a 2D set-up const uint16_t cols = SEGMENT.virtualWidth(); const uint16_t rows = SEGMENT.virtualHeight(); @@ -6349,14 +6376,14 @@ static const char _data_FX_MODE_2DSQUAREDSWIRL[] PROGMEM = "Squared Swirl@,,,,Bl // 2D Sun Radiation // ////////////////////////////// uint16_t mode_2DSunradiation(void) { // By: ldirko https://editor.soulmatelights.com/gallery/599-sun-radiation , modified by: Andrew Tuline - if (!strip.isMatrix) return mode_static(); // not a 2D set-up + if (!strip.isMatrix) return mode_oops(); // not a 2D set-up const uint16_t cols = SEGMENT.virtualWidth(); const uint16_t rows = SEGMENT.virtualHeight(); const int minSize = min(cols, rows); // WLEDMM const int magnify = (minSize <= 32) ? 8 : 46; // WLEDMM - if (!SEGENV.allocateData(sizeof(byte)*(cols+2)*(rows+2))) return mode_static(); //allocation failed + if (!SEGENV.allocateData(sizeof(byte)*(cols+2)*(rows+2))) return mode_oops(); //allocation failed byte *bump = reinterpret_cast(SEGENV.data); if (SEGENV.call == 0) { @@ -6402,7 +6429,7 @@ static const char _data_FX_MODE_2DSUNRADIATION[] PROGMEM = "Sun Radiation@Varian // 2D Tartan // ///////////////////////// uint16_t mode_2Dtartan(void) { // By: Elliott Kember https://editor.soulmatelights.com/gallery/3-tartan , Modified by: Andrew Tuline - if (!strip.isMatrix) return mode_static(); // not a 2D set-up + if (!strip.isMatrix) return mode_oops(); // not a 2D set-up const uint16_t cols = SEGMENT.virtualWidth(); const uint16_t rows = SEGMENT.virtualHeight(); @@ -6442,7 +6469,7 @@ static const char _data_FX_MODE_2DTARTAN[] PROGMEM = "Tartan@X scale,Y scale,,,S // 2D spaceships // ///////////////////////// uint16_t mode_2Dspaceships(void) { //// Space ships by stepko (c)05.02.21 [https://editor.soulmatelights.com/gallery/639-space-ships], adapted by Blaz Kristan (AKA blazoncek) - if (!strip.isMatrix) return mode_static(); // not a 2D set-up + if (!strip.isMatrix) return mode_oops(); // not a 2D set-up const uint16_t cols = SEGMENT.virtualWidth(); const uint16_t rows = SEGMENT.virtualHeight(); @@ -6490,7 +6517,7 @@ static const char _data_FX_MODE_2DSPACESHIPS[] PROGMEM = "Spaceships@!,Blur;;!;2 //// Crazy bees by stepko (c)12.02.21 [https://editor.soulmatelights.com/gallery/651-crazy-bees], adapted by Blaz Kristan (AKA blazoncek) constexpr uint_fast16_t MAX_BEES = 5; uint16_t mode_2Dcrazybees(void) { - if (!strip.isMatrix) return mode_static(); // not a 2D set-up + if (!strip.isMatrix) return mode_oops(); // not a 2D set-up const uint_fast16_t cols = SEGMENT.virtualWidth(); const uint_fast16_t rows = SEGMENT.virtualHeight(); @@ -6513,7 +6540,7 @@ uint16_t mode_2Dcrazybees(void) { }; } bee_t; - if (!SEGENV.allocateData(sizeof(bee_t)*MAX_BEES)) return mode_static(); //allocation failed + if (!SEGENV.allocateData(sizeof(bee_t)*MAX_BEES)) return mode_oops(); //allocation failed bee_t *bee = reinterpret_cast(SEGENV.data); if (SEGENV.call == 0) { @@ -6565,7 +6592,7 @@ static const char _data_FX_MODE_2DCRAZYBEES[] PROGMEM = "Crazy Bees@!,Blur;;;2"; //// Ghost Rider by stepko (c)2021 [https://editor.soulmatelights.com/gallery/716-ghost-rider], adapted by Blaz Kristan (AKA blazoncek) #define LIGHTERS_AM 64 // max lighters (adequate for 32x32 matrix) uint16_t mode_2Dghostrider(void) { - if (!strip.isMatrix) return mode_static(); // not a 2D set-up + if (!strip.isMatrix) return mode_oops(); // not a 2D set-up const uint16_t cols = SEGMENT.virtualWidth(); const uint16_t rows = SEGMENT.virtualHeight(); @@ -6583,7 +6610,7 @@ uint16_t mode_2Dghostrider(void) { int8_t Vspeed; } lighter_t; - if (!SEGENV.allocateData(sizeof(lighter_t))) return mode_static(); //allocation failed + if (!SEGENV.allocateData(sizeof(lighter_t))) return mode_oops(); //allocation failed lighter_t *lighter = reinterpret_cast(SEGENV.data); const size_t maxLighters = min(cols + rows, LIGHTERS_AM); @@ -6655,7 +6682,7 @@ static const char _data_FX_MODE_2DGHOSTRIDER[] PROGMEM = "Ghost Rider@Fade rate, //// Floating Blobs by stepko (c)2021 [https://editor.soulmatelights.com/gallery/573-blobs], adapted by Blaz Kristan (AKA blazoncek) #define MAX_BLOBS 8 uint16_t mode_2Dfloatingblobs(void) { - if (!strip.isMatrix) return mode_static(); // not a 2D set-up + if (!strip.isMatrix) return mode_oops(); // not a 2D set-up const uint16_t cols = SEGMENT.virtualWidth(); const uint16_t rows = SEGMENT.virtualHeight(); @@ -6670,7 +6697,7 @@ uint16_t mode_2Dfloatingblobs(void) { uint8_t Amount = (SEGMENT.intensity>>5) + 1; // NOTE: be sure to update MAX_BLOBS if you change this - if (!SEGENV.allocateData(sizeof(blob_t))) return mode_static(); //allocation failed + if (!SEGENV.allocateData(sizeof(blob_t))) return mode_oops(); //allocation failed blob_t *blob = reinterpret_cast(SEGENV.data); // WLEDMM fix SEGENV.step in case that timebase jumps @@ -6761,7 +6788,7 @@ static const char _data_FX_MODE_2DBLOBS[] PROGMEM = "Blobs@!,# blobs,Blur;!;!;2; // 2D Scrolling text // //////////////////////////// uint16_t mode_2Dscrollingtext(void) { - if (!strip.isMatrix) return mode_static(); // not a 2D set-up + if (!strip.isMatrix) return mode_oops(); // not a 2D set-up const uint16_t cols = SEGMENT.virtualWidth(); const uint16_t rows = SEGMENT.virtualHeight(); @@ -6867,7 +6894,7 @@ static const char _data_FX_MODE_2DSCROLLTEXT[] PROGMEM = "Scrolling Text@!,Y Off //////////////////////////// //// Drift Rose by stepko (c)2021 [https://editor.soulmatelights.com/gallery/1369-drift-rose-pattern], adapted by Blaz Kristan (AKA blazoncek) uint16_t mode_2Ddriftrose(void) { - if (!strip.isMatrix) return mode_static(); // not a 2D set-up + if (!strip.isMatrix) return mode_oops(); // not a 2D set-up const uint16_t cols = SEGMENT.virtualWidth(); const uint16_t rows = SEGMENT.virtualHeight(); @@ -6969,7 +6996,7 @@ uint16_t mode_ripplepeak(void) { // * Ripple peak. By Andrew Tuli uint16_t maxRipples = 16; uint16_t dataSize = sizeof(Ripple) * maxRipples; - if (!SEGENV.allocateData(dataSize)) return mode_static(); //allocation failed + if (!SEGENV.allocateData(dataSize)) return mode_oops(); //allocation failed Ripple* ripples = reinterpret_cast(SEGENV.data); um_data_t *um_data = getAudioData(); @@ -7048,7 +7075,7 @@ static const char _data_FX_MODE_RIPPLEPEAK[] PROGMEM = "Ripple Peak@Fade rate,Ma ///////////////////////// // By: Mark Kriegsman https://gist.github.com/kriegsman/5adca44e14ad025e6d3b , modified by Andrew Tuline uint16_t mode_2DSwirl(void) { - if (!strip.isMatrix) return mode_static(); // not a 2D set-up + if (!strip.isMatrix) return mode_oops(); // not a 2D set-up const uint16_t cols = SEGMENT.virtualWidth(); const uint16_t rows = SEGMENT.virtualHeight(); @@ -7091,7 +7118,7 @@ static const char _data_FX_MODE_2DSWIRL[] PROGMEM = "Swirl@!,Sensitivity,Blur;,B ///////////////////////// // By: Stepko, https://editor.soulmatelights.com/gallery/652-wave , modified by Andrew Tuline uint16_t mode_2DWaverly(void) { - if (!strip.isMatrix) return mode_static(); // not a 2D set-up + if (!strip.isMatrix) return mode_oops(); // not a 2D set-up const uint16_t cols = SEGMENT.virtualWidth(); const uint16_t rows = SEGMENT.virtualHeight(); @@ -7148,7 +7175,7 @@ typedef struct Gravity { uint16_t mode_gravcenter(void) { // Gravcenter. By Andrew Tuline. constexpr uint16_t dataSize = sizeof(gravity); - if (!SEGENV.allocateData(dataSize)) return mode_static(); //allocation failed + if (!SEGENV.allocateData(dataSize)) return mode_oops(); //allocation failed Gravity* gravcen = reinterpret_cast(SEGENV.data); if (SEGENV.call == 0) { SEGMENT.setUpLeds(); @@ -7196,7 +7223,7 @@ static const char _data_FX_MODE_GRAVCENTER[] PROGMEM = "Gravcenter@Rate of fall, uint16_t mode_gravcentric(void) { // Gravcentric. By Andrew Tuline. uint16_t dataSize = sizeof(gravity); - if (!SEGENV.allocateData(dataSize)) return mode_static(); //allocation failed + if (!SEGENV.allocateData(dataSize)) return mode_oops(); //allocation failed Gravity* gravcen = reinterpret_cast(SEGENV.data); if (SEGENV.call == 0) { SEGMENT.setUpLeds(); @@ -7247,7 +7274,7 @@ static const char _data_FX_MODE_GRAVCENTRIC[] PROGMEM = "Gravcentric@Rate of fal uint16_t mode_gravimeter(void) { // Gravmeter. By Andrew Tuline. uint16_t dataSize = sizeof(gravity); - if (!SEGENV.allocateData(dataSize)) return mode_static(); //allocation failed + if (!SEGENV.allocateData(dataSize)) return mode_oops(); //allocation failed Gravity* gravcen = reinterpret_cast(SEGENV.data); um_data_t *um_data = getAudioData(); @@ -7530,7 +7557,7 @@ typedef struct Plasphase { uint16_t mode_plasmoid(void) { // Plasmoid. By Andrew Tuline. // even with 1D effect we have to take logic for 2D segments for allocation as fill_solid() fills whole segment - if (!SEGENV.allocateData(sizeof(plasphase))) return mode_static(); //allocation failed + if (!SEGENV.allocateData(sizeof(plasphase))) return mode_oops(); //allocation failed Plasphase* plasmoip = reinterpret_cast(SEGENV.data); um_data_t *um_data = getAudioData(); @@ -7642,7 +7669,7 @@ static const char _data_FX_MODE_PUDDLES[] PROGMEM = "Puddles@Fade rate,Puddle si ////////////////////// uint16_t mode_pixels(void) { // Pixels. By Andrew Tuline. - if (!SEGENV.allocateData(32*sizeof(uint8_t))) return mode_static(); //allocation failed + if (!SEGENV.allocateData(32*sizeof(uint8_t))) return mode_oops(); //allocation failed uint8_t *myVals = reinterpret_cast(SEGENV.data); // Used to store a pile of samples because WLED frame rate and WLED sample rate are not synchronized. Frame rate is too low. um_data_t *um_data = getAudioData(); @@ -8046,7 +8073,7 @@ static const char _data_FX_MODE_FREQWAVE[] PROGMEM = "Freqwave@Speed,Sound effec uint16_t mode_gravfreq(void) { // Gravfreq. By Andrew Tuline. uint16_t dataSize = sizeof(gravity); - if (!SEGENV.allocateData(dataSize)) return mode_static(); //allocation failed + if (!SEGENV.allocateData(dataSize)) return mode_oops(); //allocation failed Gravity* gravcen = reinterpret_cast(SEGENV.data); um_data_t *um_data = getAudioData(); @@ -8240,7 +8267,7 @@ static void setFlatPixelXY(bool flatMode, int x, int y, uint32_t color, unsigned } uint16_t mode_2DGEQ(void) { // By Will Tatam. Code reduction by Ewoud Wijma. Flat Mode added by softhack007 - //if (!strip.isMatrix) return mode_static(); // not a 2D set-up, not a problem + //if (!strip.isMatrix) return mode_oops(); // not a 2D set-up, not a problem bool flatMode = !SEGMENT.is2D() || (SEGMENT.width() < 3) || (SEGMENT.height() < 3); // also use flat mode when less than 3 colums or rows const int NUM_BANDS = map2(SEGMENT.custom1, 0, 255, 1, 16); @@ -8249,9 +8276,9 @@ uint16_t mode_2DGEQ(void) { // By Will Tatam. Code reduction by Ewoud Wijma. Fla const uint16_t rows = flatMode ? vLength / cols : SEGMENT.virtualHeight(); const unsigned offset = flatMode ? max(0, (vLength - rows*cols +1) / 2) : 0; // flatmode: always center effect - if ((cols <=1) || (rows <=1)) return mode_static(); // too small + if ((cols <=1) || (rows <=1)) return mode_oops(); // too small - if (!SEGENV.allocateData(cols*sizeof(uint16_t))) return mode_static(); //allocation failed + if (!SEGENV.allocateData(cols*sizeof(uint16_t))) return mode_oops(); //allocation failed uint16_t *previousBarHeight = reinterpret_cast(SEGENV.data); //array of previous bar heights per frequency band um_data_t *um_data = getAudioData(); @@ -8349,7 +8376,7 @@ static const char _data_FX_MODE_2DGEQ[] PROGMEM = "GEQ ☾@Fade speed,Ripple dec // ** 2D Funky plank // ///////////////////////// uint16_t mode_2DFunkyPlank(void) { // Written by ??? Adapted by Will Tatam. - if (!strip.isMatrix) return mode_static(); // not a 2D set-up + if (!strip.isMatrix) return mode_oops(); // not a 2D set-up const uint16_t cols = SEGMENT.virtualWidth(); const uint16_t rows = SEGMENT.virtualHeight(); @@ -8439,8 +8466,10 @@ static uint8_t akemi[] PROGMEM = { }; uint16_t mode_2DAkemi(void) { - if (!strip.isMatrix) return mode_static(); // not a 2D set-up - + return mode_2DAkemi_core(true); +} +static uint16_t mode_2DAkemi_core(bool withSound) { + if ((withSound == true) && (!strip.isMatrix)) return mode_oops(); // not a 2D set-up const uint16_t cols = SEGMENT.virtualWidth(); const uint16_t rows = SEGMENT.virtualHeight(); @@ -8452,7 +8481,7 @@ uint16_t mode_2DAkemi(void) { const float lightFactor = 0.15f; const float normalFactor = 0.4f; - um_data_t *um_data = getAudioData(); + um_data_t *um_data = withSound ? getAudioData() : simulateSound(SEGMENT.soundSim); uint8_t fftResult[NUM_GEQ_CHANNELS] = {0}; if (um_data->u_data != nullptr) memcpy(fftResult, um_data->u_data[2], sizeof(fftResult)); // WLEDMM buffer curent values float base = fftResult[0]/255.0f; @@ -8509,7 +8538,7 @@ static const char _data_FX_MODE_2DAKEMI[] PROGMEM = "Akemi@Color speed,Dance;Hea // https://editor.soulmatelights.com/gallery/1089-distorsion-waves // adapted for WLED by @blazoncek uint16_t mode_2Ddistortionwaves() { - if (!strip.isMatrix) return mode_static(); // not a 2D set-up + if (!strip.isMatrix) return mode_oops(); // not a 2D set-up const uint16_t cols = SEGMENT.virtualWidth(); const uint16_t rows = SEGMENT.virtualHeight(); @@ -8564,13 +8593,13 @@ static const char _data_FX_MODE_2DDISTORTIONWAVES[] PROGMEM = "Distortion Waves@ //Idea from https://www.youtube.com/watch?v=DiHBgITrZck&ab_channel=StefanPetrick // adapted for WLED by @blazoncek uint16_t mode_2Dsoap() { - if (!strip.isMatrix) return mode_static(); // not a 2D set-up + if (!strip.isMatrix) return mode_oops(); // not a 2D set-up const uint16_t cols = SEGMENT.virtualWidth(); const uint16_t rows = SEGMENT.virtualHeight(); const size_t dataSize = SEGMENT.width() * SEGMENT.height() * sizeof(uint8_t); // prevent reallocation if mirrored or grouped - if (!SEGENV.allocateData(dataSize + sizeof(uint32_t)*3)) return mode_static(); //allocation failed + if (!SEGENV.allocateData(dataSize + sizeof(uint32_t)*3)) return mode_oops(); //allocation failed uint8_t *noise3d = reinterpret_cast(SEGENV.data); uint32_t *noise32_x = reinterpret_cast(SEGENV.data + dataSize); @@ -8685,7 +8714,7 @@ static const char _data_FX_MODE_2DSOAP[] PROGMEM = "Soap@!,Smoothness;;!;2"; // adapted for WLED by @blazoncek // RadialWave mode added by @softhack007, based on https://editor.soulmatelights.com/gallery/1090-radialwave uint16_t mode_2Doctopus() { - if (!strip.isMatrix) return mode_static(); // not a 2D set-up + if (!strip.isMatrix) return mode_oops(); // not a 2D set-up const uint16_t cols = SEGMENT.virtualWidth(); const uint16_t rows = SEGMENT.virtualHeight(); @@ -8697,7 +8726,7 @@ uint16_t mode_2Doctopus() { } map_t; const size_t dataSize = SEGMENT.width() * SEGMENT.height() * sizeof(map_t); // prevent reallocation if mirrored or grouped - if (!SEGENV.allocateData(dataSize + 2)) return mode_static(); //allocation failed + if (!SEGENV.allocateData(dataSize + 2)) return mode_oops(); //allocation failed map_t *rMap = reinterpret_cast(SEGENV.data); uint8_t *offsX = reinterpret_cast(SEGENV.data + dataSize); @@ -8770,7 +8799,7 @@ static const char _data_FX_MODE_2DOCTOPUS[] PROGMEM = "Octopus@!,,Offset X,Offse //@Stepko (https://editor.soulmatelights.com/gallery/1704-wavingcells) // adapted for WLED by @blazoncek uint16_t mode_2Dwavingcell() { - if (!strip.isMatrix) return mode_static(); // not a 2D set-up + if (!strip.isMatrix) return mode_oops(); // not a 2D set-up const uint16_t cols = SEGMENT.virtualWidth(); const uint16_t rows = SEGMENT.virtualHeight(); @@ -8803,10 +8832,10 @@ uint16_t mode_GEQLASER(void) { // Author: @TroyHacks // @license GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 - if (!strip.isMatrix) return mode_static(); // not a 2D set-up + if (!strip.isMatrix) return mode_oops(); // not a 2D set-up const int cols = SEGMENT.virtualWidth(); const int rows = SEGMENT.virtualHeight(); - if ((cols < 3) || (rows < 3)) return mode_static(); // too small + if ((cols < 3) || (rows < 3)) return mode_oops(); // too small int16_t *projector = reinterpret_cast(&(SEGENV.aux0)); // *projector is an alias for aux0 (uint16_t) int16_t *projector_dir = reinterpret_cast(&(SEGENV.aux1)); // *projector_dir is an alias for aux1 (uint16_t) @@ -8959,12 +8988,12 @@ uint16_t mode_2DPaintbrush() { // Author: @TroyHacks // @license GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 - if (!strip.isMatrix) return mode_static(); // not a 2D set-up + if (!strip.isMatrix) return mode_oops(); // not a 2D set-up const uint16_t cols = SEGMENT.virtualWidth(); const uint16_t rows = SEGMENT.virtualHeight(); - if (!SEGENV.allocateData(4)) return mode_static(); //allocation failed + if (!SEGENV.allocateData(4)) return mode_oops(); //allocation failed if (SEGENV.call == 0) { SEGMENT.setUpLeds(); @@ -9022,13 +9051,13 @@ static const char _data_FX_MODE_2DPAINTBRUSH[] PROGMEM = "Paintbrush ☾@Oscilla #define NUMBEROFSOURCES 8 uint16_t mode_particlevortex(void) { if (SEGLEN == 1) - return mode_static(); + return mode_oops(); ParticleSystem2D *PartSys = nullptr; uint32_t i, j; if (SEGMENT.call == 0) { // initialization if (!initParticleSystem2D(PartSys, NUMBEROFSOURCES)) - return mode_static(); // allocation failed + return mode_oops(); // allocation failed #ifdef ESP8266 PartSys->setMotionBlur(180); #else @@ -9046,7 +9075,7 @@ uint16_t mode_particlevortex(void) { PartSys = reinterpret_cast(SEGENV.data); // if not first call, just set the pointer to the PS if (PartSys == nullptr) - return mode_static(); // something went wrong, no data! + return mode_oops(); // something went wrong, no data! PartSys->updateSystem(); // update system properties (dimensions and data pointers) uint32_t spraycount = min(PartSys->numSources, (uint32_t)(1 + (SEGMENT.custom1 >> 5))); // number of sprays to display, 1-8 @@ -9141,7 +9170,7 @@ uint16_t mode_particlefireworks(void) { if (SEGMENT.call == 0) { // initialization if (!initParticleSystem2D(PartSys, NUMBEROFSOURCES)) - return mode_static(); // allocation failed + return mode_oops(); // allocation failed PartSys->setKillOutOfBounds(true); // out of bounds particles dont return (except on top, taken care of by gravity setting) PartSys->setWallHardness(120); // ground bounce is fixed @@ -9155,7 +9184,7 @@ uint16_t mode_particlefireworks(void) { PartSys = reinterpret_cast(SEGENV.data); // if not first call, just set the pointer to the PS if (PartSys == nullptr) - return mode_static(); // something went wrong, no data! + return mode_oops(); // something went wrong, no data! PartSys->updateSystem(); // update system properties (dimensions and data pointers) numRockets = map(SEGMENT.speed, 0 , 255, 4, min(PartSys->numSources, (uint32_t)NUMBEROFSOURCES)); @@ -9288,7 +9317,7 @@ uint16_t mode_particlevolcano(void) { if (SEGMENT.call == 0) { // initialization if (!initParticleSystem2D(PartSys, NUMBEROFSOURCES)) // init, no additional data needed - return mode_static(); // allocation failed or not 2D + return mode_oops(); // allocation failed or not 2D PartSys->setBounceY(true); PartSys->setGravity(); // enable with default gforce @@ -9309,7 +9338,7 @@ uint16_t mode_particlevolcano(void) { PartSys = reinterpret_cast(SEGENV.data); // if not first call, just set the pointer to the PS if (PartSys == nullptr) - return mode_static(); // something went wrong, no data! + return mode_oops(); // something went wrong, no data! numSprays = min(PartSys->numSources, (uint32_t)NUMBEROFSOURCES); // number of volcanoes @@ -9358,14 +9387,14 @@ uint16_t mode_particlefire(void) { if (SEGMENT.call == 0) { // initialization if (!initParticleSystem2D(PartSys, SEGMENT.virtualWidth(), 4)) //maximum number of source (PS may limit based on segment size); need 4 additional bytes for time keeping (uint32_t lastcall) - return mode_static(); // allocation failed or not 2D + return mode_oops(); // allocation failed or not 2D SEGENV.aux0 = hw_random16(); // aux0 is wind position (index) in the perlin noise } else PartSys = reinterpret_cast(SEGENV.data); // if not first call, just set the pointer to the PS if (PartSys == nullptr) - return mode_static(); // something went wrong, no data! + return mode_oops(); // something went wrong, no data! PartSys->updateSystem(); // update system properties (dimensions and data pointers) PartSys->setWrapX(SEGMENT.check2); @@ -9449,7 +9478,7 @@ uint16_t mode_particlepit(void) { if (SEGMENT.call == 0) { // initialization if (!initParticleSystem2D(PartSys, 0, 0, true, false)) // init - return mode_static(); // allocation failed or not 2D + return mode_oops(); // allocation failed or not 2D PartSys->setKillOutOfBounds(true); PartSys->setGravity(); // enable with default gravity PartSys->setUsedParticles(170); // use 75% of available particles @@ -9457,7 +9486,7 @@ uint16_t mode_particlepit(void) { else PartSys = reinterpret_cast(SEGENV.data); // if not first call, just set the pointer to the PS if (PartSys == nullptr) - return mode_static(); // something went wrong, no data! + return mode_oops(); // something went wrong, no data! PartSys->updateSystem(); // update system properties (dimensions and data pointers) @@ -9521,7 +9550,7 @@ uint16_t mode_particlewaterfall(void) { if (SEGMENT.call == 0) { // initialization if (!initParticleSystem2D(PartSys, 12)) // init, request 12 sources, no additional data needed - return mode_static(); // allocation failed or not 2D + return mode_oops(); // allocation failed or not 2D PartSys->setGravity(); // enable with default gforce PartSys->setKillOutOfBounds(true); // out of bounds particles dont return (except on top, taken care of by gravity setting) @@ -9542,7 +9571,7 @@ uint16_t mode_particlewaterfall(void) { else PartSys = reinterpret_cast(SEGENV.data); // if not first call, just set the pointer to the PS if (PartSys == nullptr) - return mode_static(); // something went wrong, no data! + return mode_oops(); // something went wrong, no data! // Particle System settings PartSys->updateSystem(); // update system properties (dimensions and data pointers) @@ -9592,7 +9621,7 @@ uint16_t mode_particlebox(void) { if (SEGMENT.call == 0) { // initialization if (!initParticleSystem2D(PartSys, 1)) // init - return mode_static(); // allocation failed or not 2D + return mode_oops(); // allocation failed or not 2D PartSys->setBounceX(true); PartSys->setBounceY(true); SEGENV.aux0 = hw_random16(); // position in perlin noise @@ -9601,7 +9630,7 @@ uint16_t mode_particlebox(void) { PartSys = reinterpret_cast(SEGENV.data); // if not first call, just set the pointer to the PS if (PartSys == nullptr) - return mode_static(); // something went wrong, no data! + return mode_oops(); // something went wrong, no data! PartSys->updateSystem(); // update system properties (dimensions and data pointers) PartSys->setParticleSize(SEGMENT.custom3<<3); @@ -9673,7 +9702,7 @@ uint16_t mode_particleperlin(void) { if (SEGMENT.call == 0) { // initialization if (!initParticleSystem2D(PartSys, 1, 0, true)) // init with 1 source and advanced properties - return mode_static(); // allocation failed or not 2D + return mode_oops(); // allocation failed or not 2D PartSys->setKillOutOfBounds(true); // should never happen, but lets make sure there are no stray particles PartSys->setMotionBlur(230); // anable motion blur @@ -9684,7 +9713,7 @@ uint16_t mode_particleperlin(void) { PartSys = reinterpret_cast(SEGENV.data); // if not first call, just set the pointer to the PS if (PartSys == nullptr) - return mode_static(); // something went wrong, no data! + return mode_oops(); // something went wrong, no data! PartSys->updateSystem(); // update system properties (dimensions and data pointers) PartSys->setWrapX(SEGMENT.check1); @@ -9738,7 +9767,7 @@ uint16_t mode_particleimpact(void) { if (SEGMENT.call == 0) { // initialization if (!initParticleSystem2D(PartSys, NUMBEROFSOURCES)) // init, no additional data needed - return mode_static(); // allocation failed or not 2D + return mode_oops(); // allocation failed or not 2D PartSys->setKillOutOfBounds(true); PartSys->setGravity(); // enable default gravity PartSys->setBounceY(true); // always use ground bounce @@ -9753,7 +9782,7 @@ uint16_t mode_particleimpact(void) { PartSys = reinterpret_cast(SEGENV.data); // if not first call, just set the pointer to the PS if (PartSys == nullptr) - return mode_static(); // something went wrong, no data! + return mode_oops(); // something went wrong, no data! // Particle System settings PartSys->updateSystem(); // update system properties (dimensions and data pointers) @@ -9848,7 +9877,7 @@ uint16_t mode_particleattractor(void) { PSparticle *attractor; // particle pointer to the attractor if (SEGMENT.call == 0) { // initialization if (!initParticleSystem2D(PartSys, 1, sizeof(PSparticle), true)) // init using 1 source and advanced particle settings - return mode_static(); // allocation failed or not 2D + return mode_oops(); // allocation failed or not 2D PartSys->sources[0].source.hue = hw_random16(); PartSys->sources[0].source.vx = -7; // will collied with wall and get random bounce direction PartSys->sources[0].sourceFlags.collide = true; // seeded particles will collide @@ -9869,7 +9898,7 @@ uint16_t mode_particleattractor(void) { } if (PartSys == nullptr) - return mode_static(); // something went wrong, no data! + return mode_oops(); // something went wrong, no data! // Particle System settings PartSys->updateSystem(); // update system properties (dimensions and data pointers) @@ -9941,7 +9970,7 @@ uint16_t mode_particlespray(void) { if (SEGMENT.call == 0) { // initialization if (!initParticleSystem2D(PartSys, 1)) // init, no additional data needed - return mode_static(); // allocation failed or not 2D + return mode_oops(); // allocation failed or not 2D PartSys->setKillOutOfBounds(true); // out of bounds particles dont return (except on top, taken care of by gravity setting) PartSys->setBounceY(true); PartSys->setMotionBlur(200); // anable motion blur @@ -9954,7 +9983,7 @@ uint16_t mode_particlespray(void) { PartSys = reinterpret_cast(SEGENV.data); // if not first call, just set the pointer to the PS if (PartSys == nullptr) - return mode_static(); // something went wrong, no data! + return mode_oops(); // something went wrong, no data! // Particle System settings PartSys->updateSystem(); // update system properties (dimensions and data pointers) @@ -10026,14 +10055,14 @@ uint16_t mode_particleGEQ(void) { if (SEGMENT.call == 0) { // initialization if (!initParticleSystem2D(PartSys, 1)) - return mode_static(); // allocation failed or not 2D + return mode_oops(); // allocation failed or not 2D PartSys->setKillOutOfBounds(true); PartSys->setUsedParticles(170); // use 2/3 of available particles } else PartSys = reinterpret_cast(SEGENV.data); // if not first call, just set the pointer to the PS if (PartSys == nullptr) - return mode_static(); // something went wrong, no data! + return mode_oops(); // something went wrong, no data! uint32_t i; // set particle system properties @@ -10103,7 +10132,7 @@ uint16_t mode_particlecenterGEQ(void) { if (SEGMENT.call == 0) { // initialization if (!initParticleSystem2D(PartSys, NUMBEROFSOURCES)) // init, request 16 sources - return mode_static(); // allocation failed or not 2D + return mode_oops(); // allocation failed or not 2D numSprays = min(PartSys->numSources, (uint32_t)NUMBEROFSOURCES); for (i = 0; i < numSprays; i++) { @@ -10119,7 +10148,7 @@ uint16_t mode_particlecenterGEQ(void) { PartSys = reinterpret_cast(SEGENV.data); // if not first call, just set the pointer to the PS if (PartSys == nullptr) - return mode_static(); // something went wrong, no data! + return mode_oops(); // something went wrong, no data! PartSys->updateSystem(); // update system properties (dimensions and data pointers) numSprays = min(PartSys->numSources, (uint32_t)NUMBEROFSOURCES); @@ -10172,7 +10201,7 @@ uint16_t mode_particleghostrider(void) { if (SEGMENT.call == 0) { // initialization if (!initParticleSystem2D(PartSys, 1)) // init, no additional data needed - return mode_static(); // allocation failed or not 2D + return mode_oops(); // allocation failed or not 2D PartSys->setKillOutOfBounds(true); // out of bounds particles dont return (except on top, taken care of by gravity setting) PartSys->sources[0].maxLife = 260; // lifetime in frames PartSys->sources[0].minLife = 250; @@ -10185,7 +10214,7 @@ uint16_t mode_particleghostrider(void) { } if (PartSys == nullptr) - return mode_static(); // something went wrong, no data! + return mode_oops(); // something went wrong, no data! if (SEGMENT.intensity > 0) { // spiraling if (SEGENV.aux1) { @@ -10251,7 +10280,7 @@ uint16_t mode_particleblobs(void) { if (SEGMENT.call == 0) { if (!initParticleSystem2D(PartSys, 0, 0, true, true)) //init, no additional bytes, advanced size & size control - return mode_static(); // allocation failed or not 2D + return mode_oops(); // allocation failed or not 2D PartSys->setBounceX(true); PartSys->setBounceY(true); PartSys->setWallHardness(255); @@ -10262,7 +10291,7 @@ uint16_t mode_particleblobs(void) { PartSys = reinterpret_cast(SEGENV.data); // if not first call, just set the pointer to the PS if (PartSys == nullptr) - return mode_static(); // something went wrong, no data! + return mode_oops(); // something went wrong, no data! PartSys->updateSystem(); // update system properties (dimensions and data pointers) PartSys->setUsedParticles(map(SEGMENT.intensity, 0, 255, 25, 128)); // minimum 10%, maximum 50% of available particles (note: PS ensures at least 1) @@ -10334,7 +10363,7 @@ uint16_t mode_particleDrip(void) { //uint8_t numSprays; if (SEGMENT.call == 0) { // initialization if (!initParticleSystem1D(PartSys, 4)) // init - return mode_static(); // allocation failed or single pixel + return mode_oops(); // allocation failed or single pixel PartSys->setKillOutOfBounds(true); // out of bounds particles dont return (except on top, taken care of by gravity setting) PartSys->sources[0].source.hue = hw_random16(); SEGENV.aux1 = 0xFFFF; // invalidate @@ -10343,7 +10372,7 @@ uint16_t mode_particleDrip(void) { PartSys = reinterpret_cast(SEGENV.data); // if not first call, just set the pointer to the PS if (PartSys == nullptr) - return mode_static(); // something went wrong, no data! + return mode_oops(); // something went wrong, no data! // Particle System settings PartSys->updateSystem(); // update system properties (dimensions and data pointers) @@ -10439,7 +10468,7 @@ uint16_t mode_particlePinball(void) { if (SEGMENT.call == 0) { // initialization if (!initParticleSystem1D(PartSys, 1, 128, 0, true)) // init - return mode_static(); // allocation failed or is single pixel + return mode_oops(); // allocation failed or is single pixel PartSys->sources[0].sourceFlags.collide = true; // seeded particles will collide (if enabled) PartSys->sources[0].source.x = PS_P_RADIUS_1D; //emit at bottom PartSys->setKillOutOfBounds(true); // out of bounds particles dont return @@ -10450,7 +10479,7 @@ uint16_t mode_particlePinball(void) { PartSys = reinterpret_cast(SEGENV.data); // if not first call, just set the pointer to the PS if (PartSys == nullptr) - return mode_static(); // something went wrong, no data! + return mode_oops(); // something went wrong, no data! // Particle System settings //uint32_t hardness = 240 + (SEGMENT.custom1>>4); @@ -10549,7 +10578,7 @@ uint16_t mode_particleDancingShadows(void) { if (SEGMENT.call == 0) { // initialization if (!initParticleSystem1D(PartSys, 1)) // init, one source - return mode_static(); // allocation failed or is single pixel + return mode_oops(); // allocation failed or is single pixel PartSys->sources[0].maxLife = 1000; //set long life (kill out of bounds is done in custom way) PartSys->sources[0].minLife = PartSys->sources[0].maxLife; } @@ -10558,7 +10587,7 @@ uint16_t mode_particleDancingShadows(void) { } if (PartSys == nullptr) - return mode_static(); // something went wrong, no data! + return mode_oops(); // something went wrong, no data! // Particle System settings PartSys->updateSystem(); // update system properties (dimensions and data pointers) @@ -10667,14 +10696,14 @@ uint16_t mode_particleFireworks1D(void) { if (SEGMENT.call == 0) { // initialization if (!initParticleSystem1D(PartSys, 4, 150, 4, true)) // init advanced particle system if (!initParticleSystem1D(PartSys, 4, 150, 4, true)) // init advanced particle system - return mode_static(); // allocation failed or is single pixel + return mode_oops(); // allocation failed or is single pixel PartSys->setKillOutOfBounds(true); PartSys->sources[0].sourceFlags.custom1 = 1; // set rocket state to standby } else PartSys = reinterpret_cast(SEGENV.data); // if not first call, just set the pointer to the PS if (PartSys == nullptr) - return mode_static(); // something went wrong, no data! + return mode_oops(); // something went wrong, no data! // Particle System settings PartSys->updateSystem(); // update system properties (dimensions and data pointers) @@ -10787,11 +10816,11 @@ uint16_t mode_particleSparkler(void) { if (SEGMENT.call == 0) { // initialization if (!initParticleSystem1D(PartSys, 16, 128 ,0, true)) // init, no additional data needed - return mode_static(); // allocation failed or is single pixel + return mode_oops(); // allocation failed or is single pixel } else PartSys = reinterpret_cast(SEGENV.data); // if not first call, just set the pointer to the PS if (PartSys == nullptr) - return mode_static(); // something went wrong, no data! + return mode_oops(); // something went wrong, no data! // Particle System settings PartSys->updateSystem(); // update system properties (dimensions and data pointers) @@ -10858,14 +10887,14 @@ uint16_t mode_particleHourglass(void) { uint32_t* settingTracker; if (SEGMENT.call == 0) { // initialization if (!initParticleSystem1D(PartSys, 0, 255, 8, false)) // init - return mode_static(); // allocation failed or is single pixel + return mode_oops(); // allocation failed or is single pixel PartSys->setBounce(true); PartSys->setWallHardness(100); } else PartSys = reinterpret_cast(SEGENV.data); // if not first call, just set the pointer to the PS if (PartSys == nullptr) - return mode_static(); // something went wrong, no data! + return mode_oops(); // something went wrong, no data! // Particle System settings PartSys->updateSystem(); // update system properties (dimensions and data pointers) @@ -10983,7 +11012,7 @@ uint16_t mode_particle1Dspray(void) { if (SEGMENT.call == 0) { // initialization if (!initParticleSystem1D(PartSys, 1)) - return mode_static(); // allocation failed or is single pixel + return mode_oops(); // allocation failed or is single pixel PartSys->setKillOutOfBounds(true); PartSys->setWallHardness(150); PartSys->setParticleSize(1); @@ -10991,7 +11020,7 @@ uint16_t mode_particle1Dspray(void) { else PartSys = reinterpret_cast(SEGENV.data); // if not first call, just set the pointer to the PS if (PartSys == nullptr) - return mode_static(); // something went wrong, no data! + return mode_oops(); // something went wrong, no data! // Particle System settings PartSys->updateSystem(); // update system properties (dimensions and data pointers) @@ -11036,13 +11065,13 @@ uint16_t mode_particleBalance(void) { if (SEGMENT.call == 0) { // initialization if (!initParticleSystem1D(PartSys, 1, 128)) // init, no additional data needed, use half of max particles - return mode_static(); // allocation failed or is single pixel + return mode_oops(); // allocation failed or is single pixel PartSys->setParticleSize(1); } else PartSys = reinterpret_cast(SEGENV.data); // if not first call, just set the pointer to the PS if (PartSys == nullptr) - return mode_static(); // something went wrong, no data! + return mode_oops(); // something went wrong, no data! // Particle System settings PartSys->updateSystem(); // update system properties (dimensions and data pointers) @@ -11115,7 +11144,7 @@ uint16_t mode_particleChase(void) { ParticleSystem1D *PartSys = nullptr; if (SEGMENT.call == 0) { // initialization if (!initParticleSystem1D(PartSys, 1, 255, 2, true)) // init - return mode_static(); // allocation failed or is single pixel + return mode_oops(); // allocation failed or is single pixel SEGENV.aux0 = 0xFFFF; // invalidate *PartSys->PSdataEnd = 1; // huedir *(PartSys->PSdataEnd + 1) = 1; // sizedir @@ -11123,7 +11152,7 @@ uint16_t mode_particleChase(void) { else PartSys = reinterpret_cast(SEGENV.data); // if not first call, just set the pointer to the PS if (PartSys == nullptr) - return mode_static(); // something went wrong, no data! + return mode_oops(); // something went wrong, no data! // Particle System settings PartSys->updateSystem(); // update system properties (dimensions and data pointers) PartSys->setColorByPosition(SEGMENT.check3); @@ -11211,7 +11240,7 @@ uint16_t mode_particleStarburst(void) { if (SEGMENT.call == 0) { // initialization if (!initParticleSystem1D(PartSys, 1, 200, 0, true)) // init - return mode_static(); // allocation failed or is single pixel + return mode_oops(); // allocation failed or is single pixel PartSys->setKillOutOfBounds(true); PartSys->enableParticleCollisions(true, 200); PartSys->sources[0].source.ttl = 1; // set initial stanby time @@ -11220,7 +11249,7 @@ uint16_t mode_particleStarburst(void) { else PartSys = reinterpret_cast(SEGENV.data); // if not first call, just set the pointer to the PS if (PartSys == nullptr) - return mode_static(); // something went wrong, no data! + return mode_oops(); // something went wrong, no data! // Particle System settings PartSys->updateSystem(); // update system properties (dimensions and data pointers) @@ -11273,12 +11302,12 @@ uint16_t mode_particle1DGEQ(void) { if (SEGMENT.call == 0) { // initialization if (!initParticleSystem1D(PartSys, 16, 255, 0, true)) // init, no additional data needed - return mode_static(); // allocation failed or is single pixel + return mode_oops(); // allocation failed or is single pixel } else PartSys = reinterpret_cast(SEGENV.data); // if not first call, just set the pointer to the PS if (PartSys == nullptr) - return mode_static(); // something went wrong, no data! + return mode_oops(); // something went wrong, no data! // Particle System settings PartSys->updateSystem(); // update system properties (dimensions and data pointers) @@ -11345,14 +11374,14 @@ uint16_t mode_particleFire1D(void) { if (SEGMENT.call == 0) { // initialization if (!initParticleSystem1D(PartSys, 5)) // init - return mode_static(); // allocation failed or is single pixel + return mode_oops(); // allocation failed or is single pixel PartSys->setKillOutOfBounds(true); PartSys->setParticleSize(1); } else PartSys = reinterpret_cast(SEGENV.data); // if not first call, just set the pointer to the PS if (PartSys == nullptr) - return mode_static(); // something went wrong, no data! + return mode_oops(); // something went wrong, no data! // Particle System settings PartSys->updateSystem(); // update system properties (dimensions and data pointers) @@ -11410,7 +11439,7 @@ uint16_t mode_particle1DsonicStream(void) { if (SEGMENT.call == 0) { // initialization if (!initParticleSystem1D(PartSys, 1, 255, 0, true)) // init, no additional data needed - return mode_static(); // allocation failed or is single pixel + return mode_oops(); // allocation failed or is single pixel PartSys->setKillOutOfBounds(true); PartSys->sources[0].source.x = 0; // at start //PartSys->sources[1].source.x = PartSys->maxX; // at end @@ -11419,7 +11448,7 @@ uint16_t mode_particle1DsonicStream(void) { else PartSys = reinterpret_cast(SEGENV.data); // if not first call, just set the pointer to the PS if (PartSys == nullptr) - return mode_static(); // something went wrong, no data! + return mode_oops(); // something went wrong, no data! // Particle System settings PartSys->updateSystem(); // update system properties (dimensions and data pointers) @@ -11513,13 +11542,13 @@ uint16_t mode_particle1DsonicBoom(void) { ParticleSystem1D *PartSys = nullptr; if (SEGMENT.call == 0) { // initialization if (!initParticleSystem1D(PartSys, 1, 255, 0, true)) // init, no additional data needed - return mode_static(); // allocation failed or is single pixel + return mode_oops(); // allocation failed or is single pixel PartSys->setKillOutOfBounds(true); } else PartSys = reinterpret_cast(SEGENV.data); // if not first call, just set the pointer to the PS if (PartSys == nullptr) - return mode_static(); // something went wrong, no data! + return mode_oops(); // something went wrong, no data! // Particle System settings PartSys->updateSystem(); // update system properties (dimensions and data pointers) @@ -11603,13 +11632,13 @@ uint16_t mode_particleSpringy(void) { ParticleSystem1D *PartSys = nullptr; if (SEGMENT.call == 0) { // initialization if (!initParticleSystem1D(PartSys, 1, 128, 0, true)) // init - return mode_static(); // allocation failed or is single pixel + return mode_oops(); // allocation failed or is single pixel SEGENV.aux0 = SEGENV.aux1 = 0xFFFF; // invalidate settings } else PartSys = reinterpret_cast(SEGENV.data); // if not first call, just set the pointer to the PS if (PartSys == nullptr) - return mode_static(); // something went wrong, no data! + return mode_oops(); // something went wrong, no data! // Particle System settings PartSys->updateSystem(); // update system properties (dimensions and data pointers) PartSys->setMotionBlur(220 * SEGMENT.check1); // anable motion blur diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index e3c30c68..7a270949 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -249,7 +249,7 @@ bool Segment::allocateData(size_t len) { Segment::addUsedSegmentData(len); _dataLen = len; memset(data, 0, len); - if (errorFlag == ERR_LOW_SEG_MEM) errorFlag = ERR_NONE; // WLEDMM reset errorflag on success + if ((errorFlag == ERR_LOW_SEG_MEM) || (errorFlag == ERR_LOW_MEM) || (errorFlag == ERR_NORAM_PX)) errorFlag = ERR_NONE; // WLEDMM reset errorflag on success return true; } @@ -1844,7 +1844,7 @@ void WS2812FX::finalizeInit(void) //#endif if (arrSize > 0) Segment::_globalLeds = (CRGB*) malloc(arrSize); // WLEDMM avoid malloc(0) if ((Segment::_globalLeds != nullptr) && (arrSize > 0)) memset(Segment::_globalLeds, 0, arrSize); // WLEDMM avoid dereferencing nullptr - if ((Segment::_globalLeds == nullptr) && (arrSize > 0)) errorFlag = ERR_LOW_MEM; // WLEDMM raise errorflag + if ((Segment::_globalLeds == nullptr) && (arrSize > 0)) errorFlag = ERR_NORAM_PX; // WLEDMM raise errorflag } //segments are created in makeAutoSegments(); diff --git a/wled00/data/index.js b/wled00/data/index.js index 3581442d..5d08a3f8 100644 --- a/wled00/data/index.js +++ b/wled00/data/index.js @@ -1977,7 +1977,7 @@ function readState(s,command=false) errstr = "Buffer locked!"; break; case 7: - errstr = "No RAM for buffer!"; + errstr = "No RAM for pixel buffer!"; break; case 8: errstr = "Effect RAM depleted!"; From c896768c0b4bff79cb1c3ca9ee64f283a188dc78 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Mon, 27 Oct 2025 11:43:23 +0100 Subject: [PATCH 034/170] small correction mode_oops() should not call mode_oops() --- wled00/FX.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index 63a1f154..93d29c17 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -135,7 +135,7 @@ static uint16_t mode_oops(void) { strip._colors_t[1] = BLUE; strip._colors_t[2] = GREEN; errorFlag = ERR_NORAM_PX; - if (SEGLEN <= 1) return mode_oops(); + if (SEGLEN <= 1) return mode_static(); const uint16_t width = SEGMENT.is2D() ? SEGMENT.virtualWidth() : SEGMENT.virtualLength(); const uint16_t height = SEGMENT.virtualHeight(); From b3f1c5d06cc6aaa97f6820be918246183096bdd0 Mon Sep 17 00:00:00 2001 From: Damian Schneider Date: Mon, 27 Oct 2025 19:28:50 +0100 Subject: [PATCH 035/170] adding fixes and improvements from AC --- wled00/FXparticleSystem.cpp | 75 +++++++++++++++++-------------------- wled00/FXparticleSystem.h | 37 +++++++++++------- 2 files changed, 58 insertions(+), 54 deletions(-) diff --git a/wled00/FXparticleSystem.cpp b/wled00/FXparticleSystem.cpp index cd537e8c..73de6a2b 100644 --- a/wled00/FXparticleSystem.cpp +++ b/wled00/FXparticleSystem.cpp @@ -593,7 +593,7 @@ void ParticleSystem2D::render() { baseRGB = ColorFromPalette(SEGPALETTE, particles[i].hue, 255, blend); if (particles[i].sat < 255) { CHSV baseHSV = rgb2hsv_approximate(baseRGB); // convert to HSV - baseHSV.s = particles[i].sat; // set the saturation + baseHSV.s = min(baseHSV.s, particles[i].sat); // set the saturation but don't increase it hsv2rgb_spectrum(baseHSV, baseRGB); // convert back to RGB } } @@ -1056,13 +1056,7 @@ void blur2D(CRGB *colorbuffer, uint32_t xsize, uint32_t ysize, uint32_t xblur, u //non class functions to use for initialization uint32_t calculateNumberOfParticles2D(uint32_t const pixels, const bool isadvanced, const bool sizecontrol) { uint32_t numberofParticles = pixels; // 1 particle per pixel (for example 512 particles on 32x16) -#ifdef ESP8266 - uint32_t particlelimit = ESP8266_MAXPARTICLES; // maximum number of paticles allowed (based on one segment of 16x16 and 4k effect ram) -#elif ARDUINO_ARCH_ESP32S2 - uint32_t particlelimit = ESP32S2_MAXPARTICLES; // maximum number of paticles allowed (based on one segment of 32x32 and 24k effect ram) -#else - uint32_t particlelimit = ESP32_MAXPARTICLES; // maximum number of paticles allowed (based on two segments of 32x32 and 40k effect ram) -#endif + uint32_t particlelimit = MAXPARTICLES_2D; // maximum number of paticles allowed numberofParticles = max((uint32_t)4, min(numberofParticles, particlelimit)); // limit to 4 - particlelimit if (isadvanced) // advanced property array needs ram, reduce number of particles to use the same amount numberofParticles = (numberofParticles * sizeof(PSparticle)) / (sizeof(PSparticle) + sizeof(PSadvancedParticle)); @@ -1075,16 +1069,8 @@ uint32_t calculateNumberOfParticles2D(uint32_t const pixels, const bool isadvanc } uint32_t calculateNumberOfSources2D(uint32_t pixels, uint32_t requestedsources) { -#ifdef ESP8266 - int numberofSources = min((pixels) / 8, (uint32_t)requestedsources); - numberofSources = max(1, min(numberofSources, ESP8266_MAXSOURCES)); // limit -#elif ARDUINO_ARCH_ESP32S2 - int numberofSources = min((pixels) / 6, (uint32_t)requestedsources); - numberofSources = max(1, min(numberofSources, ESP32S2_MAXSOURCES)); // limit -#else - int numberofSources = min((pixels) / 4, (uint32_t)requestedsources); - numberofSources = max(1, min(numberofSources, ESP32_MAXSOURCES)); // limit -#endif + int numberofSources = min((pixels) / SOURCEREDUCTIONFACTOR, (uint32_t)requestedsources); + numberofSources = max(1, min(numberofSources, MAXSOURCES_2D)); // limit // make sure it is a multiple of 4 for proper memory alignment numberofSources = (numberofSources+3) & ~0x03; return numberofSources; @@ -1122,10 +1108,19 @@ bool initParticleSystem2D(ParticleSystem2D *&PartSys, uint32_t requestedsources, PSPRINT(" segmentsize:" + String(cols) + " x " + String(rows)); PSPRINT(" request numparticles:" + String(numparticles)); uint32_t numsources = calculateNumberOfSources2D(pixels, requestedsources); - if (!allocateParticleSystemMemory2D(numparticles, numsources, advanced, sizecontrol, additionalbytes)) - { - DEBUG_PRINT(F("PS init failed: memory depleted")); - return false; + bool allocsuccess = false; + while(numparticles >= 4) { // make sure we have at least 4 particles or quit + if (allocateParticleSystemMemory2D(numparticles, numsources, advanced, sizecontrol, additionalbytes)) { + PSPRINTLN(F("PS 2D alloc succeeded")); + allocsuccess = true; + break; // allocation succeeded + } + numparticles = ((numparticles / 2) + 3) & ~0x03; // cut number of particles in half and try again, must be 4 byte aligned + PSPRINTLN(F("PS 2D alloc failed, trying with less particles...")); + } + if (!allocsuccess) { + PSPRINTLN(F("PS 2D alloc failed, not enough memory!")); + return false; // allocation failed } PartSys = new (SEGENV.data) ParticleSystem2D(cols, rows, numparticles, numsources, advanced, sizecontrol); // particle system constructor @@ -1457,7 +1452,7 @@ void ParticleSystem1D::render() { if (advPartProps) { //saturation is advanced property in 1D system if (advPartProps[i].sat < 255) { CHSV baseHSV = rgb2hsv_approximate(baseRGB); // convert to HSV - baseHSV.s = advPartProps[i].sat; + baseHSV.s = min(baseHSV.s, advPartProps[i].sat); // set the saturation but don't increase it hsv2rgb_spectrum(baseHSV, baseRGB); // convert back to RGB } } @@ -1775,18 +1770,12 @@ void ParticleSystem1D::updatePSpointers(bool isadvanced) { //non class functions to use for initialization, fraction is uint8_t: 255 means 100% uint32_t calculateNumberOfParticles1D(const uint32_t fraction, const bool isadvanced) { uint32_t numberofParticles = SEGMENT.virtualLength(); // one particle per pixel (if possible) -#ifdef ESP8266 - uint32_t particlelimit = ESP8266_MAXPARTICLES_1D; // maximum number of paticles allowed -#elif ARDUINO_ARCH_ESP32S2 - uint32_t particlelimit = ESP32S2_MAXPARTICLES_1D; // maximum number of paticles allowed -#else - uint32_t particlelimit = ESP32_MAXPARTICLES_1D; // maximum number of paticles allowed -#endif + uint32_t particlelimit = MAXPARTICLES_1D; // maximum number of paticles allowed numberofParticles = min(numberofParticles, particlelimit); // limit to particlelimit if (isadvanced) // advanced property array needs ram, reduce number of particles to use the same amount numberofParticles = (numberofParticles * sizeof(PSparticle1D)) / (sizeof(PSparticle1D) + sizeof(PSadvancedParticle1D)); numberofParticles = (numberofParticles * (fraction + 1)) >> 8; // calculate fraction of particles - numberofParticles = numberofParticles < 20 ? 20 : numberofParticles; // 20 minimum + numberofParticles = numberofParticles < 10 ? 10 : numberofParticles; // 10 minimum //make sure it is a multiple of 4 for proper memory alignment (easier than using padding bytes) numberofParticles = (numberofParticles+3) & ~0x03; // note: with a separate particle buffer, this is probably unnecessary PSPRINTLN(" calc numparticles:" + String(numberofParticles)); @@ -1794,13 +1783,7 @@ uint32_t calculateNumberOfParticles1D(const uint32_t fraction, const bool isadva } uint32_t calculateNumberOfSources1D(const uint32_t requestedsources) { -#ifdef ESP8266 - int numberofSources = max(1, min((int)requestedsources,ESP8266_MAXSOURCES_1D)); // limit -#elif ARDUINO_ARCH_ESP32S2 - int numberofSources = max(1, min((int)requestedsources, ESP32S2_MAXSOURCES_1D)); // limit -#else - int numberofSources = max(1, min((int)requestedsources, ESP32_MAXSOURCES_1D)); // limit -#endif + int numberofSources = max(1, min((int)requestedsources, MAXSOURCES_1D)); // limit // make sure it is a multiple of 4 for proper memory alignment (so minimum is acutally 4) numberofSources = (numberofSources+3) & ~0x03; return numberofSources; @@ -1828,9 +1811,19 @@ bool initParticleSystem1D(ParticleSystem1D *&PartSys, const uint32_t requestedso if (SEGLEN == 1) return false; // single pixel not supported uint32_t numparticles = calculateNumberOfParticles1D(fractionofparticles, advanced); uint32_t numsources = calculateNumberOfSources1D(requestedsources); - if (!allocateParticleSystemMemory1D(numparticles, numsources, advanced, additionalbytes)) { - DEBUG_PRINT(F("PS init failed: memory depleted")); - return false; + bool allocsuccess = false; + while(numparticles >= 10) { // make sure we have at least 10 particles or quit + if (allocateParticleSystemMemory1D(numparticles, numsources, advanced, additionalbytes)) { + PSPRINT(F("PS 1D alloc succeeded")); + allocsuccess = true; + break; // allocation succeeded + } + numparticles = ((numparticles / 2) + 3) & ~0x03; // cut number of particles in half and try again, must be 4 byte aligned + PSPRINTLN(F("PS 1D alloc failed, trying with less particles...")); + } + if (!allocsuccess) { + PSPRINTLN(F("PS init failed: memory depleted")); + return false; // allocation failed } PartSys = new (SEGENV.data) ParticleSystem1D(SEGMENT.virtualLength(), numparticles, numsources, advanced); // particle system constructor return true; diff --git a/wled00/FXparticleSystem.h b/wled00/FXparticleSystem.h index a1d273a7..d295bf85 100644 --- a/wled00/FXparticleSystem.h +++ b/wled00/FXparticleSystem.h @@ -37,13 +37,20 @@ static inline int32_t limitSpeed(const int32_t speed) { #endif #ifndef WLED_DISABLE_PARTICLESYSTEM2D -// memory allocation -#define ESP8266_MAXPARTICLES 256 // enough up to 16x16 pixels -#define ESP8266_MAXSOURCES 24 -#define ESP32S2_MAXPARTICLES 1024 // enough up to 32x32 pixels -#define ESP32S2_MAXSOURCES 64 -#define ESP32_MAXPARTICLES 2048 // enough up to 64x32 pixels -#define ESP32_MAXSOURCES 128 +// memory allocation (based on reasonable segment size and available FX memory) +#ifdef ESP8266 + #define MAXPARTICLES_2D 256 + #define MAXSOURCES_2D 24 + #define SOURCEREDUCTIONFACTOR 8 +#elif ARDUINO_ARCH_ESP32S2 + #define MAXPARTICLES_2D 1024 + #define MAXSOURCES_2D 64 + #define SOURCEREDUCTIONFACTOR 6 +#else + #define MAXPARTICLES_2D 2048 + #define MAXSOURCES_2D 128 + #define SOURCEREDUCTIONFACTOR 4 +#endif // particle dimensions (subpixel division) #define PS_P_RADIUS 64 // subpixel size, each pixel is divided by this for particle movement (must be a power of 2) @@ -232,12 +239,16 @@ bool allocateParticleSystemMemory2D(const uint32_t numparticles, const uint32_t //////////////////////// #ifndef WLED_DISABLE_PARTICLESYSTEM1D // memory allocation -#define ESP8266_MAXPARTICLES_1D 320 -#define ESP8266_MAXSOURCES_1D 16 -#define ESP32S2_MAXPARTICLES_1D 1300 -#define ESP32S2_MAXSOURCES_1D 32 -#define ESP32_MAXPARTICLES_1D 2600 -#define ESP32_MAXSOURCES_1D 64 +#ifdef ESP8266 + #define MAXPARTICLES_1D 320 + #define MAXSOURCES_1D 16 +#elif ARDUINO_ARCH_ESP32S2 + #define MAXPARTICLES_1D 1300 + #define MAXSOURCES_1D 32 +#else + #define MAXPARTICLES_1D 2600 + #define MAXSOURCES_1D 64 +#endif // particle dimensions (subpixel division) #define PS_P_RADIUS_1D 32 // subpixel size, each pixel is divided by this for particle movement, if this value is changed, also change the shift defines (next two lines) From c4f6d3d2cb463bcc51dd70b6eb0b2c5d58147b4c Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Mon, 27 Oct 2025 19:34:51 +0100 Subject: [PATCH 036/170] ParticleFX better defaults for 64 pixel height change default sliders of PS Fireworks, PS Volcano and PS GEQ 2D for better visibility on 64x64 panel --- wled00/FX.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index 93d29c17..f25de8c4 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -9299,7 +9299,7 @@ uint16_t mode_particlefireworks(void) { return FRAMETIME; } #undef NUMBEROFSOURCES -static const char _data_FX_MODE_PARTICLEFIREWORKS[] PROGMEM = "PS Fireworks@Launches,Explosion Size,Fuse,Blur,Gravity,Cylinder,Ground,Fast;;!;2;pal=11,ix=50,c1=40,c2=0,c3=12"; +static const char _data_FX_MODE_PARTICLEFIREWORKS[] PROGMEM = "PS Fireworks@Launches,Explosion Size,Fuse,Blur,Gravity,Cylinder,Ground,Fast;;!;2;pal=11,ix=200,sx=180,c1=196,c2=0,c3=10,o3=1"; /* Particle Volcano @@ -9373,7 +9373,7 @@ uint16_t mode_particlevolcano(void) { return FRAMETIME; } #undef NUMBEROFSOURCES -static const char _data_FX_MODE_PARTICLEVOLCANO[] PROGMEM = "PS Volcano@Speed,Intensity,Move,Bounce,Spread,AgeColor,Walls,Collide;;!;2;pal=35,sx=100,ix=190,c1=0,c2=160,c3=6,o1=1"; +static const char _data_FX_MODE_PARTICLEVOLCANO[] PROGMEM = "PS Volcano@Speed,Intensity,Move,Bounce,Spread,AgeColor,Walls,Collide;;!;2;pal=35,sx=208,ix=190,c1=0,c2=190,c3=16,o1=1"; /* Particle Fire @@ -9427,7 +9427,7 @@ uint16_t mode_particlefire(void) { PartSys->sources[i].source.ttl = 20 + hw_random16((SEGMENT.custom1 * SEGMENT.custom1) >> 8) / (1 + (firespeed >> 5)); //'hotness' of fire, faster flames reduce the effect or flame height will scale too much with speed PartSys->sources[i].maxLife = hw_random16(SEGMENT.virtualHeight() >> 1) + 16; // defines flame height together with the vy speed, vy speed*maxlife/PS_P_RADIUS is the average flame height PartSys->sources[i].minLife = PartSys->sources[i].maxLife >> 1; - PartSys->sources[i].vx = hw_random16(4) - 2; // emitting speed (sideways) + PartSys->sources[i].vx = hw_random16(5) - 2; // emitting speed (sideways) PartSys->sources[i].vy = (SEGMENT.virtualHeight() >> 1) + (firespeed >> 4) + (SEGMENT.custom1 >> 4); // emitting speed (upwards) PartSys->sources[i].var = 2 + hw_random16(2 + (firespeed >> 4)); // speed variation around vx,vy (+/- var) } @@ -10116,7 +10116,7 @@ uint16_t mode_particleGEQ(void) { return FRAMETIME; } -static const char _data_FX_MODE_PARTICLEGEQ[] PROGMEM = "PS GEQ 2D@Speed,Intensity,Diverge,Bounce,Gravity,Cylinder,Walls,Floor;;!;2f;pal=0,sx=155,ix=200,c1=0"; +static const char _data_FX_MODE_PARTICLEGEQ[] PROGMEM = "PS GEQ 2D@Speed,Intensity,Diverge,Bounce,Gravity,Cylinder,Walls,Floor;;!;2f;pal=0,sx=232,ix=200,c1=0,c3=9"; /* Particle rotating GEQ From 74c701b7459f8aed27769d440a43368c84786705 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Mon, 27 Oct 2025 21:19:40 +0100 Subject: [PATCH 037/170] HUB75: no color temperature correction for performance reasons Enable building color correction code if you really need it. The effect of color correction is less noticeable on HUB75 than on ws2812b, however it can reduce your framerate by up to 10%. --- wled00/bus_manager.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/wled00/bus_manager.cpp b/wled00/bus_manager.cpp index e4e70507..a3806b00 100644 --- a/wled00/bus_manager.cpp +++ b/wled00/bus_manager.cpp @@ -1059,8 +1059,9 @@ BusHub75Matrix::BusHub75Matrix(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWh void __attribute__((hot)) IRAM_ATTR BusHub75Matrix::setPixelColor(uint16_t pix, uint32_t c) { if ( pix >= _len) return; - // if (_cct >= 1900) c = colorBalanceFromKelvin(_cct, c); //color correction from CCT - + #if 0 + if ((correctWB) && (_cct >= 1900)) c = colorBalanceFromKelvin(_cct, c); //color correction from CCT - reduces framerate by up to 10%. If you still want it, change the line above to "#if 1" + #endif if (_ledBuffer) { CRGB fastled_col = CRGB(c); if (_ledBuffer[pix] != fastled_col) { From 13331e3de01caa21c28988a0253c1ba28d879c73 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Fri, 31 Oct 2025 11:09:45 +0100 Subject: [PATCH 038/170] const WS2812FX::setPixelColorXY small optimization for speed --- wled00/FX.h | 8 ++++---- wled00/FX_2Dfcn.cpp | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/wled00/FX.h b/wled00/FX.h index 7559b09e..fedca84a 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -1095,12 +1095,12 @@ class WS2812FX { // 96 bytes void setUpMatrix(), - setPixelColorXY_fast(int x, int y, uint32_t c), - setPixelColorXY(int x, int y, uint32_t c); + setPixelColorXY_fast(int x, int y, uint32_t c) const, + setPixelColorXY(int x, int y, uint32_t c) const; // outsmart the compiler :) by correctly overloading - inline void setPixelColorXY(int x, int y, byte r, byte g, byte b, byte w = 0) { setPixelColorXY(x, y, RGBW32(r,g,b,w)); } // automatically inline - inline void setPixelColorXY(int x, int y, CRGB c) { setPixelColorXY(x, y, RGBW32(c.r,c.g,c.b,0)); } + inline void setPixelColorXY(int x, int y, byte r, byte g, byte b, byte w = 0) const { setPixelColorXY(x, y, RGBW32(r,g,b,w)); } // automatically inline + inline void setPixelColorXY(int x, int y, CRGB c) const { setPixelColorXY(x, y, RGBW32(c.r,c.g,c.b,0)); } uint32_t getPixelColorXY(uint16_t, uint16_t) const; diff --git a/wled00/FX_2Dfcn.cpp b/wled00/FX_2Dfcn.cpp index 247f166e..dd2b280a 100644 --- a/wled00/FX_2Dfcn.cpp +++ b/wled00/FX_2Dfcn.cpp @@ -195,7 +195,7 @@ void WS2812FX::setUpMatrix() { } // absolute matrix version of setPixelColor(), without error checking -void IRAM_ATTR __attribute__((hot)) WS2812FX::setPixelColorXY_fast(int x, int y, uint32_t col) //WLEDMM: IRAM_ATTR conditionally +void IRAM_ATTR __attribute__((hot)) WS2812FX::setPixelColorXY_fast(int x, int y, uint32_t col) const //WLEDMM: IRAM_ATTR conditionally { uint_fast16_t index = y * Segment::maxWidth + x; if (index < customMappingSize) index = customMappingTable[index]; @@ -204,7 +204,7 @@ void IRAM_ATTR __attribute__((hot)) WS2812FX::setPixelColorXY_fast(int x, int y, } // absolute matrix version of setPixelColor() -void IRAM_ATTR_YN WS2812FX::setPixelColorXY(int x, int y, uint32_t col) //WLEDMM: IRAM_ATTR conditionally +void IRAM_ATTR_YN WS2812FX::setPixelColorXY(int x, int y, uint32_t col) const //WLEDMM: IRAM_ATTR conditionally { #ifndef WLED_DISABLE_2D if (!isMatrix) return; // not a matrix set-up From 96c32443187152b106ed51224c3a98ca7f60ded8 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sat, 1 Nov 2025 13:30:51 +0100 Subject: [PATCH 039/170] removing deactivated code --- wled00/colors.cpp | 22 +++------------------- 1 file changed, 3 insertions(+), 19 deletions(-) diff --git a/wled00/colors.cpp b/wled00/colors.cpp index 36cb1b4b..336a8e22 100644 --- a/wled00/colors.cpp +++ b/wled00/colors.cpp @@ -320,25 +320,9 @@ static float maxf (float v, float w) // WLEDMM better use standard library fmax } #endif -// adjust RGB values based on color temperature in K (range [2800-10200]) (https://en.wikipedia.org/wiki/Color_balance) -// called from bus manager when color correction is enabled! -#if 0 -// WLEDMM moved into bus_manager.cpp for better optimization -uint32_t __attribute__((hot)) IRAM_ATTR_YN colorBalanceFromKelvin(uint16_t kelvin, uint32_t rgb) // WLEDMM: IRAM_ATTR_YN -{ - //remember so that slow colorKtoRGB() doesn't have to run for every setPixelColor() - static byte correctionRGB[4] = {0,0,0,0}; - static uint16_t lastKelvin = 0; - if (lastKelvin != kelvin) colorKtoRGB(kelvin, correctionRGB); // convert Kelvin to RGB - lastKelvin = kelvin; - byte rgbw[4]; - rgbw[0] = ((uint16_t) correctionRGB[0] * R(rgb)) /255; // correct R - rgbw[1] = ((uint16_t) correctionRGB[1] * G(rgb)) /255; // correct G - rgbw[2] = ((uint16_t) correctionRGB[2] * B(rgb)) /255; // correct B - rgbw[3] = W(rgb); - return RGBW32(rgbw[0],rgbw[1],rgbw[2],rgbw[3]); -} -#endif + +// WLEDMM colorBalanceFromKelvin moved into bus_manager.cpp for better optimization + //approximates a Kelvin color temperature from an RGB color. //this does no check for the "whiteness" of the color, From 297a2c2b9cf3e5e1ced32b5195e44882586bc1e2 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sat, 1 Nov 2025 14:16:47 +0100 Subject: [PATCH 040/170] bring back lost function ColorFromPaletteWLED (WLEDMM_SAVE_FLASH only) this change was somehow lost - ColorFromPaletteWLED existed in colorTools.hpp (for fast inline) but was missing in colors.cpp (WLEDMM_SAVE_FLASH fallback). --- wled00/colors.cpp | 34 ++++++++++++++++++++++++++++++++++ wled00/fcn_declare.h | 7 +++++++ 2 files changed, 41 insertions(+) diff --git a/wled00/colors.cpp b/wled00/colors.cpp index f741e7a6..f1bbea0a 100644 --- a/wled00/colors.cpp +++ b/wled00/colors.cpp @@ -102,6 +102,40 @@ uint32_t WLED_O2_ATTR IRAM_ATTR_YN __attribute__((hot)) color_fade(uint32_t c1, uint32_t wg = (((c1 >> 8) & TWO_CHANNEL_MASK) * amount) & ~TWO_CHANNEL_MASK; // scale white and green return (rb | wg) + addRemains; } + +// +// overwrite FastLed colorFromPalette with an optimized version created by dedehai (https://github.com/Aircoookie/WLED/pull/4138) +// +// 1:1 replacement of fastled function optimized for ESP, slightly faster, more accurate and uses less flash (~ -200bytes) +CRGB IRAM_ATTR_YN __attribute__((hot)) ColorFromPaletteWLED(const CRGBPalette16& pal, unsigned index, uint8_t brightness, TBlendType blendType) +{ + if (blendType == LINEARBLEND_NOWRAP) { + index = (index*240) >> 8; // Blend range is affected by lo4 blend of values, remap to avoid wrapping + } + unsigned hi4 = byte(index) >> 4; + const CRGB* entry = (CRGB*)((uint8_t*)(&(pal[0])) + (hi4 * sizeof(CRGB))); + unsigned red1 = entry->r; + unsigned green1 = entry->g; + unsigned blue1 = entry->b; + if (blendType != NOBLEND) { + if (hi4 == 15) entry = &(pal[0]); + else ++entry; + unsigned f2 = ((index & 0x0F) << 4) + 1; // +1 so we scale by 256 as a max value, then result can just be shifted by 8 + unsigned f1 = (257 - f2); // f2 is 1 minimum, so this is 256 max + red1 = (red1 * f1 + (unsigned)entry->r * f2) >> 8; + green1 = (green1 * f1 + (unsigned)entry->g * f2) >> 8; + blue1 = (blue1 * f1 + (unsigned)entry->b * f2) >> 8; + } + if (brightness < 255) { // note: zero checking could be done to return black but that is hardly ever used so it is omitted + uint32_t scale = brightness + 1; // adjust for rounding (bitshift) + red1 = (red1 * scale) >> 8; + green1 = (green1 * scale) >> 8; + blue1 = (blue1 * scale) >> 8; + } + return RGBW32(red1,green1,blue1,0); + //return CRGB(red1,green1,blue1); +} + #endif void setRandomColor(byte* rgb) diff --git a/wled00/fcn_declare.h b/wled00/fcn_declare.h index 188c10ee..c5e95604 100644 --- a/wled00/fcn_declare.h +++ b/wled00/fcn_declare.h @@ -51,9 +51,16 @@ bool getJsonValue(const JsonVariant& element, DestType& destination, const Defau //colors.cpp #if !defined(ARDUINO_ARCH_ESP32) || !defined(WLEDMM_FASTPATH) || defined(WLEDMM_SAVE_FLASH) // WLEDMM: color utils moved into colorTools.hpp, so the compiler may inline these functions (faster) +#if !defined(FASTLED_VERSION) // pull in FastLED if we don't have it yet (we need the CRGB type) + #define FASTLED_INTERNAL + #include +#endif uint32_t __attribute__((const)) color_blend(uint32_t,uint32_t,uint_fast16_t,bool b16=false); // WLEDMM: added attribute const uint32_t __attribute__((const)) color_add(uint32_t,uint32_t, bool fast=false); // WLEDMM: added attribute const uint32_t __attribute__((const)) color_fade(uint32_t c1, uint8_t amount, bool video=false); +#undef ColorFromPalette // overwrite any existing override +CRGB __attribute__((hot,const)) ColorFromPaletteWLED(const CRGBPalette16& pal, unsigned index, uint8_t brightness=255, TBlendType blendType=LINEARBLEND); +#define ColorFromPalette ColorFromPaletteWLED // override fastled function #else #include "colorTools.hpp" #endif From 40064490ad39b161077572fe64e7f393fb4b37f8 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sat, 1 Nov 2025 16:50:20 +0100 Subject: [PATCH 041/170] strip level setPixelColor and getPixelColor optimization * moved sPC and gPC functions out of their .cpp files into FX.h, so the compiler can optimize better. depending of effect used, this gives a 2% up to 8% speedup. --- wled00/FX.h | 101 ++++++++++++++++++++++++++++++++++++++------ wled00/FX_2Dfcn.cpp | 46 +++----------------- wled00/FX_fcn.cpp | 21 ++------- 3 files changed, 97 insertions(+), 71 deletions(-) diff --git a/wled00/FX.h b/wled00/FX.h index fedca84a..327c6476 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -21,6 +21,11 @@ bool strip_uses_global_leds(void) __attribute__((pure)); // WLEDMM implemented #define USE_GET_MILLISECOND_TIMER #include "FastLED.h" + // WLEDMM strip.sPC() needs to know "busses", so we pull in the declarition +#include "pin_manager.h" // BusManager needs to know pinManager +#include "bus_manager.h" +extern BusManager busses; // same as wled.h + #define DEFAULT_BRIGHTNESS (uint8_t)127 #define DEFAULT_MODE (uint8_t)0 #define DEFAULT_SPEED (uint8_t)128 @@ -957,7 +962,6 @@ class WS2812FX { // 96 bytes resetSegments(bool boundsOnly = false), //WLEDMM add boundsOnly makeAutoSegments(bool forceReset = false), fixInvalidSegments(), - setPixelColor(int n, uint32_t c), show(void), setTargetFps(uint8_t fps), enumerateLedmaps(); //WLEDMM (from fcn_declare) @@ -968,8 +972,8 @@ class WS2812FX { // 96 bytes void setupEffectData(void); // add default effects to the list; defined in FX.cpp // outsmart the compiler :) by correctly overloading - inline void setPixelColor(int n, uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0) { setPixelColor(n, RGBW32(r,g,b,w)); } - inline void setPixelColor(int n, CRGB c) { setPixelColor(n, c.red, c.green, c.blue); } + inline void setPixelColor(int n, uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0) const { setPixelColor(n, RGBW32(r,g,b,w)); } + inline void setPixelColor(int n, CRGB c) const { setPixelColor(n, c.red, c.green, c.blue); } inline void trigger(void) { _triggered = true; } // Forces the next frame to be computed on all active segments. inline void setShowCallback(show_callback cb) { _callback = cb; } inline void setTransition(uint16_t t) { _transitionDur = t; } @@ -1024,8 +1028,33 @@ class WS2812FX { // 96 bytes uint32_t now, timebase; - uint32_t __attribute__((pure)) getPixelColor(uint_fast16_t) const; // WLEDMM attribute pure = does not have side-effects - uint32_t __attribute__((pure)) getPixelColorRestored(uint_fast16_t i) const;// WLEDMM gets the original color from the driver (without downscaling by _bri) + + // ////////////// + // inline methods for 1D + // WLEDMM setPixelColor and getPixelColor moved from FX_fcn.cpp for speed (inlining) + + inline void setPixelColor(int i, uint32_t color32) const + { + if (i < customMappingSize) i = customMappingTable[i]; + if (i >= _length) return; + busses.setPixelColor(i, color32); + } + + inline uint32_t getPixelColor(uint_fast16_t i) const + { + if (i < customMappingSize) i = customMappingTable[i]; + if (i >= _length) return 0; + return busses.getPixelColor(i); + } + + // WLEDMM gets the original color from the driver (without downscaling by _bri) + inline uint32_t getPixelColorRestored(uint_fast16_t i) const + { + if (i < customMappingSize) i = customMappingTable[i]; + if (i >= _length) return 0; + return busses.getPixelColorRestored(i); + } + inline uint32_t getLastShow(void) const { return _lastShow; } inline uint32_t segColor(uint8_t i) const { return _colors_t[i]; } @@ -1093,18 +1122,64 @@ class WS2812FX { // 96 bytes std::vector panel; #endif - void - setUpMatrix(), - setPixelColorXY_fast(int x, int y, uint32_t c) const, - setPixelColorXY(int x, int y, uint32_t c) const; + void setUpMatrix(); + + // ////////////// + // inline methods for 2D + // WLEDMM setPixelColorXY and getPixelColorXY moved from FX_2Dfcn.cpp for speed (inlining) + + // absolute matrix version of setPixelColor(), without error checking // WLEDMM + inline void __attribute__((hot)) setPixelColorXY_fast(int x, int y, uint32_t color32) const //WLEDMM: IRAM_ATTR conditionally + { + uint_fast16_t index = y * Segment::maxWidth + x; + if (index < customMappingSize) index = customMappingTable[index]; + if (index >= _length) return; + busses.setPixelColor(index, color32); + } + + // absolute matrix version of setPixelColor() + inline void setPixelColorXY(int x, int y, uint32_t color32) const //WLEDMM: IRAM_ATTR conditionally + { + #ifndef WLED_DISABLE_2D + if (!isMatrix) return; // not a matrix set-up + uint_fast16_t index = y * Segment::maxWidth + x; + #else + uint16_t index = x; + #endif + if (index < customMappingSize) index = customMappingTable[index]; + if (index >= _length) return; + busses.setPixelColor(index, color32); + } + + // returns RGBW values of pixel + inline uint32_t __attribute__((hot)) getPixelColorXY(uint16_t x, uint16_t y) const { + #ifndef WLED_DISABLE_2D + uint_fast16_t index = (y * Segment::maxWidth + x); //WLEDMM: use fast types + #else + uint16_t index = x; + #endif + if (index < customMappingSize) index = customMappingTable[index]; + if (index >= _length) return 0; + return busses.getPixelColor(index); + } + + // WLEDMM gets the original color from the driver (without downscaling by _bri) + inline uint32_t __attribute__((hot)) getPixelColorXYRestored(uint16_t x, uint16_t y) const { + #ifndef WLED_DISABLE_2D + uint_fast16_t index = (y * Segment::maxWidth + x); //WLEDMM: use fast types + #else + uint16_t index = x; + #endif + if (index < customMappingSize) index = customMappingTable[index]; + if (index >= _length) return 0; + return busses.getPixelColorRestored(index); + } + // outsmart the compiler :) by correctly overloading inline void setPixelColorXY(int x, int y, byte r, byte g, byte b, byte w = 0) const { setPixelColorXY(x, y, RGBW32(r,g,b,w)); } // automatically inline inline void setPixelColorXY(int x, int y, CRGB c) const { setPixelColorXY(x, y, RGBW32(c.r,c.g,c.b,0)); } - uint32_t - getPixelColorXY(uint16_t, uint16_t) const; - // end 2D support void loadCustomPalettes(void); // loads custom palettes from JSON @@ -1121,8 +1196,6 @@ class WS2812FX { // 96 bytes std::vector _segments; friend struct Segment; - uint32_t getPixelColorXYRestored(uint16_t x, uint16_t y) const; // WLEDMM gets the original color from the driver (without downscaling by _bri) - private: uint16_t _length; uint8_t _brightness; diff --git a/wled00/FX_2Dfcn.cpp b/wled00/FX_2Dfcn.cpp index dd2b280a..a8545113 100644 --- a/wled00/FX_2Dfcn.cpp +++ b/wled00/FX_2Dfcn.cpp @@ -194,51 +194,19 @@ void WS2812FX::setUpMatrix() { #endif } + // absolute matrix version of setPixelColor(), without error checking -void IRAM_ATTR __attribute__((hot)) WS2812FX::setPixelColorXY_fast(int x, int y, uint32_t col) const //WLEDMM: IRAM_ATTR conditionally -{ - uint_fast16_t index = y * Segment::maxWidth + x; - if (index < customMappingSize) index = customMappingTable[index]; - if (index >= _length) return; - busses.setPixelColor(index, col); -} +// WLEDMM: WS2812FX::setPixelColorXY_fast() moved FX.h for speed (inlining) // absolute matrix version of setPixelColor() -void IRAM_ATTR_YN WS2812FX::setPixelColorXY(int x, int y, uint32_t col) const //WLEDMM: IRAM_ATTR conditionally -{ -#ifndef WLED_DISABLE_2D - if (!isMatrix) return; // not a matrix set-up - uint_fast16_t index = y * Segment::maxWidth + x; -#else - uint16_t index = x; -#endif - if (index < customMappingSize) index = customMappingTable[index]; - if (index >= _length) return; - busses.setPixelColor(index, col); -} +// WLEDMM: WS2812FX::setPixelColorXY() moved FX.h for speed (inlining) // returns RGBW values of pixel -uint32_t __attribute__((hot)) WS2812FX::getPixelColorXY(uint16_t x, uint16_t y) const { -#ifndef WLED_DISABLE_2D - uint_fast16_t index = (y * Segment::maxWidth + x); //WLEDMM: use fast types -#else - uint16_t index = x; -#endif - if (index < customMappingSize) index = customMappingTable[index]; - if (index >= _length) return 0; - return busses.getPixelColor(index); -} +// WLEDMM: WS2812FX::getPixelColorXY() moved FX.h for speed (inlining) + +// WLEDMM gets the original color from the driver (without downscaling by _bri) +// WLEDMM: WS2812FX::getPixelColorXYRestored() moved FX.h for speed (inlining) -uint32_t __attribute__((hot)) WS2812FX::getPixelColorXYRestored(uint16_t x, uint16_t y) const { // WLEDMM gets the original color from the driver (without downscaling by _bri) - #ifndef WLED_DISABLE_2D - uint_fast16_t index = (y * Segment::maxWidth + x); //WLEDMM: use fast types - #else - uint16_t index = x; - #endif - if (index < customMappingSize) index = customMappingTable[index]; - if (index >= _length) return 0; - return busses.getPixelColorRestored(index); -} /////////////////////////////////////////////////////////// // Segment:: routines diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index 7a270949..eb0c97e8 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -1969,26 +1969,11 @@ void WS2812FX::service() { _isServicing = false; } -void IRAM_ATTR WS2812FX::setPixelColor(int i, uint32_t col) -{ - if (i < customMappingSize) i = customMappingTable[i]; - if (i >= _length) return; - busses.setPixelColor(i, col); -} -uint32_t WS2812FX::getPixelColor(uint_fast16_t i) const // WLEDMM fast int types -{ - if (i < customMappingSize) i = customMappingTable[i]; - if (i >= _length) return 0; - return busses.getPixelColor(i); -} +// WLEDMM: WS2812FX::setPixelColor() moved FX.h for speed (inlining) +// WLEDMM: WS2812FX::getPixelColor() moved FX.h for speed (inlining) +// WLEDMM: WS2812FX::getPixelColorRestored() moved FX.h for speed (inlining) -uint32_t WS2812FX::getPixelColorRestored(uint_fast16_t i) const // WLEDMM gets the original color from the driver (without downscaling by _bri) -{ - if (i < customMappingSize) i = customMappingTable[i]; - if (i >= _length) return 0; - return busses.getPixelColorRestored(i); -} //DISCLAIMER //The following function attemps to calculate the current LED power usage, From d5dee6f58a27a66a1f687d748672c644bbe70bd4 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sat, 1 Nov 2025 17:06:58 +0100 Subject: [PATCH 042/170] small segment level setPixelColor and getPixelColor optimization replaced CRGB -> RGBW32 conversion with FastLED native ``uint32_t(c) & 0x00FFFFFF`` operator. ` `& 0x00FFFFFF`` is needed to cut out the "alpha" channel, because the fastLED operator return RGBA not RGBW. --> slightly faster --- wled00/FX.h | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/wled00/FX.h b/wled00/FX.h index 327c6476..c52c8869 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -678,10 +678,10 @@ typedef struct Segment { #endif void setPixelColor(int n, uint32_t c); // set relative pixel within segment with color inline void setPixelColor(int n, byte r, byte g, byte b, byte w = 0) { setPixelColor(n, RGBW32(r,g,b,w)); } // automatically inline - inline void setPixelColor(int n, CRGB c) { setPixelColor(n, RGBW32(c.r,c.g,c.b,0)); } // automatically inline + inline void setPixelColor(int n, CRGB c) { setPixelColor(n, uint32_t(c) & 0x00FFFFFF); } // automatically inline void setPixelColor(float i, uint32_t c, bool aa = true); inline void setPixelColor(float i, uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0, bool aa = true) { setPixelColor(i, RGBW32(r,g,b,w), aa); } - inline void setPixelColor(float i, CRGB c, bool aa = true) { setPixelColor(i, RGBW32(c.r,c.g,c.b,0), aa); } + inline void setPixelColor(float i, CRGB c, bool aa = true) { setPixelColor(i, uint32_t(c) & 0x00FFFFFF, aa); } uint32_t __attribute__((pure)) getPixelColor(int i) const; // WLEDMM attribute added // 1D support functions (some implement 2D as well) void blur(uint8_t, bool smear = false); @@ -689,10 +689,10 @@ typedef struct Segment { void fade_out(uint8_t r); void fadeToBlackBy(uint8_t fadeBy); void blendPixelColor(int n, uint32_t color, uint8_t blend); - inline void blendPixelColor(int n, CRGB c, uint8_t blend) { blendPixelColor(n, RGBW32(c.r,c.g,c.b,0), blend); } + inline void blendPixelColor(int n, CRGB c, uint8_t blend) { blendPixelColor(n, uint32_t(c) & 0x00FFFFFF, blend); } void addPixelColor(int n, uint32_t color, bool fast = false); inline void addPixelColor(int n, byte r, byte g, byte b, byte w = 0, bool fast = false) { addPixelColor(n, RGBW32(r,g,b,w), fast); } // automatically inline - inline void addPixelColor(int n, CRGB c, bool fast = false) { addPixelColor(n, RGBW32(c.r,c.g,c.b,0), fast); } // automatically inline + inline void addPixelColor(int n, CRGB c, bool fast = false) { addPixelColor(n, uint32_t(c) & 0x00FFFFFF, fast); } // automatically inline void fadePixelColor(uint16_t n, uint8_t fade); uint8_t get_random_wheel_index(uint8_t pos) const; uint32_t __attribute__((pure)) color_from_palette(uint_fast16_t, bool mapping, bool wrap, uint8_t mcol, uint8_t pbri = 255); @@ -784,21 +784,21 @@ typedef struct Segment { #endif inline void setPixelColorXY(unsigned x, unsigned y, uint32_t c) { setPixelColorXY(int(x), int(y), c); } inline void setPixelColorXY(int x, int y, byte r, byte g, byte b, byte w = 0) { setPixelColorXY(x, y, RGBW32(r,g,b,w)); } - inline void setPixelColorXY(int x, int y, CRGB c) { setPixelColorXY(x, y, RGBW32(c.r,c.g,c.b,0)); } - inline void setPixelColorXY(unsigned x, unsigned y, CRGB c) { setPixelColorXY(int(x), int(y), RGBW32(c.r,c.g,c.b,0)); } + inline void setPixelColorXY(int x, int y, CRGB c) { setPixelColorXY(x, y, uint32_t(c) & 0x00FFFFFF); } + inline void setPixelColorXY(unsigned x, unsigned y, CRGB c) { setPixelColorXY(int(x), int(y), uint32_t(c) & 0x00FFFFFF); } //#ifdef WLED_USE_AA_PIXELS void setPixelColorXY(float x, float y, uint32_t c, bool aa = true, bool fast=true); inline void setPixelColorXY(float x, float y, byte r, byte g, byte b, byte w = 0, bool aa = true) { setPixelColorXY(x, y, RGBW32(r,g,b,w), aa); } - inline void setPixelColorXY(float x, float y, CRGB c, bool aa = true) { setPixelColorXY(x, y, RGBW32(c.r,c.g,c.b,0), aa); } + inline void setPixelColorXY(float x, float y, CRGB c, bool aa = true) { setPixelColorXY(x, y, uint32_t(c) & 0x00FFFFFF, aa); } //#endif uint32_t __attribute__((pure)) getPixelColorXY_part2(int x, int y, int cols, int rows) const; uint32_t __attribute__((pure)) getPixelColorXY_slow(int x, int y) const; // 2D support functions void blendPixelColorXY(uint16_t x, uint16_t y, uint32_t color, uint8_t blend); - inline void blendPixelColorXY(uint16_t x, uint16_t y, CRGB c, uint8_t blend) { blendPixelColorXY(x, y, RGBW32(c.r,c.g,c.b,0), blend); } + inline void blendPixelColorXY(uint16_t x, uint16_t y, CRGB c, uint8_t blend) { blendPixelColorXY(x, y, uint32_t(c) & 0x00FFFFFF, blend); } void addPixelColorXY(int x, int y, uint32_t color, bool fast = false); inline void addPixelColorXY(int x, int y, byte r, byte g, byte b, byte w = 0, bool fast = false) { addPixelColorXY(x, y, RGBW32(r,g,b,w), fast); } // automatically inline - inline void addPixelColorXY(int x, int y, CRGB c, bool fast = false) { addPixelColorXY(x, y, RGBW32(c.r,c.g,c.b,0), fast); } + inline void addPixelColorXY(int x, int y, CRGB c, bool fast = false) { addPixelColorXY(x, y, uint32_t(c) & 0x00FFFFFF, fast); } void fadePixelColorXY(uint16_t x, uint16_t y, uint8_t fade); void box_blur(uint16_t i, bool vertical, fract8 blur_amount); // 1D box blur (with weight) void blurRow(uint32_t row, fract8 blur_amount, bool smear = false); @@ -807,19 +807,19 @@ typedef struct Segment { void moveY(int8_t delta, bool wrap = false); void move(uint8_t dir, uint8_t delta, bool wrap = false); void drawCircle(uint16_t cx, uint16_t cy, uint8_t radius, uint32_t c, bool soft = false); - inline void drawCircle(uint16_t cx, uint16_t cy, uint8_t radius, CRGB c, bool soft = false) { drawCircle(cx, cy, radius, RGBW32(c.r,c.g,c.b,0), soft); } + inline void drawCircle(uint16_t cx, uint16_t cy, uint8_t radius, CRGB c, bool soft = false) { drawCircle(cx, cy, radius, uint32_t(c) & 0x00FFFFFF, soft); } void fillCircle(unsigned cx, unsigned cy, int radius, uint32_t col, bool soft); - inline void fillCircle(unsigned cx, unsigned cy, int radius, CRGB c, bool soft = false) { fillCircle(cx, cy, radius, RGBW32(c.r,c.g,c.b,0), soft); } + inline void fillCircle(unsigned cx, unsigned cy, int radius, CRGB c, bool soft = false) { fillCircle(cx, cy, radius, uint32_t(c) & 0x00FFFFFF, soft); } void drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint32_t c, bool soft = false, uint8_t depth = UINT8_MAX); - inline void drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, CRGB c, bool soft = false, uint8_t depth = UINT8_MAX) { drawLine(x0, y0, x1, y1, RGBW32(c.r,c.g,c.b,0), soft, depth); } // automatic inline + inline void drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, CRGB c, bool soft = false, uint8_t depth = UINT8_MAX) { drawLine(x0, y0, x1, y1, uint32_t(c) & 0x00FFFFFF, soft, depth); } // automatic inline void drawArc(unsigned x0, unsigned y0, int radius, uint32_t color, uint32_t fillColor = 0); - inline void drawArc(unsigned x0, unsigned y0, int radius, CRGB color, CRGB fillColor = BLACK) { drawArc(x0, y0, radius, RGBW32(color.r,color.g,color.b,0), RGBW32(fillColor.r,fillColor.g,fillColor.b,0)); } // automatic inline + inline void drawArc(unsigned x0, unsigned y0, int radius, CRGB color, CRGB fillColor = BLACK) { drawArc(x0, y0, radius, uint32_t(color) & 0x00FFFFFF, uint32_t(fillColor) & 0x00FFFFFF); } // automatic inline void drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, uint8_t h, uint32_t color, uint32_t col2 = 0, bool drawShadow = false); - inline void drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, uint8_t h, CRGB c, CRGB c2) { drawCharacter(chr, x, y, w, h, RGBW32(c.r,c.g,c.b,0), RGBW32(c2.r,c2.g,c2.b,0)); } // automatic inline + inline void drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, uint8_t h, CRGB c, CRGB c2) { drawCharacter(chr, x, y, w, h, uint32_t(c) & 0x00FFFFFF, uint32_t(c2) & 0x00FFFFFF); } // automatic inline void wu_pixel(uint32_t x, uint32_t y, CRGB c); //void blur1d(fract8 blur_amount); // blur all rows in 1 dimension void blur2d(fract8 blur_amount) { blur(blur_amount); } - inline void fill_solid(CRGB c) { fill(RGBW32(c.r,c.g,c.b,0)); } + inline void fill_solid(CRGB c) { fill(uint32_t(c) & 0x00FFFFFF); } void nscale8(uint8_t scale); bool jsonToPixels(char *name, uint8_t fileNr); //WLEDMM for artifx #else @@ -827,19 +827,19 @@ typedef struct Segment { inline void setPixelColorXY(int x, int y, uint32_t c) { setPixelColor(x, c); } inline void setPixelColorXY(unsigned x, unsigned y, uint32_t c) { setPixelColor(int(x), c); } inline void setPixelColorXY(int x, int y, byte r, byte g, byte b, byte w = 0) { setPixelColor(x, RGBW32(r,g,b,w)); } - inline void setPixelColorXY(int x, int y, CRGB c) { setPixelColor(x, RGBW32(c.r,c.g,c.b,0)); } - inline void setPixelColorXY(unsigned x, unsigned y, CRGB c) { setPixelColor(int(x), RGBW32(c.r,c.g,c.b,0)); } + inline void setPixelColorXY(int x, int y, CRGB c) { setPixelColor(x, uint32_t(c) & 0x00FFFFFF); } + inline void setPixelColorXY(unsigned x, unsigned y, CRGB c) { setPixelColor(int(x), uint32_t(c) & 0x00FFFFFF); } //#ifdef WLED_USE_AA_PIXELS inline void setPixelColorXY(float x, float y, uint32_t c, bool aa = true) { setPixelColor(x, c, aa); } inline void setPixelColorXY(float x, float y, byte r, byte g, byte b, byte w = 0, bool aa = true) { setPixelColor(x, RGBW32(r,g,b,w), aa); } - inline void setPixelColorXY(float x, float y, CRGB c, bool aa = true) { setPixelColor(x, RGBW32(c.r,c.g,c.b,0), aa); } + inline void setPixelColorXY(float x, float y, CRGB c, bool aa = true) { setPixelColor(x, uint32_t(c) & 0x00FFFFFF, aa); } //#endif inline uint32_t getPixelColorXY(uint16_t x, uint16_t y) { return getPixelColor(x); } inline void blendPixelColorXY(uint16_t x, uint16_t y, uint32_t c, uint8_t blend) { blendPixelColor(x, c, blend); } - inline void blendPixelColorXY(uint16_t x, uint16_t y, CRGB c, uint8_t blend) { blendPixelColor(x, RGBW32(c.r,c.g,c.b,0), blend); } + inline void blendPixelColorXY(uint16_t x, uint16_t y, CRGB c, uint8_t blend) { blendPixelColor(x, uint32_t(c) & 0x00FFFFFF, blend); } inline void addPixelColorXY(int x, int y, uint32_t color, bool fast = false) { addPixelColor(x, color, fast); } inline void addPixelColorXY(int x, int y, byte r, byte g, byte b, byte w = 0, bool fast = false) { addPixelColor(x, RGBW32(r,g,b,w), fast); } - inline void addPixelColorXY(int x, int y, CRGB c, bool fast = false) { addPixelColor(x, RGBW32(c.r,c.g,c.b,0), fast); } + inline void addPixelColorXY(int x, int y, CRGB c, bool fast = false) { addPixelColor(x, uint32_t(c) & 0x00FFFFFF, fast); } inline void fadePixelColorXY(uint16_t x, uint16_t y, uint8_t fade) { fadePixelColor(x, fade); } inline void box_blur(uint16_t i, bool vertical, fract8 blur_amount) {} inline void blurRow(uint32_t row, fract8 blur_amount, bool smear = false) {} @@ -973,7 +973,7 @@ class WS2812FX { // 96 bytes // outsmart the compiler :) by correctly overloading inline void setPixelColor(int n, uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0) const { setPixelColor(n, RGBW32(r,g,b,w)); } - inline void setPixelColor(int n, CRGB c) const { setPixelColor(n, c.red, c.green, c.blue); } + inline void setPixelColor(int n, CRGB c) const { setPixelColor(n, uint32_t(c) & 0x00FFFFFF); } inline void trigger(void) { _triggered = true; } // Forces the next frame to be computed on all active segments. inline void setShowCallback(show_callback cb) { _callback = cb; } inline void setTransition(uint16_t t) { _transitionDur = t; } @@ -1178,7 +1178,7 @@ class WS2812FX { // 96 bytes // outsmart the compiler :) by correctly overloading inline void setPixelColorXY(int x, int y, byte r, byte g, byte b, byte w = 0) const { setPixelColorXY(x, y, RGBW32(r,g,b,w)); } // automatically inline - inline void setPixelColorXY(int x, int y, CRGB c) const { setPixelColorXY(x, y, RGBW32(c.r,c.g,c.b,0)); } + inline void setPixelColorXY(int x, int y, CRGB c) const { setPixelColorXY(x, y, uint32_t(c) & 0x00FFFFFF); } // end 2D support From 0510fd308f9f7605007c994c3a3bda9b91108b64 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sun, 2 Nov 2025 16:33:10 +0100 Subject: [PATCH 043/170] HUB75: small delay at cleanup, to ensure that DMA finishes before deleting the driver based on a suggestion by @DedeHai --- wled00/bus_manager.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/wled00/bus_manager.cpp b/wled00/bus_manager.cpp index d2404915..a9b479b2 100644 --- a/wled00/bus_manager.cpp +++ b/wled00/bus_manager.cpp @@ -1174,6 +1174,7 @@ void BusHub75Matrix::cleanup() { #else USER_PRINTLN("HUB75 output paused."); #endif + delay(30); // give some time to finish DMA _valid = false; deallocatePins(); From d9e542663634812e9136b66bd1d53f187979d33a Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sun, 2 Nov 2025 16:38:03 +0100 Subject: [PATCH 044/170] HUB75: small correction of order first set _valid=false, then perform delay. --- wled00/bus_manager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wled00/bus_manager.cpp b/wled00/bus_manager.cpp index a9b479b2..eaa46caa 100644 --- a/wled00/bus_manager.cpp +++ b/wled00/bus_manager.cpp @@ -1174,9 +1174,9 @@ void BusHub75Matrix::cleanup() { #else USER_PRINTLN("HUB75 output paused."); #endif - delay(30); // give some time to finish DMA _valid = false; + delay(30); // give some time to finish DMA deallocatePins(); _len = 0; //if (fourScanPanel != nullptr) delete fourScanPanel; // warning: deleting object of polymorphic class type 'VirtualMatrixPanel' which has non-virtual destructor might cause undefined behavior From 2c62cd5e4118d3e96b735826c6251fb888839d67 Mon Sep 17 00:00:00 2001 From: netmindz Date: Sat, 14 Jun 2025 21:17:01 +0100 Subject: [PATCH 045/170] Merge pull request #4690 from Arcitec/ar-agc-control AR: add compile-time flag for "Automatic Gain Control" option --- usermods/audioreactive/audio_reactive.h | 14 +++++++++----- usermods/audioreactive/readme.md | 5 +++-- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/usermods/audioreactive/audio_reactive.h b/usermods/audioreactive/audio_reactive.h index cf34b547..406ae316 100644 --- a/usermods/audioreactive/audio_reactive.h +++ b/usermods/audioreactive/audio_reactive.h @@ -136,15 +136,19 @@ static bool udpSyncConnected = false; // UDP connection status -> true i // audioreactive variables #ifdef ARDUINO_ARCH_ESP32 +#ifndef SR_AGC // Automatic gain control mode + #ifdef SR_SQUELCH + #define SR_AGC 1 // default "squelch" was provided --> default mode = on + #else + #define SR_AGC 0 // default mode = off + #endif +#endif + static float micDataReal = 0.0f; // MicIn data with full 24bit resolution - lowest 8bit after decimal point static float multAgc = 1.0f; // sample * multAgc = sampleAgc. Our AGC multiplier static float sampleAvg = 0.0f; // Smoothed Average sample - sampleAvg < 1 means "quiet" (simple noise gate) static float sampleAgc = 0.0f; // Smoothed AGC sample -#ifdef SR_SQUELCH -static uint8_t soundAgc = 1; // Automagic gain control: 0 - none, 1 - normal, 2 - vivid, 3 - lazy (config value) - enable AGC if default "squelch" was provided -#else -static uint8_t soundAgc = 0; // Automagic gain control: 0 - none, 1 - normal, 2 - vivid, 3 - lazy (config value) -#endif +static uint8_t soundAgc = SR_AGC; // Automagic gain control: 0 - none, 1 - normal, 2 - vivid, 3 - lazy (config value) - enable AGC if default "squelch" was provided #endif static float volumeSmth = 0.0f; // either sampleAvg or sampleAgc depending on soundAgc; smoothed sample diff --git a/usermods/audioreactive/readme.md b/usermods/audioreactive/readme.md index a80fa681..2054d6b5 100644 --- a/usermods/audioreactive/readme.md +++ b/usermods/audioreactive/readme.md @@ -58,9 +58,10 @@ Other options: You can use the following additional flags in your `build_flags` * `-D SR_SQUELCH=x` : Default "squelch" setting (10) * `-D SR_GAIN=x` : Default "gain" setting (60) +* `-D SR_AGC=x` : (Only ESP32) Default "AGC (Automatic Gain Control)" setting (0): 0=off, 1=normal, 2=vivid, 3=lazy * `-D I2S_USE_RIGHT_CHANNEL`: Use RIGHT instead of LEFT channel (not recommended unless you strictly need this). -* `-D I2S_USE_16BIT_SAMPLES`: Use 16bit instead of 32bit for internal sample buffers. Reduces sampling quality, but frees some RAM ressources (not recommended unless you absolutely need this). -* `-D I2S_GRAB_ADC1_COMPLETELY`: Experimental: continuously sample analog ADC microphone. Only effective on ESP32. WARNING this _will_ cause conflicts(lock-up) with any analogRead() call. +* `-D I2S_USE_16BIT_SAMPLES`: Use 16bit instead of 32bit for internal sample buffers. Reduces sampling quality, but frees some RAM resources (not recommended unless you absolutely need this). +* `-D I2S_GRAB_ADC1_COMPLETELY`: Experimental: continuously sample analog ADC microphone. Only effective on ESP32. WARNING this *will* cause conflicts(lock-up) with any analogRead() call. * `-D MIC_LOGGER` : (debugging) Logs samples from the microphone to serial USB. Use with serial plotter (Arduino IDE) * `-D SR_DEBUG` : (debugging) Additional error diagnostics and debug info on serial USB. From 69f9499e257929ae4837f72d1e13ffe0e9c9e9b7 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Tue, 4 Nov 2025 16:39:02 +0100 Subject: [PATCH 046/170] CSS bugfix: #pql and #rgbwrap should be hidden initially a missing comma caused unexpected UI behaviour in some corner cases. --- wled00/data/index.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wled00/data/index.css b/wled00/data/index.css index deb0cc64..1c3a08c5 100644 --- a/wled00/data/index.css +++ b/wled00/data/index.css @@ -707,7 +707,7 @@ img { #wbal .sliderdisplay { background: linear-gradient(90deg, #ff8f1f 0%, #fff 50%, #cbdbff); } /* wrapper divs hidden by default */ -#liveview, #liveview2D, #roverstar, #pql +#liveview, #liveview2D, #roverstar, #pql, #rgbwrap, #swrap, #hwrap, #kwrap, #wwrap, #wbal, #qcs-w, #hexw, .clear-icon, .edit-icon, .ptxt { display: none; From bb44dd861634a980a2988c6c910bc3efda08e562 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Tue, 4 Nov 2025 20:28:26 +0100 Subject: [PATCH 047/170] robustness improvements for image presets prevent errors / crashes when drawing "i" images from a preset. - prevent out-of-bounds writing (segment smaller than image) - make sure that segment properties are cached correctly - always do "show" when strip was triggered (avoids lost frames) --- wled00/FX_2Dfcn.cpp | 4 ++-- wled00/FX_fcn.cpp | 7 ++++--- wled00/json.cpp | 10 +++++++++- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/wled00/FX_2Dfcn.cpp b/wled00/FX_2Dfcn.cpp index a8545113..9491e134 100644 --- a/wled00/FX_2Dfcn.cpp +++ b/wled00/FX_2Dfcn.cpp @@ -249,7 +249,7 @@ void IRAM_ATTR __attribute__((hot)) Segment::setPixelColorXY_fast(int x, int y, } #if 0 // this is still a dangerous optimization - if ((i < UINT_MAX) && sameColor && (call > 0) && (!transitional) && (mode != FX_MODE_2DSCROLLTEXT) && (ledsrgb[i] == CRGB(scaled_col))) return; // WLEDMM looks like nothing to do + if ((i < UINT_MAX) && sameColor && (call > 0) && (!transitional) && (!freeze) && (mode != FX_MODE_2DSCROLLTEXT) && (ledsrgb[i] == CRGB(scaled_col))) return; // WLEDMM looks like nothing to do #endif // handle reverse and transpose @@ -311,7 +311,7 @@ void IRAM_ATTR_YN Segment::setPixelColorXY(int x, int y, uint32_t col) //WLEDMM: } #if 0 // this is a dangerous optimization - if ((i < UINT_MAX) && sameColor && (call > 0) && (!transitional) && (mode != FX_MODE_2DSCROLLTEXT) && (ledsrgb[i] == CRGB(col))) return; // WLEDMM looks like nothing to do + if ((i < UINT_MAX) && sameColor && (call > 0) && (!transitional) && (!freeze) && (mode != FX_MODE_2DSCROLLTEXT) && (ledsrgb[i] == CRGB(col))) return; // WLEDMM looks like nothing to do #endif if (reverse ) x = cols - x - 1; diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index eb0c97e8..75d7c828 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -945,8 +945,7 @@ void IRAM_ATTR_YN WLED_O2_ATTR __attribute__((hot)) Segment::setPixelColor(int i int vStrip = i>>16; // hack to allow running on virtual strips (2D segment columns/rows) #endif i &= 0xFFFF; - - if (i >= virtualLength() || i<0) return; // if pixel would fall out of segment just exit + if (unsigned(i) >= virtualLength()) return; // if pixel would fall out of segment just exit //WLEDMM unsigned(i)>SEGLEN also catches "i<0" #ifndef WLED_DISABLE_2D if (is2D()) { @@ -1914,7 +1913,7 @@ void WS2812FX::service() { if(nowUp >= seg.next_time || _triggered || (doShow && seg.mode == FX_MODE_STATIC)) // WLEDMM ">=" instead of ">" { if (seg.grouping == 0) seg.grouping = 1; //sanity check - if (!seg.freeze) doShow = true; + if ((!seg.freeze) || _triggered) doShow = true; // WLEDMM "triggered" overrules "freeze" uint16_t frameDelay = FRAMETIME; // WLEDMM avoid name clash with "delay" function if (!seg.freeze) { //only run effect function if not frozen @@ -1950,6 +1949,8 @@ void WS2812FX::service() { } _segment_index++; } + if (_triggered) doShow = true; // WLEDMM "triggered" always means "show" + _virtualSegmentLength = 0; busses.setSegmentCCT(-1); if(doShow) { diff --git a/wled00/json.cpp b/wled00/json.cpp index c51deefa..f9f9f5c4 100644 --- a/wled00/json.cpp +++ b/wled00/json.cpp @@ -329,6 +329,8 @@ bool deserializeSegment(JsonObject elem, byte it, byte presetId) uint8_t oldMap1D2D = seg.map1D2D; seg.map1D2D = M12_Pixels; // no mapping // WLEDMM begin - we need to init segment caches before putting any pixels + auto oldLock = suspendStripService; // remember pevious lock status + suspendStripService = true; if (strip.isServicing()) { USER_PRINTLN(F("deserializeSegment() image: strip is still drawing effects.")); strip.waitUntilIdle(); @@ -350,6 +352,8 @@ bool deserializeSegment(JsonObject elem, byte it, byte presetId) start = 0, stop = 0; set = 0; //0 nothing set, 1 start set, 2 range set + seg.startFrame(); // WLEDMM do it again, to be sure that all segment properties get cached + unsigned seg_len = seg.calc_virtualLength(); // WLEDMM prevent out-of-bounds writing for (size_t i = 0; i < iarr.size(); i++) { if(iarr[i].is()) { if (!set) { @@ -375,12 +379,16 @@ bool deserializeSegment(JsonObject elem, byte it, byte presetId) if (set < 2 || stop <= start) stop = start + 1; uint32_t c = gamma32(RGBW32(rgbw[0], rgbw[1], rgbw[2], rgbw[3])); - while (start < stop) seg.setPixelColor(start++, c); + while (start < stop) { + if (unsigned(start) < seg_len) seg.setPixelColor(start, c); // WLEDMM don't write out-of-bounds + start++; + } set = 0; } } seg.map1D2D = oldMap1D2D; // restore mapping strip.trigger(); // force segment update + suspendStripService = oldLock; // restore previous lock status } // send UDP/WS if segment options changed (except selection; will also deselect current preset) uint8_t diffresult = seg.differs(prev) & 0x7F; From 5122a80f503870246def3c084ca1499ab7490b64 Mon Sep 17 00:00:00 2001 From: MoonModules <91013628+MoonModules@users.noreply.github.com> Date: Wed, 5 Nov 2025 09:55:50 +0100 Subject: [PATCH 048/170] Fix typo in disclaimer about liability --- readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.md b/readme.md index 37258c3e..4323fe7e 100644 --- a/readme.md +++ b/readme.md @@ -33,4 +33,4 @@ We welcome contributions to this project! See [contributing](https://github.com/ ## *Disclaimer:* -Using this software is the users responsibility as it is not bug free. Therefore contributors of this repo are not reliable for anything including but not limited to spontaneous combustion of the entire led strip, the house and the inevitable heat death of the universe +Using this software is the users responsibility as it is not bug free. Therefore contributors of this repo are not liable for anything including but not limited to spontaneous combustion of the entire led strip, the house and the inevitable heat death of the universe From a956b22a166d80ef5a98662037b3c92f8adb4239 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Wed, 5 Nov 2025 22:01:07 +0100 Subject: [PATCH 049/170] unGamma8() accuracy improvement based on upstream changes by @DedeHai --- wled00/colors.cpp | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/wled00/colors.cpp b/wled00/colors.cpp index f1bbea0a..69846272 100644 --- a/wled00/colors.cpp +++ b/wled00/colors.cpp @@ -441,19 +441,20 @@ static void calcInvGammaTable(float gamma) { float gammaInv = 1.0f / 2.4f; // surprise surprise: WLED palettes use a fixed gamma of 2.4 !!! //float gammaInv = 1.0f / gamma; // if we go by the book, 1.0/gamma will revert gamma corrections - for (size_t i = 0; i < 256; i++) { - gammaTinv[i] = (int)(powf((float)i / 255.0f, gammaInv) * 255.0f + 0.5f); + for (size_t i = 1; i < 256; i++) { + gammaTinv[i] = (int)(powf(((float)i - 0.5f) / 255.0f, gammaInv) * 255.0f + 0.5f); // improved by @dedehai } + gammaTinv[0]=0; + gammaTinv[255]=255; } -uint8_t __attribute__((hot)) unGamma8(uint8_t value) { +IRAM_ATTR_YN uint8_t __attribute__((hot)) unGamma8(uint8_t value) { //if (!gammaCorrectCol || (value == 0) || (value == 255)) return value; - if ((value == 0) || (value == 255)) return value; if ((gammaCorrectVal < 0.999f) || (gammaCorrectVal > 3.0f)) return value; if (gammaTinv[255] == 0) calcInvGammaTable(gammaCorrectVal); return gammaTinv[value]; } -uint32_t __attribute__((hot)) unGamma24(uint32_t c) { +IRAM_ATTR_YN uint32_t __attribute__((hot)) unGamma24(uint32_t c) { if ((gammaCorrectVal < 0.999f) || (gammaCorrectVal > 3.0f)) return c; if (gammaTinv[255] == 0) calcInvGammaTable(gammaCorrectVal); return RGBW32(gammaTinv[R(c)], gammaTinv[G(c)], gammaTinv[B(c)], W(c)); @@ -462,6 +463,8 @@ uint32_t __attribute__((hot)) unGamma24(uint32_t c) { uint8_t gamma8_cal(uint8_t b, float gamma) { + if (b==0) return 0; + if (b==255) return 255; return (int)(powf((float)b / 255.0f, gamma) * 255.0f + 0.5f); } @@ -469,9 +472,11 @@ uint8_t gamma8_cal(uint8_t b, float gamma) void calcGammaTable(float gamma) { #if !defined(WLED_USE_CIE_BRIGHTNESS_TABLE) // WLEDMM not possible when using the CIE table - for (uint16_t i = 0; i < 256; i++) { + for (uint16_t i = 1; i < 256; i++) { gammaT[i] = gamma8_cal(i, gamma); } + gammaT[0]=0; + gammaT[255]=255; #endif calcInvGammaTable(gamma); // WLEDMM } From 5177ebd271147f1befce8c00b8a732eceff8034b Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Thu, 6 Nov 2025 22:09:11 +0100 Subject: [PATCH 050/170] fix false warnings when temporarily exceeding MAX_SEGMENT_DATA The segment copy constructors can temporarily exceed the budget of MAX_SEGMENT_DATA. The original segment will be de-allocated a few milliseconds later. This change introduced an "overdraft" budget of 50% that can be used for temporary segment copies. --- wled00/FX.h | 6 ++++-- wled00/FX_fcn.cpp | 32 ++++++++++++++++++++++---------- 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/wled00/FX.h b/wled00/FX.h index c52c8869..32086c50 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -87,6 +87,8 @@ extern BusManager busses; // same as wled.h #endif #endif +#define MAX_SEGMENT_OVERDATA ((MAX_SEGMENT_DATA) + (MAX_SEGMENT_DATA)/2) // WLEDMM 50% extra overdraft budget + /* How much data bytes each segment should max allocate to leave enough space for other segments, assuming each segment uses the same amount of data. 256 for ESP8266, 640 for ESP32. */ #define FAIR_DATA_PER_SEG (MAX_SEGMENT_DATA / strip.getMaxSegments()) @@ -611,7 +613,7 @@ typedef struct Segment { inline uint8_t getLightCapabilities(void) const { return _capabilities; } static size_t getUsedSegmentData(void) { return _usedSegmentData; } // WLEDMM size_t - static void addUsedSegmentData(int len) { _usedSegmentData += len; } + static void addUsedSegmentData(int len) { _usedSegmentData = max(0, int(_usedSegmentData + len)); } // WLEDMM prevent negative alloc void allocLeds(); //WLEDMM inline static const CRGBPalette16 &getCurrentPalette(void) { return Segment::_currentPalette; } @@ -628,7 +630,7 @@ typedef struct Segment { // runtime data functions inline size_t dataSize(void) const { return _dataLen; } - bool allocateData(size_t len); + bool allocateData(size_t len, bool allowOverdraft = false); void deallocateData(void); void resetIfRequired(void); void startFrame(void); // cache a few values that don't change while an effect is drawing diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index 75d7c828..34b77f1f 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -94,7 +94,7 @@ Segment::Segment(const Segment &orig) { _t = nullptr; if (ledsrgb && !Segment::_globalLeds) {ledsrgb = nullptr; ledsrgbSize = 0;} // WLEDMM if (orig.name) { name = new(std::nothrow) char[strlen(orig.name)+1]; if (name) strcpy(name, orig.name); } - if (orig.data) { if (allocateData(orig._dataLen)) memcpy(data, orig.data, orig._dataLen); } + if (orig.data) { if (allocateData(orig._dataLen, true)) memcpy(data, orig.data, orig._dataLen); } //if (orig._t) { _t = new(std::nothrow) Transition(orig._t->_dur, orig._t->_briT, orig._t->_cctT, orig._t->_colorT); } //else markForReset(); // WLEDMM // if (orig.ledsrgb && !Segment::_globalLeds) { allocLeds(); if (ledsrgb) memcpy(ledsrgb, orig.ledsrgb, sizeof(CRGB)*length()); } // WLEDMM @@ -179,7 +179,7 @@ Segment& Segment::operator= (const Segment &orig) { if (!Segment::_globalLeds) {ledsrgb = nullptr; ledsrgbSize = 0;}; // WLEDMM copy has no buffers (yet) // copy source data if (orig.name) { name = new(std::nothrow) char[strlen(orig.name)+1]; if (name) strcpy(name, orig.name); } - if (orig.data) { if (allocateData(orig._dataLen)) memcpy(data, orig.data, orig._dataLen); } + if (orig.data) { if (allocateData(orig._dataLen, true)) memcpy(data, orig.data, orig._dataLen); } //if (orig._t) { _t = new(std::nothrow) Transition(orig._t->_dur, orig._t->_briT, orig._t->_cctT, orig._t->_colorT); } //else markForReset(); // WLEDMM //if (orig.ledsrgb && !Segment::_globalLeds) { allocLeds(); if (ledsrgb) memcpy(ledsrgb, orig.ledsrgb, sizeof(CRGB)*length()); } // WLEDMM don't copy old buffer @@ -218,7 +218,7 @@ Segment& Segment::operator= (Segment &&orig) noexcept { return *this; } -bool Segment::allocateData(size_t len) { +bool Segment::allocateData(size_t len, bool allowOverdraft) { // WLEDMM allowOverdraft for temporary overdraft by segment copy constructor // WLEDMM if (data && _dataLen >= len) { // already allocated enough (reduce fragmentation) if ((call == 0) && (len > 0)) memset(data, 0, len); // erase buffer if called during effect initialisation @@ -228,9 +228,11 @@ bool Segment::allocateData(size_t len) { deallocateData(); if (len == 0) return false; // nothing to do if (Segment::getUsedSegmentData() + len > MAX_SEGMENT_DATA) { - //USER_PRINTF("Segment::allocateData: Segment data quota exceeded! used:%u request:%u max:%d\n", Segment::getUsedSegmentData(), len, MAX_SEGMENT_DATA); - if (len > 0) errorFlag = ERR_LOW_SEG_MEM; // WLEDMM raise errorflag - return false; //not enough memory + if (!allowOverdraft || (Segment::getUsedSegmentData() + len > MAX_SEGMENT_OVERDATA)) { // WLEDMM 50% overdraft allowed temporarily + //USER_PRINTF("Segment::allocateData: Segment data quota exceeded! used:%u request:%u max:%d\n", Segment::getUsedSegmentData(), len, MAX_SEGMENT_DATA); + if (len > 0) errorFlag = ERR_LOW_SEG_MEM; // WLEDMM raise errorflag + return false; //not enough memory + } } // do not use SPI RAM on ESP32 since it is slow //#if defined(ARDUINO_ARCH_ESP32) && defined(BOARD_HAS_PSRAM) && defined(WLED_USE_PSRAM) @@ -241,12 +243,15 @@ bool Segment::allocateData(size_t len) { data = (byte*) malloc(len); if (!data) { _dataLen = 0; // WLEDMM reset dataLen + if ((errorFlag != ERR_LOW_MEM) && (errorFlag != ERR_LOW_SEG_MEM)) { // spam filter + USER_PRINT(F("Segment::allocateData: FAILED to allocate ")); + USER_PRINT(len); USER_PRINTLN(F(" bytes.")); + } errorFlag = ERR_LOW_MEM; // WLEDMM raise errorflag - USER_PRINT(F("Segment::allocateData: FAILED to allocate ")); - USER_PRINT(len); USER_PRINTLN(F(" bytes.")); return false; } //allocation failed Segment::addUsedSegmentData(len); + DEBUG_PRINTF("Segment::allocateData: %u bytes allocated (%u used)\n", len, Segment::getUsedSegmentData()); _dataLen = len; memset(data, 0, len); if ((errorFlag == ERR_LOW_SEG_MEM) || (errorFlag == ERR_LOW_MEM) || (errorFlag == ERR_NORAM_PX)) errorFlag = ERR_NONE; // WLEDMM reset errorflag on success @@ -254,10 +259,17 @@ bool Segment::allocateData(size_t len) { } void Segment::deallocateData() { - if (!data) {_dataLen = 0; return;} // WLEDMM reset dataLen + if (!data) { + if (_dataLen>0) { + Segment::addUsedSegmentData(-_dataLen); // WLEDMM fix housekeeping + DEBUG_PRINTF("Segment::deallocateData unregistering %u bytes as unused.", _dataLen); + } + _dataLen = 0; + return; + } // WLEDMM reset dataLen free(data); data = nullptr; - //USER_PRINTF("Segment::deallocateData: free'd %d bytes.\n", _dataLen); + DEBUG_PRINTF("Segment::deallocateData: free'd %d bytes.\n", _dataLen); Segment::addUsedSegmentData(-_dataLen); _dataLen = 0; } From 10b3ac0eb1e72c932b8b753bfcfdbec5b609c8e7 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Thu, 6 Nov 2025 22:50:59 +0100 Subject: [PATCH 051/170] gifdecoder speedup and bugfixes * fixed a bug that caused wrong behavior with segment mirroring (effects must use virtualHeight() / virtualWidth() instead of height() / width()) * added image blur as an option (second slider) * added very basic error reporting for users * up to 25% faster, especially with big animated gifs * made all local variables "static" (don't pollute global namespace) * drawPixelCallback: cache calculation that do not depend on x/y position * reduced memory allocations on boards without PSRAM, to avoid crashes --- wled00/FX.cpp | 4 +- wled00/image_loader.cpp | 87 +++++++++++++++++++++++++++++++---------- 2 files changed, 70 insertions(+), 21 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index f25de8c4..e9d8c01e 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -4693,9 +4693,11 @@ static const char _data_FX_MODE_WASHING_MACHINE[] PROGMEM = "Washing Machine@!,! Draws a .gif image from filesystem on the matrix/strip */ uint16_t mode_image(void) { + if (!strip.isMatrix) return mode_oops(); // not a 2D set-up #ifndef WLED_ENABLE_GIF return mode_oops(); #else + if (max(SEGMENT.virtualWidth(),SEGMENT.virtualHeight()) < 4) return mode_oops(); // too small renderImageToSegment(SEGMENT); return FRAMETIME; #endif @@ -4704,7 +4706,7 @@ uint16_t mode_image(void) { // Serial.println(status); // } } -static const char _data_FX_MODE_IMAGE[] PROGMEM = "Image@!,;;;12;sx=128"; +static const char _data_FX_MODE_IMAGE[] PROGMEM = "Image@!,Blur,;;;12;sx=128,ix=0"; /* Blends random colors across palette diff --git a/wled00/image_loader.cpp b/wled00/image_loader.cpp index 2bb465f9..ef283956 100644 --- a/wled00/image_loader.cpp +++ b/wled00/image_loader.cpp @@ -9,11 +9,15 @@ * Functions to render images from filesystem to segments, used by the "Image" effect */ -File file; -char lastFilename[34] = "/"; -GifDecoder<320,320,12,true> decoder; -bool gifDecodeFailed = false; -unsigned long lastFrameDisplayTime = 0, currentFrameDelay = 0; +static File file; +static char lastFilename[34] = "/"; +#if !defined(BOARD_HAS_PSRAM) + static GifDecoder<256,256,11,true> decoder; // WLEDMM use less RAM on boards without PSRAM - avoids crashes due to out-of-memory +#else + static GifDecoder<320,320,12,true> decoder; +#endif +static bool gifDecodeFailed = false; +static unsigned long lastFrameDisplayTime = 0, currentFrameDelay = 0; bool fileSeekCallback(unsigned long position) { return file.seek(position); @@ -35,29 +39,49 @@ int fileSizeCallback(void) { return file.size(); } -bool openGif(const char *filename) { +bool openGif(const char *filename) { // side-effect: updates "file" file = WLED_FS.open(filename, "r"); + DEBUG_PRINTF("opening GIF file %s\n", filename); if (!file) return false; return true; } -Segment* activeSeg; -uint16_t gifWidth, gifHeight; +static Segment* activeSeg; +static uint16_t gifWidth, gifHeight; // these two must stay uint16_t, because they are passed by reference +static unsigned seg_cols = 1; +static unsigned seg_rows = 1; +static int expandX = 1; +static int expandY = 1; +static int lastX = -1, lastY = -1; void screenClearCallback(void) { activeSeg->fill(0); } -void updateScreenCallback(void) {} - +void updateScreenCallback(void) { + // this callback runs when the decoder has finished painting all pixels + // perfect time for adding blur + if (activeSeg->intensity > 1) { + uint8_t blurAmount = activeSeg->intensity >> 2; + if ((blurAmount < 24) && (activeSeg->is2D())) activeSeg->blurRows(activeSeg->intensity >> 1); // some blur - fast + else activeSeg->blur(blurAmount); // more blur - slower + } + lastX = lastY = -1; // invalidate last position +} void drawPixelCallback(int16_t x, int16_t y, uint8_t red, uint8_t green, uint8_t blue) { - // simple nearest-neighbor scaling - int16_t outY = y * activeSeg->height() / gifHeight; - int16_t outX = x * activeSeg->width() / gifWidth; + // simple nearest-neighbor downscaling + int outY = y * seg_rows / gifHeight; + int outX = x * seg_cols / gifWidth; + + if ((unsigned(outX) >= seg_cols) || (unsigned(outY) >= seg_rows)) return; // out of range + if ((lastX == outX) && (lastY == outY)) return; // downscaling optimization: skip re-painting same pixel + lastX = outX; lastY = outY; + // set multiple pixels if upscaling - for (int16_t i = 0; i < (activeSeg->width()+(gifWidth-1)) / gifWidth; i++) { - for (int16_t j = 0; j < (activeSeg->height()+(gifHeight-1)) / gifHeight; j++) { + // softhack007: changed loop x/y order -> minor speedup from better cache locality + for (int j = 0; j < expandY; j++) { + for (int i = 0; i < expandX; i++) { activeSeg->setPixelColorXY(outX + i, outY + j, gamma8(red), gamma8(green), gamma8(blue)); } } @@ -81,17 +105,24 @@ byte renderImageToSegment(Segment &seg) { // TODO: if (seg.mode != seg.currentMode()) return IMAGE_ERROR_WAITING; if (activeSeg && activeSeg != &seg) return IMAGE_ERROR_SEG_LIMIT; // only one segment at a time activeSeg = &seg; + seg_cols = activeSeg->virtualWidth(); + seg_rows = activeSeg->virtualHeight(); if (strncmp(lastFilename +1, seg.name, 32) != 0) { // segment name changed, load new image strncpy(lastFilename +1, seg.name, 32); gifDecodeFailed = false; if (strcmp(lastFilename + strlen(lastFilename) - 4, ".gif") != 0) { gifDecodeFailed = true; + USER_PRINTF("Unsupported format: %s\n", lastFilename); return IMAGE_ERROR_UNSUPPORTED_FORMAT; } if (file) file.close(); - openGif(lastFilename); - if (!file) { gifDecodeFailed = true; return IMAGE_ERROR_FILE_MISSING; } + + if (!openGif(lastFilename)) { + gifDecodeFailed = true; + USER_PRINTF("GIF file not found: %s\n", lastFilename); + return IMAGE_ERROR_FILE_MISSING; + } decoder.setScreenClearCallback(screenClearCallback); decoder.setUpdateScreenCallback(updateScreenCallback); decoder.setDrawPixelCallback(drawPixelCallback); @@ -100,9 +131,18 @@ byte renderImageToSegment(Segment &seg) { decoder.setFileReadCallback(fileReadCallback); decoder.setFileReadBlockCallback(fileReadBlockCallback); decoder.setFileSizeCallback(fileSizeCallback); - decoder.alloc(); + decoder.alloc(); // WLEDMM this function may throw out-of memory and cause a crash + DEBUG_PRINTLN(F("Starting decoding")); - if(decoder.startDecoding() < 0) { gifDecodeFailed = true; return IMAGE_ERROR_GIF_DECODE; } + int derr = 0; + if((derr = decoder.startDecoding()) < 0) { + gifDecodeFailed = true; + USER_PRINTF("GIF Decoding error %d\n", derr); + if ((derr == ERROR_GIF_TOO_WIDE) || (derr == ERROR_GIF_UNSUPPORTED_FEATURE) || (derr == ERROR_GIF_INVALID_PARAMETER)) + errorFlag = ERR_NORAM_PX; + return IMAGE_ERROR_GIF_DECODE; + } + if ((errorFlag == ERR_NORAM_PX) || (errorFlag == ERR_NORAM)) errorFlag = ERR_NONE; // success -> reset previous memory error codes DEBUG_PRINTLN(F("Decoding started")); } @@ -118,9 +158,16 @@ byte renderImageToSegment(Segment &seg) { if (millis() - lastFrameDisplayTime < wait) return IMAGE_ERROR_WAITING; decoder.getSize(&gifWidth, &gifHeight); + // softhack007: pre-calculate upscaling for speedup + expandX = (seg_cols+(gifWidth-1)) / gifWidth; + expandY = (seg_rows+(gifHeight-1)) / gifHeight; int result = decoder.decodeFrame(false); - if (result < 0) { gifDecodeFailed = true; return IMAGE_ERROR_FRAME_DECODE; } + if (result < 0) { + gifDecodeFailed = true; + USER_PRINTF("GIF Frame decode failed %d\n", result); + return IMAGE_ERROR_FRAME_DECODE; + } currentFrameDelay = decoder.getFrameDelay_ms(); unsigned long tooSlowBy = (millis() - lastFrameDisplayTime) - wait; // if last frame was longer than intended, compensate From 698da84b4ac058e080668a08645e000f7009028e Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Thu, 6 Nov 2025 23:09:09 +0100 Subject: [PATCH 052/170] prevent division by zero when image width or height is 0 catch error early before starting the decode/paint loop --- wled00/image_loader.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/wled00/image_loader.cpp b/wled00/image_loader.cpp index ef283956..5ba7af0a 100644 --- a/wled00/image_loader.cpp +++ b/wled00/image_loader.cpp @@ -158,6 +158,12 @@ byte renderImageToSegment(Segment &seg) { if (millis() - lastFrameDisplayTime < wait) return IMAGE_ERROR_WAITING; decoder.getSize(&gifWidth, &gifHeight); + // bad gif size: prevent division by zero + if (gifWidth == 0 || gifHeight == 0) { + gifDecodeFailed = true; + USER_PRINTF("Invalid GIF dimensions: %dx%d\n", gifWidth, gifHeight); + return IMAGE_ERROR_GIF_DECODE; + } // softhack007: pre-calculate upscaling for speedup expandX = (seg_cols+(gifWidth-1)) / gifWidth; expandY = (seg_rows+(gifHeight-1)) / gifHeight; From 25391fe765f72c0c079f5589afc717bb8fed25a8 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Fri, 7 Nov 2025 00:11:14 +0100 Subject: [PATCH 053/170] try to catch / handle Gif decoder OOM gracefully ... by adding an exception handler that will catch OOM inside decoder.alloc(). not tested yet. --- wled00/image_loader.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/wled00/image_loader.cpp b/wled00/image_loader.cpp index 5ba7af0a..6ad0dc2d 100644 --- a/wled00/image_loader.cpp +++ b/wled00/image_loader.cpp @@ -131,7 +131,18 @@ byte renderImageToSegment(Segment &seg) { decoder.setFileReadCallback(fileReadCallback); decoder.setFileReadBlockCallback(fileReadBlockCallback); decoder.setFileSizeCallback(fileSizeCallback); +#if __cpp_exceptions // use exception handler if we can (some targets don't support exceptions) + try { +#endif decoder.alloc(); // WLEDMM this function may throw out-of memory and cause a crash +#if __cpp_exceptions + } catch (...) { // if we arrive here, the decoder has thrown an OOM exception + gifDecodeFailed = true; + errorFlag = ERR_NORAM_PX; + USER_PRINTLN("\nGIF decoder out of memory. I'm going to shoot myself now.\n"); + return IMAGE_ERROR_DECODER_ALLOC; + } +#endif DEBUG_PRINTLN(F("Starting decoding")); int derr = 0; From 956479164098c78df0a012d78a674b6fe9b86727 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Fri, 7 Nov 2025 00:28:40 +0100 Subject: [PATCH 054/170] prevent string underflow if seg.name is empty or shorter than four characters, ``strlen(lastFilename) - 4`` underflows (size_t), so the pointer passed to strcmp lands far before the buffer and triggers undefined behavior. This patch catches too-short segment names and aborts decoding. --- wled00/image_loader.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/wled00/image_loader.cpp b/wled00/image_loader.cpp index 6ad0dc2d..a7bd816e 100644 --- a/wled00/image_loader.cpp +++ b/wled00/image_loader.cpp @@ -111,9 +111,10 @@ byte renderImageToSegment(Segment &seg) { if (strncmp(lastFilename +1, seg.name, 32) != 0) { // segment name changed, load new image strncpy(lastFilename +1, seg.name, 32); gifDecodeFailed = false; - if (strcmp(lastFilename + strlen(lastFilename) - 4, ".gif") != 0) { + size_t fnameLen = strlen(lastFilename); + if ((fnameLen < 4) || strcmp(lastFilename + strlen(lastFilename) - 4, ".gif") != 0) { // empty segment name, name too short, or name not ending in .gif gifDecodeFailed = true; - USER_PRINTF("Unsupported format: %s\n", lastFilename); + USER_PRINTF("GIF decoder unsupported file: %s\n", lastFilename); return IMAGE_ERROR_UNSUPPORTED_FORMAT; } if (file) file.close(); From f955df04880120999bedffff75252376d625f167 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Fri, 7 Nov 2025 11:05:44 +0100 Subject: [PATCH 055/170] camelCase, future support, minor cleanup * use camelCase for local variables * furure support: rename drawPixelCallback to draw2DPixelCallback --- wled00/image_loader.cpp | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/wled00/image_loader.cpp b/wled00/image_loader.cpp index a7bd816e..808ab4c1 100644 --- a/wled00/image_loader.cpp +++ b/wled00/image_loader.cpp @@ -49,8 +49,9 @@ bool openGif(const char *filename) { // side-effect: updates "file" static Segment* activeSeg; static uint16_t gifWidth, gifHeight; // these two must stay uint16_t, because they are passed by reference -static unsigned seg_cols = 1; -static unsigned seg_rows = 1; +static unsigned segCols = 1; +static unsigned segRows = 1; +//static unsigned segLen = 1; // for future 1D support static int expandX = 1; static int expandY = 1; static int lastX = -1, lastY = -1; @@ -69,12 +70,11 @@ void updateScreenCallback(void) { } lastX = lastY = -1; // invalidate last position } -void drawPixelCallback(int16_t x, int16_t y, uint8_t red, uint8_t green, uint8_t blue) { +void draw2DPixelCallback(int16_t x, int16_t y, uint8_t red, uint8_t green, uint8_t blue) { // simple nearest-neighbor downscaling - int outY = y * seg_rows / gifHeight; - int outX = x * seg_cols / gifWidth; - - if ((unsigned(outX) >= seg_cols) || (unsigned(outY) >= seg_rows)) return; // out of range + int outY = y * segRows / gifHeight; + int outX = x * segCols / gifWidth; + if ((unsigned(outX) >= segCols) || (unsigned(outY) >= segRows)) return; // out of range if ((lastX == outX) && (lastY == outY)) return; // downscaling optimization: skip re-painting same pixel lastX = outX; lastY = outY; @@ -105,8 +105,9 @@ byte renderImageToSegment(Segment &seg) { // TODO: if (seg.mode != seg.currentMode()) return IMAGE_ERROR_WAITING; if (activeSeg && activeSeg != &seg) return IMAGE_ERROR_SEG_LIMIT; // only one segment at a time activeSeg = &seg; - seg_cols = activeSeg->virtualWidth(); - seg_rows = activeSeg->virtualHeight(); + segCols = activeSeg->virtualWidth(); + segRows = activeSeg->virtualHeight(); + // segLen = activeSeg->virtualLength(); // for future 1D and expand1D support if (strncmp(lastFilename +1, seg.name, 32) != 0) { // segment name changed, load new image strncpy(lastFilename +1, seg.name, 32); @@ -126,7 +127,7 @@ byte renderImageToSegment(Segment &seg) { } decoder.setScreenClearCallback(screenClearCallback); decoder.setUpdateScreenCallback(updateScreenCallback); - decoder.setDrawPixelCallback(drawPixelCallback); + decoder.setDrawPixelCallback(draw2DPixelCallback); decoder.setFileSeekCallback(fileSeekCallback); decoder.setFilePositionCallback(filePositionCallback); decoder.setFileReadCallback(fileReadCallback); @@ -177,8 +178,8 @@ byte renderImageToSegment(Segment &seg) { return IMAGE_ERROR_GIF_DECODE; } // softhack007: pre-calculate upscaling for speedup - expandX = (seg_cols+(gifWidth-1)) / gifWidth; - expandY = (seg_rows+(gifHeight-1)) / gifHeight; + expandX = (segCols+(gifWidth-1)) / gifWidth; + expandY = (segRows+(gifHeight-1)) / gifHeight; int result = decoder.decodeFrame(false); if (result < 0) { From 9115cd17af00599fbbfe0a92e5ce1645e77af6dd Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Fri, 7 Nov 2025 11:45:46 +0100 Subject: [PATCH 056/170] tiny cleanup, ready to merge --- wled00/image_loader.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wled00/image_loader.cpp b/wled00/image_loader.cpp index 808ab4c1..b5a17644 100644 --- a/wled00/image_loader.cpp +++ b/wled00/image_loader.cpp @@ -113,7 +113,7 @@ byte renderImageToSegment(Segment &seg) { strncpy(lastFilename +1, seg.name, 32); gifDecodeFailed = false; size_t fnameLen = strlen(lastFilename); - if ((fnameLen < 4) || strcmp(lastFilename + strlen(lastFilename) - 4, ".gif") != 0) { // empty segment name, name too short, or name not ending in .gif + if ((fnameLen < 4) || strcmp(lastFilename + fnameLen - 4, ".gif") != 0) { // empty segment name, name too short, or name not ending in .gif gifDecodeFailed = true; USER_PRINTF("GIF decoder unsupported file: %s\n", lastFilename); return IMAGE_ERROR_UNSUPPORTED_FORMAT; From c58c6ef26887e68168a13e85765181bb7ab81bd0 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Fri, 7 Nov 2025 11:58:55 +0100 Subject: [PATCH 057/170] minor robustness improvement If seg.name is at least 32 characters long, strncpy will fill the 32-byte window without appending '\0'. This could lead to sporadic errors. --- wled00/image_loader.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/wled00/image_loader.cpp b/wled00/image_loader.cpp index b5a17644..8046fe78 100644 --- a/wled00/image_loader.cpp +++ b/wled00/image_loader.cpp @@ -111,6 +111,7 @@ byte renderImageToSegment(Segment &seg) { if (strncmp(lastFilename +1, seg.name, 32) != 0) { // segment name changed, load new image strncpy(lastFilename +1, seg.name, 32); + lastFilename[33] = '\0'; // make sure that lastFilename is always null-terminated gifDecodeFailed = false; size_t fnameLen = strlen(lastFilename); if ((fnameLen < 4) || strcmp(lastFilename + fnameLen - 4, ".gif") != 0) { // empty segment name, name too short, or name not ending in .gif From c1979f8bc7849049e7e8a0013296ef817ab7cb63 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Fri, 7 Nov 2025 12:08:31 +0100 Subject: [PATCH 058/170] no fun in Germany ;-) no fun, just rabbits. Lets stay professional. --- wled00/image_loader.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/wled00/image_loader.cpp b/wled00/image_loader.cpp index 8046fe78..d8c21243 100644 --- a/wled00/image_loader.cpp +++ b/wled00/image_loader.cpp @@ -142,7 +142,8 @@ byte renderImageToSegment(Segment &seg) { } catch (...) { // if we arrive here, the decoder has thrown an OOM exception gifDecodeFailed = true; errorFlag = ERR_NORAM_PX; - USER_PRINTLN("\nGIF decoder out of memory. I'm going to shoot myself now.\n"); + USER_PRINTLN("\nGIF decoder out of memory. Please try a smaller image file.\n"); + //USER_PRINTLN("I'm going to shoot myself now."); return IMAGE_ERROR_DECODER_ALLOC; } #endif From d78ea5ae2edd5a4fb03b8ad9947b0b1c64d7165f Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Fri, 7 Nov 2025 15:07:13 +0100 Subject: [PATCH 059/170] prevent bad filenames in "segment names as ledmap names" Increase buffer size for fileName to accommodate long segment names (max 32 chars) without producing broken filenames. --- wled00/FX_fcn.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index 34b77f1f..5847309e 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -1765,8 +1765,8 @@ void WS2812FX::enumerateLedmaps() { uint8_t segment_index = 0; for (segment &seg : _segments) { if (seg.name != nullptr && strlen(seg.name) > 0) { - char fileName[33]; - snprintf_P(fileName, sizeof(fileName), PSTR("/lm%s.json"), seg.name); + char fileName[33+11] = { '\0' }; // segment name is 32 chars max, so we need 43 chars in worst case + snprintf_P(fileName, sizeof(fileName)-1, PSTR("/lm%s.json"), seg.name); bool isFile = WLED_FS.exists(fileName); if (isFile) ledMaps |= 1 << (10+segment_index); } From f9a2099240e31eece1ce24cb1eb06eb4a80df2a1 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sun, 9 Nov 2025 20:30:43 +0100 Subject: [PATCH 060/170] always use same GifDecoder initialization Removed conditional compilation for GifDecoder based on PSRAM availability. After inspecting the library code, it became clear that any parameter changes for GifDecoder will not impact memory needs - decoder.alloc() always requires 24KB. --- wled00/image_loader.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/wled00/image_loader.cpp b/wled00/image_loader.cpp index d8c21243..3a8fd99d 100644 --- a/wled00/image_loader.cpp +++ b/wled00/image_loader.cpp @@ -11,11 +11,7 @@ static File file; static char lastFilename[34] = "/"; -#if !defined(BOARD_HAS_PSRAM) - static GifDecoder<256,256,11,true> decoder; // WLEDMM use less RAM on boards without PSRAM - avoids crashes due to out-of-memory -#else - static GifDecoder<320,320,12,true> decoder; -#endif +static GifDecoder<320,320,12,true> decoder; // this creates the basic object; parameter lzwMaxBits is not used; decoder.alloc() always allocated "everything else" = 24Kb static bool gifDecodeFailed = false; static unsigned long lastFrameDisplayTime = 0, currentFrameDelay = 0; @@ -209,4 +205,4 @@ void endImagePlayback(Segment *seg) { DEBUG_PRINTLN(F("Image playback ended")); } -#endif \ No newline at end of file +#endif From 71b7121dedfc5abd9110d5d093a3ba0acd605076 Mon Sep 17 00:00:00 2001 From: Damian Schneider Date: Sun, 28 Sep 2025 17:06:31 +0200 Subject: [PATCH 061/170] bugfix: do not reset segments if unchanged #4969 lines were swapped, causing segment reset on every preset call. --- wled00/FX_fcn.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index 5847309e..50c9ffc7 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -537,7 +537,7 @@ void Segment::setUp(uint16_t i1, uint16_t i2, uint8_t grp, uint8_t spc, uint16_t stateChanged = true; // send UDP/WS broadcast - if (stop>start) markForBlank(); //turn old segment range off // WLEDMM stop > start + if (stop>start) markForBlank(); //turn old segment range off // WLEDMM stop > start // toDo: check if this can be skipped when boundsUnchanged if (i2 <= i1) { //disable segment stop = 0; markForReset(); @@ -558,8 +558,11 @@ void Segment::setUp(uint16_t i1, uint16_t i2, uint8_t grp, uint8_t spc, uint16_t spacing = spc; } if (ofs < UINT16_MAX) offset = ofs; - markForReset(); - if (!boundsUnchanged) refreshLightCapabilities(); + + if (!boundsUnchanged) { + markForReset(); + refreshLightCapabilities(); + } } From b94fc7c3f04a661308c1450ecbb8ff1a89ce650a Mon Sep 17 00:00:00 2001 From: netmindz Date: Wed, 20 Aug 2025 07:02:01 +0100 Subject: [PATCH 062/170] Merge pull request #4849 from Arcitec/0_15_x-improve-version-info (0.15.2 backport): Make version information consistent across update interfaces --- wled00/data/settings_sec.htm | 2 +- wled00/data/update.htm | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/wled00/data/settings_sec.htm b/wled00/data/settings_sec.htm index b6fe5590..b012e0b9 100644 --- a/wled00/data/settings_sec.htm +++ b/wled00/data/settings_sec.htm @@ -122,7 +122,7 @@ A huge thank you to everyone who helped me create WLED!

WLED core (c) 2016-2024 Christian Schwinne
WLED MM Licensed under the EUPL-1.2 license

- Server message: Response error!
+ Installed version: WLEDMM ##VERSION##
diff --git a/wled00/data/update.htm b/wled00/data/update.htm index a4cee007..d52e3638 100644 --- a/wled00/data/update.htm +++ b/wled00/data/update.htm @@ -16,7 +16,7 @@

MoonMod WLED Software Update

- ##VERSION##
+ Installed version: WLEDMM ##VERSION##
Download the latest release:

From 4a323ba05790fb94f193a0b54c9d6af8d24d662e Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sun, 9 Nov 2025 23:19:43 +0100 Subject: [PATCH 063/170] align Release Strings with upstream "server message" on OTA update page follows the new format used by upstream WLED. --- wled00/xml.cpp | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/wled00/xml.cpp b/wled00/xml.cpp index 4eb0b008..596d2ae7 100644 --- a/wled00/xml.cpp +++ b/wled00/xml.cpp @@ -767,9 +767,19 @@ void getSettingsJS(AsyncWebServerRequest* request, byte subPage, char* dest) //W sappends('m',SET_F("(\"sip\")[0]"),(char*)F("WLEDMM ")); //WLEDMM server message olen -= 2; //delete "; oappend(versionString); - oappend(SET_F(" (build ")); + oappend(SET_F(" (")); oappendi(VERSION); - oappend(SET_F(")\";")); + oappend(SET_F(")
\\\"")); + oappend(releaseString); + oappend(SET_F(".bin\\\"
(Processor: ")); + oappend( + #if defined(ARDUINO_ARCH_ESP32) + ESP.getChipModel() + #else + "ESP8266" + #endif + ); + oappend(SET_F(")
\";")); oappend(SET_F("sd=\"")); oappend(serverDescription); oappend(SET_F("\";")); @@ -863,7 +873,7 @@ void getSettingsJS(AsyncWebServerRequest* request, byte subPage, char* dest) //W oappend(versionString); oappend(SET_F(" ")); oappend((char*)FPSTR(releaseString)); - oappend(SET_F(".bin
(")); + oappend(SET_F(".bin
(")); #if defined(CONFIG_IDF_TARGET_ESP32C3) oappend(SET_F("ESP32-C3")); #elif defined(CONFIG_IDF_TARGET_ESP32S3) @@ -877,7 +887,7 @@ void getSettingsJS(AsyncWebServerRequest* request, byte subPage, char* dest) //W #endif oappend(SET_F(" build ")); oappendi(VERSION); - oappend(SET_F(")\";")); + oappend(SET_F(")\";")); } if (subPage == 10) // 2D matrices From 36648d193623d8c8922d77bf9aa35a064e52cb25 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Mon, 10 Nov 2025 23:17:16 +0100 Subject: [PATCH 064/170] hot path optimization: make gamma correction inline * make sure that gamma LUT is always initialized * remove some unnecessary safety checks * make gamma8() inline, for more speed * use fast unGamma8 for preview * add super-fast unGamma8 for HUB75 - old function lost 3-10 fps, this version does not reduce fps at all *grins* --- wled00/bus_manager.cpp | 32 ++++++++++++++++++++++++++------ wled00/colors.cpp | 13 ++++++------- wled00/const.h | 2 ++ wled00/fcn_declare.h | 8 +++++++- wled00/wled.cpp | 5 +++++ wled00/ws.cpp | 7 ++++--- 6 files changed, 50 insertions(+), 17 deletions(-) diff --git a/wled00/bus_manager.cpp b/wled00/bus_manager.cpp index eaa46caa..bfeb6616 100644 --- a/wled00/bus_manager.cpp +++ b/wled00/bus_manager.cpp @@ -610,6 +610,20 @@ uint8_t BusHub75Matrix::activeType = 0; uint8_t BusHub75Matrix::instanceCount = 0; uint8_t BusHub75Matrix::last_bri = 0; +#ifndef NO_CIE1931 + +// WLEDMM speedup: create a version of "unGamma8" that can be inlined by the compiler +extern uint8_t gammaTinv[256]; // defined in colors.cpp +static uint8_t const* myGammaTable = gammaTinv; // local alias for gammaTinv + +static inline uint8_t unGamma8_bus(uint8_t value) { + return myGammaTable[value]; +} +static inline uint32_t unGamma24_bus(uint32_t c) { + return RGBW32(myGammaTable[R(c)], myGammaTable[G(c)], myGammaTable[B(c)], W(c)); +} + +#endif // -------------------------- // Bitdepth reduction based on panel size @@ -1080,6 +1094,13 @@ BusHub75Matrix::BusHub75Matrix(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWh activeFourScanPanel = fourScanPanel; if (newDisplay) memcpy(&activeMXconfig, &mxconfig, sizeof(mxconfig)); } + +#ifndef NO_CIE1931 + // force initial calculation of gamma correction tables + if ((gammaCorrectVal < 0.999f) || (gammaCorrectVal > 3.0f)) calcGammaTable(1.0f); + else calcGammaTable(gammaCorrectVal); +#endif + instanceCount++; USER_PRINT(F("heap usage: ")); USER_PRINTLN(int(lastHeap - ESP.getFreeHeap())); } @@ -1142,13 +1163,12 @@ void __attribute__((hot)) IRAM_ATTR BusHub75Matrix::show(void) { for (int y=0; y 3.0f)) return value; if (gammaTinv[255] == 0) calcInvGammaTable(gammaCorrectVal); + //if ((gammaCorrectVal < 0.999f) || (gammaCorrectVal > 3.0f)) return value; // WLEDMM yes, looks stupid return gammaTinv[value]; } @@ -482,13 +481,13 @@ void calcGammaTable(float gamma) } // used for individual channel or brightness gamma correction -IRAM_ATTR_YN __attribute__((hot)) uint8_t gamma8(uint8_t b) // WLEDMM added IRAM_ATTR_YN +IRAM_ATTR_YN __attribute__((hot)) uint8_t gamma8_slow(uint8_t b) // WLEDMM added IRAM_ATTR_YN { return gammaT[b]; } // used for color gamma correction -uint32_t __attribute__((hot)) gamma32(uint32_t color) +IRAM_ATTR_YN uint32_t __attribute__((hot)) gamma32(uint32_t color) { if (!gammaCorrectCol) return color; uint8_t w = W(color); diff --git a/wled00/const.h b/wled00/const.h index bf0e62ad..388eaad6 100644 --- a/wled00/const.h +++ b/wled00/const.h @@ -594,8 +594,10 @@ // error only in MM, not in upstream... tbd: find out why #ifdef ARDUINO_ARCH_ESP32 #define IRAM_ATTR_YN IRAM_ATTR + #define DRAM_ATTR_YN DRAM_ATTR #else #define IRAM_ATTR_YN + #define DRAM_ATTR_YN #endif #define WLED_O2_ATTR __attribute__((optimize("O2"))) diff --git a/wled00/fcn_declare.h b/wled00/fcn_declare.h index c5e95604..37b4e10a 100644 --- a/wled00/fcn_declare.h +++ b/wled00/fcn_declare.h @@ -78,11 +78,17 @@ uint16_t __attribute__((const)) approximateKelvinFromRGB(uint32_t rgb); void setRandomColor(byte* rgb); uint8_t gamma8_cal(uint8_t b, float gamma); void calcGammaTable(float gamma); -uint8_t __attribute__((pure)) gamma8(uint8_t b); // WLEDMM: added attribute pure +uint8_t __attribute__((pure)) gamma8_slow(uint8_t b); // WLEDMM: added attribute pure uint32_t __attribute__((pure)) gamma32(uint32_t); // WLEDMM: added attribute pure uint8_t unGamma8(uint8_t value); // WLEDMM revert gamma correction uint32_t unGamma24(uint32_t c); // WLEDMM for 24bit color (white left as-is) +// WLEDMM: speedup - inline function for gamma correction +extern uint8_t gammaTinv[256]; // colors.cpp +extern uint8_t gammaT[256]; // colors.cpp +inline uint8_t gamma8(uint8_t value) { return gammaT[value];} // WLEDMM inlined for speed +inline uint8_t fast_unGamma8(uint8_t value) { return gammaTinv[value];} + //dmx_output.cpp void initDMXOutput(); void handleDMXOutput(); diff --git a/wled00/wled.cpp b/wled00/wled.cpp index 1842d6ad..d778251b 100644 --- a/wled00/wled.cpp +++ b/wled00/wled.cpp @@ -886,6 +886,11 @@ void WLED::setup() #endif USER_PRINT(F("Free heap ")); USER_PRINTLN(ESP.getFreeHeap());USER_PRINTLN(); + + // WLEDMM force initial calculation of gamma correction LUT + if ((gammaCorrectVal < 0.999f) || (gammaCorrectVal > 3.0f)) calcGammaTable(1.0f); // no gamma => create linear LUT + else calcGammaTable(gammaCorrectVal); + USER_PRINTLN(F("WLED initialization done.\n")); delay(50); // repeat Ada prompt diff --git a/wled00/ws.cpp b/wled00/ws.cpp index 9b7d24e7..e061b6a6 100644 --- a/wled00/ws.cpp +++ b/wled00/ws.cpp @@ -253,6 +253,7 @@ static bool sendLiveLedsWs(uint32_t wsClient) // WLEDMM added "static" } #endif + (void) unGamma8(127); // WLEDMM dummy call, just to make sure that gammaTinv is initialized, so we can use fast_unGamma8 uint8_t stripBrightness = strip.getBrightness(); for (size_t i = 0; pos < bufSize -2; i += n) { @@ -268,9 +269,9 @@ static bool sendLiveLedsWs(uint32_t wsClient) // WLEDMM added "static" if (gammaCorrectPreview) { uint8_t w = W(c); // not sure why, but it looks better if using "white" without corrections if (w>0) c = color_add(c, RGBW32(w, w, w, 0), false); // add white channel to RGB channels - color_add() will prevent over-saturation - buffer[pos++] = unGamma8(R(c)); //R - buffer[pos++] = unGamma8(G(c)); //G - buffer[pos++] = unGamma8(B(c)); //B + buffer[pos++] = fast_unGamma8(R(c)); //R + buffer[pos++] = fast_unGamma8(G(c)); //G + buffer[pos++] = fast_unGamma8(B(c)); //B } else { // WLEDMM end uint8_t w = W(c); // WLEDMM small optimization From e4c964ebaf1d63d6138291939dfbc707c8c5f29b Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Tue, 11 Nov 2025 21:59:19 +0100 Subject: [PATCH 065/170] deserializeMap robustness improvements * make sure that fileName is big enough for segmentName".json" * fix possible buffer overflow in f.readBytesUntil * stop reading map{ } entries when customMappingSize is reached * raise "low mem" error when malloc failed --- wled00/FX_fcn.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index 50c9ffc7..d6a2a552 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -2564,7 +2564,7 @@ void WS2812FX::loadCustomPalettes() { bool WS2812FX::deserializeMap(uint8_t n) { // 2D support creates its own ledmap (on the fly) if a ledmap.json exists it will overwrite built one. - char fileName[32] = {'\0'}; + char fileName[42] = {'\0'}; // WLEDMM we need at least 32 + 7 bytes //WLEDMM: als support segment name ledmaps bool isFile = false;; if (n<10) { @@ -2576,7 +2576,8 @@ bool WS2812FX::deserializeMap(uint8_t n) { uint8_t segment_index = 0; for (segment &seg : _segments) { if (n == 10 + segment_index && !isFile && seg.name != nullptr) { - sprintf_P(fileName, PSTR("/%s.json"), seg.name); + snprintf_P(fileName, sizeof(fileName) -1, PSTR("/%s.json"), seg.name); + fileName[sizeof(fileName) -1] = '\0'; isFile = WLED_FS.exists(fileName); } if (isFile) break; @@ -2618,13 +2619,13 @@ bool WS2812FX::deserializeMap(uint8_t n) { //WLEDMM: read width and height memset(fileName, 0, sizeof(fileName)); // clear old buffer - readBytesUntil() does not terminate strings !!! f.find("\"width\":"); - f.readBytesUntil('\n', fileName, sizeof(fileName)); //hack: use fileName as we have this allocated already + f.readBytesUntil('\n', fileName, sizeof(fileName)-1); //hack: use fileName as we have this allocated already uint16_t maxWidth = atoi(cleanUpName(fileName)); //DEBUG_PRINTF(" (\"width\": %s) ", fileName) memset(fileName, 0, sizeof(fileName)); // clear old buffer f.find("\"height\":"); - f.readBytesUntil('\n', fileName, sizeof(fileName)); + f.readBytesUntil('\n', fileName, sizeof(fileName)-1); uint16_t maxHeight = atoi(cleanUpName(fileName)); //DEBUG_PRINTF(" (\"height\": %s) \n", fileName) @@ -2661,6 +2662,7 @@ bool WS2812FX::deserializeMap(uint8_t n) { errorFlag = ERR_LOW_MEM; // WLEDMM raise errorflag } } + if ((errorFlag == ERR_LOW_MEM) && (size > 0) && (customMappingTable != nullptr)) errorFlag == ERR_NONE; // reset error flag if (customMappingTable != nullptr) customMappingTableSize = size; } @@ -2677,7 +2679,7 @@ bool WS2812FX::deserializeMap(uint8_t n) { int mapi = f.readStringUntil(',').toInt(); // USER_PRINTF(", %d(%d)", mapi, i); if (i < customMappingSize) customMappingTable[i++] = (uint16_t) (mapi<0 ? 0xFFFFU : mapi); // WLEDMM do not write past array bounds - } while (f.available()); + } while (f.available() && (i < customMappingSize)); loadedLedmap = n; f.close(); @@ -2692,6 +2694,7 @@ bool WS2812FX::deserializeMap(uint8_t n) { #endif } else { // memory allocation error customMappingTableSize = 0; + errorFlag = ERR_LOW_MEM; // WLEDMM raise errorflag USER_PRINTLN(F("Deserializemap: Ledmap alloc error.")); USER_FLUSH(); } From 1e14e4b4e5dc95e5cd927c0aa88837e3131d27db Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Tue, 11 Nov 2025 23:09:09 +0100 Subject: [PATCH 066/170] fix minor bug (errorflag reset not working) typo: == instead of = --- wled00/FX_fcn.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index d6a2a552..7ef615c1 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -2662,7 +2662,7 @@ bool WS2812FX::deserializeMap(uint8_t n) { errorFlag = ERR_LOW_MEM; // WLEDMM raise errorflag } } - if ((errorFlag == ERR_LOW_MEM) && (size > 0) && (customMappingTable != nullptr)) errorFlag == ERR_NONE; // reset error flag + if ((errorFlag == ERR_LOW_MEM) && (size > 0) && (customMappingTable != nullptr)) errorFlag = ERR_NONE; // reset error flag if (customMappingTable != nullptr) customMappingTableSize = size; } From a833cb5706afeb9ff3e513aaed72b45197e3c75c Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Tue, 11 Nov 2025 23:17:50 +0100 Subject: [PATCH 067/170] JMap robustness and use-after-free fixes * increased ArrayAndSize.size from 8bit to 16bit * prevent out-of-bounds access in JMapC::getPixelColor * do not delete[] SEGMENT.name from outside of segment class !! --- wled00/FX_fcn.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index 7ef615c1..573de218 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -687,7 +687,7 @@ struct XandY { uint8_t y; }; struct ArrayAndSize { - uint8_t size; + uint16_t size; XandY *array; }; class JMapC { @@ -727,7 +727,7 @@ class JMapC { } uint32_t getPixelColor(uint16_t i) { updatejMapDoc(); - if (jVectorMap.size() > 0) + if (jVectorMap.size() > i) // implies jVectorMap.size() > 0, because i is unsigned return SEGMENT.getPixelColorXY(jVectorMap[i].array[0].x * scale, jVectorMap[i].array[0].y * scale); else return 0; @@ -735,7 +735,7 @@ class JMapC { private: std::vector jVectorMap; StaticJsonDocument<4096> docChunk; //must fit forks with about 32 points each - uint8_t scale; + uint8_t scale=1; void updatejMapDoc() { if (SEGMENT.name == nullptr && jVectorMap.size() > 0) { @@ -745,7 +745,7 @@ class JMapC { uint32_t dataSize = 0; deletejVectorMap(); DEBUG_PRINT("New "); DEBUG_PRINTLN(SEGMENT.name); - char jMapFileName[50]; + char jMapFileName[50] = {'\0'}; // we need at most 32 + 7 bytes strcpy(jMapFileName, "/"); strcat(jMapFileName, SEGMENT.name); strcat(jMapFileName, ".json"); @@ -765,7 +765,10 @@ class JMapC { { USER_PRINTF("deserializeJson() of parseTree failed with code %s\n", err.c_str()); USER_FLUSH(); - if (SEGMENT.name) delete[] SEGMENT.name; SEGMENT.name = nullptr; //need to clear the name as otherwise continuously loaded // softhack007 avoid deleting nullptr + // softhack007: DO NOT delete SEGMENT.name - it's owned by Segment class, deleting it from outside can lead to use-after-free + // if (SEGMENT.name) delete[] SEGMENT.name; SEGMENT.name = nullptr; //need to clear the name as otherwise continuously loaded // softhack007 avoid deleting nullptr + strlcpy(previousSegmentName, SEGMENT.name, sizeof(previousSegmentName)); // Mark name as processed to avoid reload loop + if (jMapFile) jMapFile.close(); // make sure the file is closed return; } From ca35e9914a9609e0c52d7ad9a2afaa67987bc238 Mon Sep 17 00:00:00 2001 From: Damian Schneider Date: Fri, 14 Nov 2025 18:22:31 +0100 Subject: [PATCH 068/170] Improved 1D support for GIF images, bugfixes, blur option by @DedeHai & @softhack007 - add better support for 1D gifs: use the full gif, row by row, scale if needed - add blur slider to image FX - improved safety checks to avoid crashes - add "fast path" if image size matches virtual segment size --- wled00/image_loader.cpp | 153 +++++++++++++++++++++++++--------------- 1 file changed, 96 insertions(+), 57 deletions(-) diff --git a/wled00/image_loader.cpp b/wled00/image_loader.cpp index 3a8fd99d..b6d13efa 100644 --- a/wled00/image_loader.cpp +++ b/wled00/image_loader.cpp @@ -5,13 +5,18 @@ #include "GifDecoder.h" +//upstream compatibility +#if !defined(WLED_MAX_SEGNAME_LEN) +#define WLED_MAX_SEGNAME_LEN 32 +#endif + /* * Functions to render images from filesystem to segments, used by the "Image" effect */ static File file; -static char lastFilename[34] = "/"; -static GifDecoder<320,320,12,true> decoder; // this creates the basic object; parameter lzwMaxBits is not used; decoder.alloc() always allocated "everything else" = 24Kb +static char lastFilename[WLED_MAX_SEGNAME_LEN+2] = "/"; // enough space for "/" + seg.name + '\0' +static GifDecoder<320,320,12,true> decoder; // this creates the basic object; parameter lzwMaxBits is not used; decoder.alloc() always allocates "everything else" = 24Kb static bool gifDecodeFailed = false; static unsigned long lastFrameDisplayTime = 0, currentFrameDelay = 0; @@ -37,7 +42,7 @@ int fileSizeCallback(void) { bool openGif(const char *filename) { // side-effect: updates "file" file = WLED_FS.open(filename, "r"); - DEBUG_PRINTF("opening GIF file %s\n", filename); + USER_PRINTF("opening GIF file %s\n", filename); if (!file) return false; return true; @@ -47,37 +52,56 @@ static Segment* activeSeg; static uint16_t gifWidth, gifHeight; // these two must stay uint16_t, because they are passed by reference static unsigned segCols = 1; static unsigned segRows = 1; -//static unsigned segLen = 1; // for future 1D support -static int expandX = 1; -static int expandY = 1; -static int lastX = -1, lastY = -1; +static unsigned segLen = 1; // for 1D and 1DExpand support +static int lastCoordinate = -1; // last coordinate (x+y) that was set, used to reduce redundant pixel writes +static unsigned perPixelX, perPixelY; // scaling factors when upscaling void screenClearCallback(void) { activeSeg->fill(0); } +// this callback runs when the decoder has finished painting all pixels void updateScreenCallback(void) { - // this callback runs when the decoder has finished painting all pixels // perfect time for adding blur if (activeSeg->intensity > 1) { - uint8_t blurAmount = activeSeg->intensity >> 2; - if ((blurAmount < 24) && (activeSeg->is2D())) activeSeg->blurRows(activeSeg->intensity >> 1); // some blur - fast - else activeSeg->blur(blurAmount); // more blur - slower + uint8_t blurAmount = activeSeg->intensity >> 1; + if ((blurAmount < 48) && (activeSeg->is2D())) activeSeg->blurRows(activeSeg->intensity); // some blur - fast + else activeSeg->blur(blurAmount); // more blur - slower } - lastX = lastY = -1; // invalidate last position + lastCoordinate = -1; // invalidate last position } -void draw2DPixelCallback(int16_t x, int16_t y, uint8_t red, uint8_t green, uint8_t blue) { - // simple nearest-neighbor downscaling - int outY = y * segRows / gifHeight; - int outX = x * segCols / gifWidth; - if ((unsigned(outX) >= segCols) || (unsigned(outY) >= segRows)) return; // out of range - if ((lastX == outX) && (lastY == outY)) return; // downscaling optimization: skip re-painting same pixel - lastX = outX; lastY = outY; - // set multiple pixels if upscaling - // softhack007: changed loop x/y order -> minor speedup from better cache locality - for (int j = 0; j < expandY; j++) { - for (int i = 0; i < expandX; i++) { +// note: GifDecoder drawing is done top right to bottom left, line by line + +// callbacks to draw a pixel at (x,y) without scaling: used if GIF size matches (virtual)segment size (faster) works for 1D and 2D segments +void drawPixelCallbackNoScale1D(int16_t x, int16_t y, uint8_t red, uint8_t green, uint8_t blue) { + activeSeg->setPixelColor(y * gifWidth + x, gamma8(red), gamma8(green), gamma8(blue)); +} +void drawPixelCallbackNoScale2D(int16_t x, int16_t y, uint8_t red, uint8_t green, uint8_t blue) { // WLEDMM setPixelColorXY is faster in our fork + activeSeg->setPixelColorXY(x, y, gamma8(red), gamma8(green), gamma8(blue)); +} + +void drawPixelCallback1D(int16_t x, int16_t y, uint8_t red, uint8_t green, uint8_t blue) { + // 1D strip: load pixel-by-pixel left to right, top to bottom (0/0 = top-left in gifs) + int totalImgPix = (int)gifWidth * gifHeight; + int start = ((int)y * gifWidth + (int)x) * segLen / totalImgPix; // simple nearest-neighbor scaling + if (start == lastCoordinate) return; // skip setting same coordinate again + lastCoordinate = start; + for (int i = 0; i < perPixelX; i++) { + activeSeg->setPixelColor(start + i, gamma8(red), gamma8(green), gamma8(blue)); + } +} + +void drawPixelCallback2D(int16_t x, int16_t y, uint8_t red, uint8_t green, uint8_t blue) { + // simple nearest-neighbor scaling + int outY = (int)y * segRows / gifHeight; + int outX = (int)x * segCols / gifWidth; + // Pack coordinates uniquely: outY into upper 16 bits, outX into lower 16 bits + if (((outY << 16) | outX) == lastCoordinate) return; // skip setting same coordinate again + lastCoordinate = (outY << 16) | outX; // since input is a "scanline" this is sufficient to identify a "unique" coordinate + // set multiple pixels if upscaling // softhack007: changed loop x/y order -> minor speedup from better cache locality + for (int j = 0; j < perPixelY; j++) { + for (int i = 0; i < perPixelX; i++) { activeSeg->setPixelColorXY(outX + i, outY + j, gamma8(red), gamma8(green), gamma8(blue)); } } @@ -98,16 +122,18 @@ void draw2DPixelCallback(int16_t x, int16_t y, uint8_t red, uint8_t green, uint8 byte renderImageToSegment(Segment &seg) { if (!seg.name) return IMAGE_ERROR_NO_NAME; // disable during effect transition, causes flickering, multiple allocations and depending on image, part of old FX remaining - // TODO: if (seg.mode != seg.currentMode()) return IMAGE_ERROR_WAITING; + //if (seg.mode != seg.currentMode()) return IMAGE_ERROR_WAITING; if (activeSeg && activeSeg != &seg) return IMAGE_ERROR_SEG_LIMIT; // only one segment at a time + activeSeg = &seg; segCols = activeSeg->virtualWidth(); segRows = activeSeg->virtualHeight(); - // segLen = activeSeg->virtualLength(); // for future 1D and expand1D support + segLen = activeSeg->calc_virtualLength(); - if (strncmp(lastFilename +1, seg.name, 32) != 0) { // segment name changed, load new image - strncpy(lastFilename +1, seg.name, 32); - lastFilename[33] = '\0'; // make sure that lastFilename is always null-terminated + if (strncmp(lastFilename +1, seg.name, WLED_MAX_SEGNAME_LEN) != 0) { // segment name changed, load new image + strcpy(lastFilename, "/"); // filename always starts with '/' + strncpy(lastFilename +1, seg.name, WLED_MAX_SEGNAME_LEN); + lastFilename[WLED_MAX_SEGNAME_LEN+1] ='\0'; // ensure proper string termination when segment name was truncated gifDecodeFailed = false; size_t fnameLen = strlen(lastFilename); if ((fnameLen < 4) || strcmp(lastFilename + fnameLen - 4, ".gif") != 0) { // empty segment name, name too short, or name not ending in .gif @@ -116,45 +142,69 @@ byte renderImageToSegment(Segment &seg) { return IMAGE_ERROR_UNSUPPORTED_FORMAT; } if (file) file.close(); - if (!openGif(lastFilename)) { - gifDecodeFailed = true; + gifDecodeFailed = true; USER_PRINTF("GIF file not found: %s\n", lastFilename); - return IMAGE_ERROR_FILE_MISSING; + return IMAGE_ERROR_FILE_MISSING; } + lastCoordinate = -1; decoder.setScreenClearCallback(screenClearCallback); decoder.setUpdateScreenCallback(updateScreenCallback); - decoder.setDrawPixelCallback(draw2DPixelCallback); + decoder.setDrawPixelCallback(drawPixelCallbackNoScale1D); // default: use "fast path" callback without scaling decoder.setFileSeekCallback(fileSeekCallback); decoder.setFilePositionCallback(filePositionCallback); decoder.setFileReadCallback(fileReadCallback); decoder.setFileReadBlockCallback(fileReadBlockCallback); decoder.setFileSizeCallback(fileSizeCallback); #if __cpp_exceptions // use exception handler if we can (some targets don't support exceptions) - try { + try { #endif - decoder.alloc(); // WLEDMM this function may throw out-of memory and cause a crash + decoder.alloc(); // this function may throw out-of memory and cause a crash #if __cpp_exceptions } catch (...) { // if we arrive here, the decoder has thrown an OOM exception gifDecodeFailed = true; errorFlag = ERR_NORAM_PX; - USER_PRINTLN("\nGIF decoder out of memory. Please try a smaller image file.\n"); + USER_PRINTLN(F("\nGIF decoder out of memory. Please try a smaller image file.\n")); //USER_PRINTLN("I'm going to shoot myself now."); return IMAGE_ERROR_DECODER_ALLOC; + // decoder cleanup (hi @coderabbitai): No additonal cleanup necessary - decoder.alloc() ultimately uses "new AnimatedGIF". + // If new throws, no pointer is assigned, previous decoder state (if any) has already been deleted inside alloc(), so calling decoder.dealloc() here is unnecessary. } #endif - DEBUG_PRINTLN(F("Starting decoding")); - int derr = 0; - if((derr = decoder.startDecoding()) < 0) { + int decoderError = decoder.startDecoding(); + if(decoderError < 0) { + USER_PRINTF("GIF Decoding error %d in startDecoding().\n", decoderError); + errorFlag = ERR_NORAM_PX; gifDecodeFailed = true; - USER_PRINTF("GIF Decoding error %d\n", derr); - if ((derr == ERROR_GIF_TOO_WIDE) || (derr == ERROR_GIF_UNSUPPORTED_FEATURE) || (derr == ERROR_GIF_INVALID_PARAMETER)) - errorFlag = ERR_NORAM_PX; - return IMAGE_ERROR_GIF_DECODE; + return IMAGE_ERROR_GIF_DECODE; } - if ((errorFlag == ERR_NORAM_PX) || (errorFlag == ERR_NORAM)) errorFlag = ERR_NONE; // success -> reset previous memory error codes DEBUG_PRINTLN(F("Decoding started")); + // after startDecoding, we can get GIF size, update static variables and callbacks + decoder.getSize(&gifWidth, &gifHeight); + if (gifWidth == 0 || gifHeight == 0) { // bad gif size: prevent division by zero + gifDecodeFailed = true; + USER_PRINTF("Invalid GIF dimensions: %dx%d\n", gifWidth, gifHeight); + return IMAGE_ERROR_GIF_DECODE; + } + if (activeSeg->is2D()) { + perPixelX = (segCols + gifWidth -1) / gifWidth; + perPixelY = (segRows + gifHeight-1) / gifHeight; + if (segCols != gifWidth || segRows != gifHeight) { + decoder.setDrawPixelCallback(drawPixelCallback2D); // use 2D callback with scaling + //DEBUG_PRINTLN(F("scaling image")); + } else { + decoder.setDrawPixelCallback(drawPixelCallbackNoScale2D); // use 2D callback without scaling + } + } else { + int totalImgPix = (int)gifWidth * gifHeight; + if (totalImgPix - segLen == 1) totalImgPix--; // handle off-by-one: skip last pixel instead of first (gifs constructed from 1D input pad last pixel if length is odd) + perPixelX = (segLen + totalImgPix-1) / totalImgPix; + if (totalImgPix != segLen) { + decoder.setDrawPixelCallback(drawPixelCallback1D); // use 1D callback with scaling + //DEBUG_PRINTLN(F("scaling image")); + } + } } if (gifDecodeFailed) return IMAGE_ERROR_PREV; @@ -168,23 +218,12 @@ byte renderImageToSegment(Segment &seg) { // TODO consider handling this on FX level with a different frametime, but that would cause slow gifs to speed up during transitions if (millis() - lastFrameDisplayTime < wait) return IMAGE_ERROR_WAITING; - decoder.getSize(&gifWidth, &gifHeight); - // bad gif size: prevent division by zero - if (gifWidth == 0 || gifHeight == 0) { - gifDecodeFailed = true; - USER_PRINTF("Invalid GIF dimensions: %dx%d\n", gifWidth, gifHeight); - return IMAGE_ERROR_GIF_DECODE; - } - // softhack007: pre-calculate upscaling for speedup - expandX = (segCols+(gifWidth-1)) / gifWidth; - expandY = (segRows+(gifHeight-1)) / gifHeight; - int result = decoder.decodeFrame(false); if (result < 0) { + USER_PRINTF("GIF Decoding error %d in decodeFrame().\n", result); gifDecodeFailed = true; - USER_PRINTF("GIF Frame decode failed %d\n", result); return IMAGE_ERROR_FRAME_DECODE; - } + } currentFrameDelay = decoder.getFrameDelay_ms(); unsigned long tooSlowBy = (millis() - lastFrameDisplayTime) - wait; // if last frame was longer than intended, compensate @@ -201,7 +240,7 @@ void endImagePlayback(Segment *seg) { decoder.dealloc(); gifDecodeFailed = false; activeSeg = nullptr; - lastFilename[1] = '\0'; + strcpy(lastFilename, "/"); // reset filename DEBUG_PRINTLN(F("Image playback ended")); } From 9b6ce948f25d0166ee027987f8db8c0f00843335 Mon Sep 17 00:00:00 2001 From: Damian Schneider Date: Tue, 21 Oct 2025 19:41:57 +0200 Subject: [PATCH 069/170] Adding DDP over WS, moving duplicate WS-connection to common.js (#4997) - Enabling DDP over WebSocket: this allows for UI or html tools to stream data to the LEDs much faster than through the JSON API. - first byte of data array is used to determine protocol for future use - Moved the duplicate function to establish a WS connection from the live-view htm files to common.js - add better safety check for DDP: prevent OOB reads of buffer --- wled00/e131.cpp | 10 +++++++++- wled00/ws.cpp | 33 ++++++++++++++++++++++++++++++++- 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/wled00/e131.cpp b/wled00/e131.cpp index a6123e7a..27ce1e3c 100644 --- a/wled00/e131.cpp +++ b/wled00/e131.cpp @@ -31,11 +31,19 @@ void handleDDPPacket(e131_packet_t* p) { uint32_t start = htonl(p->channelOffset) / ddpChannelsPerLed; start += DMXAddress / ddpChannelsPerLed; - uint16_t stop = start + htons(p->dataLen) / ddpChannelsPerLed; + uint16_t dataLen = htons(p->dataLen); + unsigned stop = start + dataLen / ddpChannelsPerLed; uint8_t* data = p->data; uint16_t c = 0; if (p->flags & DDP_TIMECODE_FLAG) c = 4; //packet has timecode flag, we do not support it, but data starts 4 bytes later + unsigned numLeds = stop - start; // stop >= start is guaranteed + unsigned maxDataIndex = c + numLeds * ddpChannelsPerLed; // validate bounds before accessing data array + if (maxDataIndex > dataLen) { + DEBUG_PRINTLN(F("DDP packet data bounds exceeded, rejecting.")); + return; + } + if (realtimeMode != REALTIME_MODE_DDP) ddpSeenPush = false; // just starting, no push yet realtimeLock(realtimeTimeoutMs, REALTIME_MODE_DDP); diff --git a/wled00/ws.cpp b/wled00/ws.cpp index e061b6a6..0c819934 100644 --- a/wled00/ws.cpp +++ b/wled00/ws.cpp @@ -7,6 +7,16 @@ static volatile uint16_t wsLiveClientId = 0; // WLEDMM added "static" static volatile unsigned long wsLastLiveTime = 0; // WLEDMM + +// define some constants for binary protocols, dont use defines but C++ style constexpr +constexpr uint8_t BINARY_PROTOCOL_GENERIC = 0xFF; // generic / auto detect NOT IMPLEMENTED +constexpr uint8_t BINARY_PROTOCOL_E131 = P_E131; // = 0, untested! +constexpr uint8_t BINARY_PROTOCOL_ARTNET = P_ARTNET; // = 1, untested! +constexpr uint8_t BINARY_PROTOCOL_DDP = P_DDP; // = 2 + +uint16_t wsLiveClientId = 0; +unsigned long wsLastLiveTime = 0; + //uint8_t* wsFrameBuffer = nullptr; #if !defined(ARDUINO_ARCH_ESP32) || defined(WLEDMM_FASTPATH) // WLEDMM @@ -32,7 +42,7 @@ void wsEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventTyp // data packet AwsFrameInfo * info = (AwsFrameInfo*)arg; if(info->final && info->index == 0 && info->len == len){ - // the whole message is in a single frame and we got all of its data (max. 1450 bytes) + // the whole message is in a single frame and we got all of its data (max. 1428 bytes / ESP8266: 528 bytes) if(info->opcode == WS_TEXT) { if (len > 0 && len < 10 && data[0] == 'p') { @@ -74,8 +84,29 @@ void wsEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventTyp // force broadcast in 500ms after updating client //lastInterfaceUpdate = millis() - (INTERFACE_UPDATE_COOLDOWN -500); // ESP8266 does not like this } + }else if (info->opcode == WS_BINARY) { + // first byte determines protocol. Note: since e131_packet_t is "packed", the compiler handles alignment issues + //DEBUG_PRINTF_P(PSTR("WS binary message: len %u, byte0: %u\n"), len, data[0]); + int offset = 1; // offset to skip protocol byte + switch (data[0]) { + case BINARY_PROTOCOL_E131: + handleE131Packet((e131_packet_t*)&data[offset], client->remoteIP(), P_E131); + break; + case BINARY_PROTOCOL_ARTNET: + handleE131Packet((e131_packet_t*)&data[offset], client->remoteIP(), P_ARTNET); + break; + case BINARY_PROTOCOL_DDP: + if (len < 10 + offset) return; // DDP header is 10 bytes (+1 protocol byte) + size_t ddpDataLen = (data[8+offset] << 8) | data[9+offset]; // data length in bytes from DDP header + uint8_t flags = data[0+offset]; + if ((flags & DDP_TIMECODE_FLAG) ) ddpDataLen += 4; // timecode flag adds 4 bytes to data length + if (len < (10 + offset + ddpDataLen)) return; // not enough data, prevent out of bounds read + // could be a valid DDP packet, forward to handler + handleE131Packet((e131_packet_t*)&data[offset], client->remoteIP(), P_DDP); + } } } else { + DEBUG_PRINTF_P(PSTR("WS multipart message: final %u index %u len %u total %u\n"), info->final, info->index, len, (uint32_t)info->len); //message is comprised of multiple frames or the frame is split into multiple packets //if(info->index == 0){ //if (!wsFrameBuffer && len < 4096) wsFrameBuffer = new uint8_t[4096]; From 47f96fdd4adcff96565bbe999317c1248a8b860e Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Fri, 14 Nov 2025 19:51:17 +0100 Subject: [PATCH 070/170] post-merge adjustments --- wled00/ws.cpp | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/wled00/ws.cpp b/wled00/ws.cpp index 0c819934..d475c6b0 100644 --- a/wled00/ws.cpp +++ b/wled00/ws.cpp @@ -7,6 +7,7 @@ static volatile uint16_t wsLiveClientId = 0; // WLEDMM added "static" static volatile unsigned long wsLastLiveTime = 0; // WLEDMM +//uint8_t* wsFrameBuffer = nullptr; // define some constants for binary protocols, dont use defines but C++ style constexpr constexpr uint8_t BINARY_PROTOCOL_GENERIC = 0xFF; // generic / auto detect NOT IMPLEMENTED @@ -14,11 +15,6 @@ constexpr uint8_t BINARY_PROTOCOL_E131 = P_E131; // = 0, untested! constexpr uint8_t BINARY_PROTOCOL_ARTNET = P_ARTNET; // = 1, untested! constexpr uint8_t BINARY_PROTOCOL_DDP = P_DDP; // = 2 -uint16_t wsLiveClientId = 0; -unsigned long wsLastLiveTime = 0; - -//uint8_t* wsFrameBuffer = nullptr; - #if !defined(ARDUINO_ARCH_ESP32) || defined(WLEDMM_FASTPATH) // WLEDMM #define WS_LIVE_INTERVAL_MAX 120 #define WS_LIVE_INTERVAL_MIN 25 @@ -84,7 +80,7 @@ void wsEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventTyp // force broadcast in 500ms after updating client //lastInterfaceUpdate = millis() - (INTERFACE_UPDATE_COOLDOWN -500); // ESP8266 does not like this } - }else if (info->opcode == WS_BINARY) { + } else if (info->opcode == WS_BINARY) { // first byte determines protocol. Note: since e131_packet_t is "packed", the compiler handles alignment issues //DEBUG_PRINTF_P(PSTR("WS binary message: len %u, byte0: %u\n"), len, data[0]); int offset = 1; // offset to skip protocol byte @@ -106,7 +102,7 @@ void wsEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventTyp } } } else { - DEBUG_PRINTF_P(PSTR("WS multipart message: final %u index %u len %u total %u\n"), info->final, info->index, len, (uint32_t)info->len); + DEBUG_PRINTF("WS multipart message: final %u index %u len %u total %u\n", info->final, info->index, len, (uint32_t)info->len); //message is comprised of multiple frames or the frame is split into multiple packets //if(info->index == 0){ //if (!wsFrameBuffer && len < 4096) wsFrameBuffer = new uint8_t[4096]; From 9f31f2444ff01794103c3c3511703e5089e3f26a Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Fri, 14 Nov 2025 22:43:44 +0100 Subject: [PATCH 071/170] some precautions to prevent buffer out-of-bounds access and concurrency problems * make sure that filenames can hold 32chars of segment.name * fix logic error in Segment::drawCharacter * protect free(Segment::_globalLeds) with a critical section --- wled00/FX_2Dfcn.cpp | 8 ++++---- wled00/FX_fcn.cpp | 19 +++++++++++++++++-- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/wled00/FX_2Dfcn.cpp b/wled00/FX_2Dfcn.cpp index 9491e134..0b1c01f6 100644 --- a/wled00/FX_2Dfcn.cpp +++ b/wled00/FX_2Dfcn.cpp @@ -101,7 +101,7 @@ void WS2812FX::setUpMatrix() { // content of the file is just raw JSON array in the form of [val1,val2,val3,...] // there are no other "key":"value" pairs in it // allowed values are: -1 (missing pixel/no LED attached), 0 (inactive/unused pixel), 1 (active/used pixel) - char fileName[32]; strcpy_P(fileName, PSTR("/2d-gaps.json")); // reduce flash footprint + char fileName[32]; strcpy_P(fileName, PSTR("/2d-gaps.json")); // reduce flash footprint //WLEDMM you sure? bool isFile = WLED_FS.exists(fileName); size_t gapSize = 0; int8_t *gapTable = nullptr; @@ -842,11 +842,11 @@ void Segment::drawArc(unsigned x0, unsigned y0, int radius, uint32_t color, uint //WLEDMM for artifx bool Segment::jsonToPixels(char * name, uint8_t fileNr) { if (!isActive()) return true; // segment not active, nothing to do - char fileName[32] = { '\0' }; + char fileName[42] = { '\0' }; // we need up to 40 bytes (seg.name is 32 bytes max) //WLEDMM: als support segment name ledmaps bool isFile = false; // strcpy_P(fileName, PSTR("/mario")); - snprintf(fileName, sizeof(fileName), "/%s%d.json", name, fileNr); //WLEDMM: trick to not include 0 in ledmap.json + snprintf(fileName, sizeof(fileName)-1, "/%s%d.json", name, fileNr); //WLEDMM: trick to not include 0 in ledmap.json // strcat(fileName, ".json"); isFile = WLED_FS.exists(fileName); @@ -928,7 +928,7 @@ void Segment::drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, for (int j = 0; j= 0) || (x0 < cols)) { + if (unsigned(x0) < cols) { // WLEDMM same as "x0 > 0 && x0 < cols" if ((bits>>(j+(8-w))) & 0x01) { // bit set & drawing on-screen setPixelColorXY(x0, y0, fgCol); } else { diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index 573de218..b3b9cc54 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -8,7 +8,10 @@ #include "FX.h" #include "palettes.h" #ifdef ARDUINO_ARCH_ESP32 -#include // WLEDMM to get esp_timer_get_time() +#include // WLEDMM to get esp_timer_get_time() +#include "freertos/FreeRTOS.h" +#include "freertos/portmacro.h" +static portMUX_TYPE s_wled_strip_mux = portMUX_INITIALIZER_UNLOCKED; // to protect deleting Segment::_globalLeds #endif /* @@ -953,7 +956,9 @@ static void xyFromBlock(uint16_t &x,uint16_t &y, uint16_t i, uint16_t vW, uint16 x = vW / 2 - vStrip - 1; y = vH / 2 + vStrip - i2 * vStrip * 2; } - + // softhack007 not sure if clamping is necessary + //x = min(x, uint16_t(vW-1)); // clamp x at vW-1 + //y = min(y, uint16_t(vH-1)); // clamp y at vH-1 } void IRAM_ATTR_YN WLED_O2_ATTR __attribute__((hot)) Segment::setPixelColor(int i, uint32_t col) //WLEDMM: IRAM_ATTR conditionally @@ -1847,9 +1852,19 @@ void WS2812FX::finalizeInit(void) //initialize leds array. TBD: realloc if nr of leds change if (Segment::_globalLeds) { + // DONG - Valkyrie is about to die + // this is a critical section that will be removed with PR #278 which removes _globalLeds + // problem: suspendStripService provides interlocking, but there’s a window before service() observes it, + // and ESP32 is dual-core. A critical section closes that window so the pointer swap is atomic across cores. +#if defined(ARDUINO_ARCH_ESP32) + taskENTER_CRITICAL(&s_wled_strip_mux); +#endif free(Segment::_globalLeds); Segment::_globalLeds = nullptr; purgeSegments(true); // WLEDMM moved here, because it seems to improve stability. +#if defined(ARDUINO_ARCH_ESP32) + taskEXIT_CRITICAL(&s_wled_strip_mux); +#endif } if (useLedsArray && getLengthTotal()>0) { // WLEDMM avoid malloc(0) size_t arrSize = sizeof(CRGB) * getLengthTotal(); From dc04ccbde7f2fb6fd1dba2c33d945081220fdbf0 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sat, 15 Nov 2025 00:11:35 +0100 Subject: [PATCH 072/170] another attempt to avoid LED glitches during file writing * mark synchronization variables volatile (thread-safe) * additional logic in closeFile() to avoid file write while leds are pushed out by NPB driver * some comments and analysis * replace "yield()" after file ops with "delay(0)" before operations. --- wled00/file.cpp | 31 +++++++++++++++++++++++++------ wled00/wled.cpp | 15 +++++++++++++++ wled00/wled.h | 4 ++-- 3 files changed, 42 insertions(+), 8 deletions(-) diff --git a/wled00/file.cpp b/wled00/file.cpp index d3727d16..e2ae00bb 100644 --- a/wled00/file.cpp +++ b/wled00/file.cpp @@ -8,6 +8,7 @@ #if WLED_FS != LITTLEFS && ESP_IDF_VERSION_MAJOR < 4 #include "esp_spiffs.h" #endif +//#define yield() {delay(0);} // WLEDMM yield() is completely unnecessary on esp32, but delay(0) can reduce task contention #endif //WLEDMM seems that 256 is indeed the optimal buffer length @@ -37,7 +38,20 @@ static File f; // don't export to other cpp files void closeFile() { #ifdef ARDUINO_ARCH_ESP32 // WLEDMM: file.close() triggers flash writing. While flash is writing, the NPB RMT driver cannot fill its buffer which may create glitches. + // WLEDMM more precisely (thanks to a web research done by AI): + // the RMT peripheral itself doesn’t stall, but the refill path often does. In Arduino-ESP32/WLED + // typical builds, close() that commits flash writes frequently causes enough blocking that the LED pipeline under-runs, resulting in visible glitches. + // So the assumption is practically correct for this project context. + // --> with neopixelBus 2.7.5, the practical ISR stall budget is about 0.08–0.12 ms — far less than LittleFS flash commit times. + // typical flash write "commit" times are between 0.5ms and 10ms, but they can be a few 100ms in worst case + // --> file reads rarely cause refill stalls compared to writes, but large/fragmented reads can still exceed the ~0.08–0.12 ms budget. + // esp32 recommendations: use f.setBufferSize() (512–1024 for reads is reasonable); use delay(0) after file reads, to reduce task contention + + if (!f) {doCloseFile = false; return;} // WLEDMM only do all this hick-hack when f is an open file + unsigned long t_wait = millis(); + bool oldLock = suspendStripService; + if (strip.isUpdating()) suspendStripService = true; // WLEDMM schedule short pause to prevent LEDs glitching during flash write while(strip.isUpdating() && (millis() - t_wait < 72)) delay(1); // WLEDMM try to catch a moment when strip is idle while(strip.isUpdating() && (millis() - t_wait < 96)) delay(0); // try harder //if (strip.isUpdating()) USER_PRINTLN("closeFile: strip still updating."); @@ -47,7 +61,12 @@ void closeFile() { DEBUGFS_PRINT(F("Close -> ")); uint32_t s = millis(); #endif + if ((suspendStripService == false) && (oldLock == true)) oldLock = false; // update in case of parallel lock release by another task f.close(); + #ifdef ARDUINO_ARCH_ESP32 + delay(1); // might help + #endif + suspendStripService = oldLock; // restore previous lock DEBUGFS_PRINTF("took %d ms\n", millis() - s); doCloseFile = false; } @@ -61,7 +80,7 @@ static bool bufferedFind(const char *target, bool fromStart = true) { uint32_t s = millis(); #endif - if (!f || !f.size()) return false; + if (!f || !f.size()) return false; // fast return when current file closed, or file size is zero size_t targetLen = strlen(target); size_t index = 0; @@ -466,11 +485,11 @@ static const uint8_t *getPresetCache(size_t &size) { #endif // WLEDMM -static bool haveLedmapFile = true; -static bool haveIndexFile = true; -static bool haveSkinFile = true; -static bool haveICOFile = true; -static bool haveCpalFile = true; +static volatile bool haveLedmapFile = true; +static volatile bool haveIndexFile = true; +static volatile bool haveSkinFile = true; +static volatile bool haveICOFile = true; +static volatile bool haveCpalFile = true; void invalidateFileNameCache() { // reset "file not found" cache haveLedmapFile = true; haveIndexFile = true; diff --git a/wled00/wled.cpp b/wled00/wled.cpp index d778251b..a91280e5 100644 --- a/wled00/wled.cpp +++ b/wled00/wled.cpp @@ -99,7 +99,11 @@ void WLED::reset() #endif long dly = millis(); while (millis() - dly < 450) { +#ifdef ARDUINO_ARCH_ESP32 + delay(2); // yield => BS +#else yield(); // enough time to send response to client +#endif } applyBri(); USER_PRINTLN(F("\nWLED RESTART\n")); @@ -191,6 +195,9 @@ void WLED::loop() reset(); if (doCloseFile) { +#ifdef ARDUINO_ARCH_ESP32 + delay(0); // yield => BS +#endif closeFile(); yield(); } @@ -203,7 +210,11 @@ void WLED::loop() #endif handleNightlight(); handlePlaylist(); +#ifdef ARDUINO_ARCH_ESP32 + delay(0); // yield => BS +#else yield(); +#endif #ifndef WLED_DISABLE_HUESYNC handleHue(); @@ -211,7 +222,11 @@ void WLED::loop() #endif handlePresets(); +#ifdef ARDUINO_ARCH_ESP32 + delay(0); // yield => BS +#else yield(); +#endif #if defined(_MoonModules_WLED_) && defined(WLEDMM_FASTPATH) #ifdef WLED_DEBUG diff --git a/wled00/wled.h b/wled00/wled.h index dd1ba6da..2778ed21 100644 --- a/wled00/wled.h +++ b/wled00/wled.h @@ -714,9 +714,9 @@ WLED_GLOBAL uint16_t olen _INIT(0); // General filesystem WLED_GLOBAL size_t fsBytesUsed _INIT(0); WLED_GLOBAL size_t fsBytesTotal _INIT(0); -WLED_GLOBAL unsigned long presetsModifiedTime _INIT(0L); +WLED_GLOBAL volatile unsigned long presetsModifiedTime _INIT(0L); WLED_GLOBAL JsonDocument* fileDoc; -WLED_GLOBAL bool doCloseFile _INIT(false); +WLED_GLOBAL volatile bool doCloseFile _INIT(false); // presets WLED_GLOBAL byte currentPreset _INIT(0); From 4e2605b2a6e38650e851385b4e64437d4a9f419f Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sat, 15 Nov 2025 00:17:16 +0100 Subject: [PATCH 073/170] fix for 8266 build error --- wled00/file.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/wled00/file.cpp b/wled00/file.cpp index e2ae00bb..5a82bdb3 100644 --- a/wled00/file.cpp +++ b/wled00/file.cpp @@ -56,6 +56,8 @@ void closeFile() { while(strip.isUpdating() && (millis() - t_wait < 96)) delay(0); // try harder //if (strip.isUpdating()) USER_PRINTLN("closeFile: strip still updating."); delay(2); // might help + #else + bool oldLock = suspendStripService; // fix build f***u* on 8266 #endif #ifdef WLED_DEBUG_FS DEBUGFS_PRINT(F("Close -> ")); From 2932644381163a72363dd32b93b494f822a0acb8 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 15 Nov 2025 21:25:33 +0000 Subject: [PATCH 074/170] Add CDC_ON_BOOT=1 check: only modify USB_MODE for USB-OTG boards Co-authored-by: softhack007 <91616163+softhack007@users.noreply.github.com> --- pio-scripts/conditional_usb_mode.py | 41 +++++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/pio-scripts/conditional_usb_mode.py b/pio-scripts/conditional_usb_mode.py index 170eb923..5cb70b7f 100644 --- a/pio-scripts/conditional_usb_mode.py +++ b/pio-scripts/conditional_usb_mode.py @@ -8,25 +8,62 @@ This script automatically sets ARDUINO_USB_MODE based on the build context: The script detects release builds by checking for the WLED_RELEASE environment variable which is set to True in the GitHub Actions CI workflow. + +CRITICAL: This change only applies to boards with USB-OTG (ARDUINO_USB_CDC_ON_BOOT=1). +For boards with classical UART-to-USB chips (ARDUINO_USB_CDC_ON_BOOT=0), +ARDUINO_USB_MODE=1 is harmless and left unchanged. """ Import('env') import os +def has_cdc_on_boot_enabled(env): + """ + Check if ARDUINO_USB_CDC_ON_BOOT is set to 1 in the build configuration. + + Returns True if CDC_ON_BOOT=1, False otherwise. + This is used to identify boards with USB-OTG (native USB) vs UART-to-USB chips. + """ + cpp_defines = env.get('CPPDEFINES', []) + build_flags = env.get('BUILD_FLAGS', []) + + # Check in CPPDEFINES + for define in cpp_defines: + if isinstance(define, (list, tuple)) and len(define) == 2: + if define[0] == 'ARDUINO_USB_CDC_ON_BOOT' and define[1] == '1': + return True + + # Check in raw build flags + for flag in build_flags: + if isinstance(flag, str) and 'ARDUINO_USB_CDC_ON_BOOT=1' in flag: + return True + + return False + def conditional_usb_mode(env): """ Conditionally set ARDUINO_USB_MODE based on build context. - For ESP32-C3, ESP32-S2, and ESP32-S3 variants: + For ESP32-C3, ESP32-S2, and ESP32-S3 variants with USB-OTG (CDC_ON_BOOT=1): - Development builds: ARDUINO_USB_MODE=1 (default, good for debugging) - Release builds: ARDUINO_USB_MODE=0 (prevents hanging without USB debugger) + + For boards with classical UART-to-USB chip (CDC_ON_BOOT=0): + - ARDUINO_USB_MODE=1 is harmless and left unchanged """ # Check if this is a release build (CI sets WLED_RELEASE=True) is_release_build = os.environ.get('WLED_RELEASE', '').lower() in ('true', '1', 'yes') if is_release_build: - print("WLED Release build detected - setting ARDUINO_USB_MODE=0 for production") + # Check if this board uses USB-OTG (CDC_ON_BOOT=1) + if not has_cdc_on_boot_enabled(env): + print("WLED Release build detected - board has UART-to-USB chip (CDC_ON_BOOT=0)") + print(" Keeping ARDUINO_USB_MODE=1 (harmless for UART-to-USB boards)") + return + + print("WLED Release build detected - board has USB-OTG (CDC_ON_BOOT=1)") + print(" Setting ARDUINO_USB_MODE=0 for production") # Find and modify ARDUINO_USB_MODE in build flags build_flags = env.get('BUILD_FLAGS', []) From 0c92e573e1c56b1b8abce9f5be4d004d40cf0df7 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 15 Nov 2025 21:48:43 +0000 Subject: [PATCH 075/170] Improve messaging: conditional warnings and production alerts Co-authored-by: softhack007 <91616163+softhack007@users.noreply.github.com> --- pio-scripts/conditional_usb_mode.py | 36 ++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/pio-scripts/conditional_usb_mode.py b/pio-scripts/conditional_usb_mode.py index 5cb70b7f..ca88ffda 100644 --- a/pio-scripts/conditional_usb_mode.py +++ b/pio-scripts/conditional_usb_mode.py @@ -40,6 +40,28 @@ def has_cdc_on_boot_enabled(env): return False +def has_usb_mode_enabled(env): + """ + Check if ARDUINO_USB_MODE is set to 1 in the build configuration. + + Returns True if USB_MODE=1, False otherwise. + """ + cpp_defines = env.get('CPPDEFINES', []) + build_flags = env.get('BUILD_FLAGS', []) + + # Check in CPPDEFINES + for define in cpp_defines: + if isinstance(define, (list, tuple)) and len(define) == 2: + if define[0] == 'ARDUINO_USB_MODE' and define[1] == '1': + return True + + # Check in raw build flags + for flag in build_flags: + if isinstance(flag, str) and 'ARDUINO_USB_MODE=1' in flag: + return True + + return False + def conditional_usb_mode(env): """ Conditionally set ARDUINO_USB_MODE based on build context. @@ -104,7 +126,19 @@ def conditional_usb_mode(env): env.Replace(BUILD_FLAGS=new_build_flags) else: - print("Development build detected - keeping ARDUINO_USB_MODE=1 for debugging") + # Development build + has_usb_mode = has_usb_mode_enabled(env) + has_cdc_boot = has_cdc_on_boot_enabled(env) + + if has_usb_mode and has_cdc_boot: + print("Development build detected - keeping ARDUINO_USB_MODE=1 for debugging") + # Warning in orange/yellow using ANSI color codes + print("\033[93m WARNING: This build is NOT suitable for production devices!\033[0m") + print("\033[93m Production builds require WLED_RELEASE=True environment variable.\033[0m") + elif has_usb_mode: + # USB_MODE=1 present but not CDC_ON_BOOT=1 (UART-to-USB board) + print("Development build detected - board has UART-to-USB chip") + # If neither flag is present, don't print anything # Apply the conditional USB mode logic conditional_usb_mode(env) \ No newline at end of file From 43b0da03aa3f2aa236669eec3a210991f645103d Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sat, 15 Nov 2025 23:15:44 +0100 Subject: [PATCH 076/170] Update debug messages for USB mode detection --- pio-scripts/conditional_usb_mode.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/pio-scripts/conditional_usb_mode.py b/pio-scripts/conditional_usb_mode.py index ca88ffda..a851648f 100644 --- a/pio-scripts/conditional_usb_mode.py +++ b/pio-scripts/conditional_usb_mode.py @@ -131,14 +131,17 @@ def conditional_usb_mode(env): has_cdc_boot = has_cdc_on_boot_enabled(env) if has_usb_mode and has_cdc_boot: - print("Development build detected - keeping ARDUINO_USB_MODE=1 for debugging") + print("Development build detected - keeping ARDUINO_USB_MODE=1 for USB-OTG debugging") # Warning in orange/yellow using ANSI color codes print("\033[93m WARNING: This build is NOT suitable for production devices!\033[0m") print("\033[93m Production builds require WLED_RELEASE=True environment variable.\033[0m") + elif has_cdc_boot: + # CDC_ON_BOOT=1 present but not USB_MODE=1 + print("Development build detected - USB-OTG enabled, but ARDUINO_USB_MODE=1 missing for debugging.") elif has_usb_mode: # USB_MODE=1 present but not CDC_ON_BOOT=1 (UART-to-USB board) print("Development build detected - board has UART-to-USB chip") # If neither flag is present, don't print anything # Apply the conditional USB mode logic -conditional_usb_mode(env) \ No newline at end of file +conditional_usb_mode(env) From 3bc68c574e2ddeed3cf0d008e80fe75d623b8bdc Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 15 Nov 2025 23:24:01 +0000 Subject: [PATCH 077/170] Fix conflicting ARDUINO_USB_MODE definitions using BUILD_UNFLAGS Co-authored-by: softhack007 <91616163+softhack007@users.noreply.github.com> --- pio-scripts/conditional_usb_mode.py | 44 +++++------------------------ 1 file changed, 7 insertions(+), 37 deletions(-) diff --git a/pio-scripts/conditional_usb_mode.py b/pio-scripts/conditional_usb_mode.py index a851648f..08e73664 100644 --- a/pio-scripts/conditional_usb_mode.py +++ b/pio-scripts/conditional_usb_mode.py @@ -87,43 +87,13 @@ def conditional_usb_mode(env): print("WLED Release build detected - board has USB-OTG (CDC_ON_BOOT=1)") print(" Setting ARDUINO_USB_MODE=0 for production") - # Find and modify ARDUINO_USB_MODE in build flags - build_flags = env.get('BUILD_FLAGS', []) - cpp_defines = env.get('CPPDEFINES', []) - - # Look through CPPDEFINES and modify ARDUINO_USB_MODE if found - modified = False - new_defines = [] - - for define in cpp_defines: - if isinstance(define, (list, tuple)) and len(define) == 2: - if define[0] == 'ARDUINO_USB_MODE' and define[1] == '1': - # Change ARDUINO_USB_MODE from 1 to 0 for release builds - new_defines.append(('ARDUINO_USB_MODE', '0')) - modified = True - print(f" Changed ARDUINO_USB_MODE from 1 to 0") - else: - new_defines.append(define) - else: - new_defines.append(define) - - if modified: - env.Replace(CPPDEFINES=new_defines) - - # Also check raw build flags for -DARDUINO_USB_MODE=1 - new_build_flags = [] - for flag in build_flags: - if isinstance(flag, str) and 'ARDUINO_USB_MODE=1' in flag: - # Replace ARDUINO_USB_MODE=1 with ARDUINO_USB_MODE=0 - new_flag = flag.replace('ARDUINO_USB_MODE=1', 'ARDUINO_USB_MODE=0') - new_build_flags.append(new_flag) - modified = True - print(f" Modified build flag: {flag} -> {new_flag}") - else: - new_build_flags.append(flag) - - if modified: - env.Replace(BUILD_FLAGS=new_build_flags) + # Check if ARDUINO_USB_MODE=1 is present + if has_usb_mode_enabled(env): + # Remove the old definition and add the new one + # This approach properly handles flag inheritance in PlatformIO + env.Append(BUILD_UNFLAGS=["-DARDUINO_USB_MODE=1"]) + env.Append(CPPDEFINES=[("ARDUINO_USB_MODE", "0")]) + print(f" Changed ARDUINO_USB_MODE from 1 to 0") else: # Development build From 2869de215cfd298c6becb75846f4b71614d3f6c5 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sun, 16 Nov 2025 00:35:23 +0100 Subject: [PATCH 078/170] USB mode script: updated print statements for clarity --- pio-scripts/conditional_usb_mode.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/pio-scripts/conditional_usb_mode.py b/pio-scripts/conditional_usb_mode.py index 08e73664..0fd1e638 100644 --- a/pio-scripts/conditional_usb_mode.py +++ b/pio-scripts/conditional_usb_mode.py @@ -13,6 +13,7 @@ CRITICAL: This change only applies to boards with USB-OTG (ARDUINO_USB_CDC_ON_BO For boards with classical UART-to-USB chips (ARDUINO_USB_CDC_ON_BOOT=0), ARDUINO_USB_MODE=1 is harmless and left unchanged. """ +## This script was created with the help of an AI, reviewed and tested by @softhack007 Import('env') import os @@ -80,11 +81,11 @@ def conditional_usb_mode(env): if is_release_build: # Check if this board uses USB-OTG (CDC_ON_BOOT=1) if not has_cdc_on_boot_enabled(env): - print("WLED Release build detected - board has UART-to-USB chip (CDC_ON_BOOT=0)") + print("WLED Release build detected - board uses UART-to-USB chip (CDC_ON_BOOT=0)") print(" Keeping ARDUINO_USB_MODE=1 (harmless for UART-to-USB boards)") return - print("WLED Release build detected - board has USB-OTG (CDC_ON_BOOT=1)") + print("WLED Release build detected - board uses USB-OTG (CDC_ON_BOOT=1)") print(" Setting ARDUINO_USB_MODE=0 for production") # Check if ARDUINO_USB_MODE=1 is present @@ -107,10 +108,10 @@ def conditional_usb_mode(env): print("\033[93m Production builds require WLED_RELEASE=True environment variable.\033[0m") elif has_cdc_boot: # CDC_ON_BOOT=1 present but not USB_MODE=1 - print("Development build detected - USB-OTG enabled, but ARDUINO_USB_MODE=1 missing for debugging.") + print("Development build detected - USB-OTG enabled, but ARDUINO_USB_MODE=1 missing for debugging") elif has_usb_mode: # USB_MODE=1 present but not CDC_ON_BOOT=1 (UART-to-USB board) - print("Development build detected - board has UART-to-USB chip") + print("Development build detected - board uses UART-to-USB chip") # If neither flag is present, don't print anything # Apply the conditional USB mode logic From c785cb5f6c756008ec30279e046136c78e4344be Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 15 Nov 2025 23:51:04 +0000 Subject: [PATCH 079/170] Fix Serial breakage: remove ARDUINO_USB_MODE instead of setting to 0 Co-authored-by: softhack007 <91616163+softhack007@users.noreply.github.com> --- pio-scripts/conditional_usb_mode.py | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/pio-scripts/conditional_usb_mode.py b/pio-scripts/conditional_usb_mode.py index 0fd1e638..2d34126e 100644 --- a/pio-scripts/conditional_usb_mode.py +++ b/pio-scripts/conditional_usb_mode.py @@ -2,9 +2,9 @@ """ Conditional USB Mode Script for WLED-MM -This script automatically sets ARDUINO_USB_MODE based on the build context: +This script automatically manages ARDUINO_USB_MODE based on the build context: - For development builds: ARDUINO_USB_MODE=1 (allows USB debugging) -- For release builds (CI): ARDUINO_USB_MODE=0 (allows normal boot without USB debugger) +- For release builds (CI): ARDUINO_USB_MODE is removed (prevents hanging, allows normal boot) The script detects release builds by checking for the WLED_RELEASE environment variable which is set to True in the GitHub Actions CI workflow. @@ -12,6 +12,10 @@ which is set to True in the GitHub Actions CI workflow. CRITICAL: This change only applies to boards with USB-OTG (ARDUINO_USB_CDC_ON_BOOT=1). For boards with classical UART-to-USB chips (ARDUINO_USB_CDC_ON_BOOT=0), ARDUINO_USB_MODE=1 is harmless and left unchanged. + +IMPORTANT: We remove ARDUINO_USB_MODE entirely for release builds rather than setting +it to 0, because ARDUINO_USB_MODE=0 breaks Serial functionality when CDC_ON_BOOT=1. +When ARDUINO_USB_MODE is undefined, the framework uses appropriate defaults. """ ## This script was created with the help of an AI, reviewed and tested by @softhack007 @@ -65,14 +69,17 @@ def has_usb_mode_enabled(env): def conditional_usb_mode(env): """ - Conditionally set ARDUINO_USB_MODE based on build context. + Conditionally manage ARDUINO_USB_MODE based on build context. For ESP32-C3, ESP32-S2, and ESP32-S3 variants with USB-OTG (CDC_ON_BOOT=1): - Development builds: ARDUINO_USB_MODE=1 (default, good for debugging) - - Release builds: ARDUINO_USB_MODE=0 (prevents hanging without USB debugger) + - Release builds: ARDUINO_USB_MODE removed (prevents hanging, preserves Serial functionality) For boards with classical UART-to-USB chip (CDC_ON_BOOT=0): - ARDUINO_USB_MODE=1 is harmless and left unchanged + + Note: We remove the flag entirely rather than setting to 0, because + ARDUINO_USB_MODE=0 breaks Serial functionality with CDC_ON_BOOT=1. """ # Check if this is a release build (CI sets WLED_RELEASE=True) @@ -86,15 +93,14 @@ def conditional_usb_mode(env): return print("WLED Release build detected - board uses USB-OTG (CDC_ON_BOOT=1)") - print(" Setting ARDUINO_USB_MODE=0 for production") + print(" Removing ARDUINO_USB_MODE definition for production") # Check if ARDUINO_USB_MODE=1 is present if has_usb_mode_enabled(env): - # Remove the old definition and add the new one - # This approach properly handles flag inheritance in PlatformIO + # Remove ARDUINO_USB_MODE entirely - don't set it to 0 as that breaks Serial + # When undefined, the framework uses appropriate defaults based on CDC_ON_BOOT env.Append(BUILD_UNFLAGS=["-DARDUINO_USB_MODE=1"]) - env.Append(CPPDEFINES=[("ARDUINO_USB_MODE", "0")]) - print(f" Changed ARDUINO_USB_MODE from 1 to 0") + print(f" Removed ARDUINO_USB_MODE definition (was 1)") else: # Development build From 6ccbfe61ab60fb55983670d9c45a2d11ff7ea75f Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sun, 16 Nov 2025 01:08:27 +0100 Subject: [PATCH 080/170] additional debug help --- pio-scripts/output_bins.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pio-scripts/output_bins.py b/pio-scripts/output_bins.py index 3a55ced8..6b5ed337 100644 --- a/pio-scripts/output_bins.py +++ b/pio-scripts/output_bins.py @@ -49,7 +49,7 @@ def wledmm_print_build_info(env): found = False for item in all_flags: - if 'WLED_RELEASE_NAME' in item[0] or 'WLED_VERSION' in item[0] or 'ARDUINO_USB_CDC_ON_BOOT' in item[0]: + if 'WLED_RELEASE_NAME' in item[0] or 'WLED_VERSION' in item[0] or 'ARDUINO_USB_CDC_ON_BOOT' in item[0] or 'ARDUINO_USB_MODE' in item[0]: if first: print("\nUsermods and Features:") print_my_item(item) first = False From 9860dc5ca01171d31ebe25df04e73f43754c30ed Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sun, 16 Nov 2025 01:19:08 +0100 Subject: [PATCH 081/170] Disable CDC USB on boot for older framework compatibility Changed ARDUINO_USB_CDC_ON_BOOT flag to disable CDC USB due to issues with the older framework. --- platformio.ini | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index ecdb65ce..90dcf48f 100644 --- a/platformio.ini +++ b/platformio.ini @@ -2502,11 +2502,12 @@ upload_speed = 460800 build_unflags = ${env:esp32c3dev_4MB_M.build_unflags} -DWLEDMM_FASTPATH ;; needs more testing on -C3 -D WLED_ENABLE_HUB75MATRIX ;; not enough pins + -DARDUINO_USB_CDC_ON_BOOT=1 ;; hangs on boot build_flags = ${common.build_flags} ${esp32c3.build_flags} -D WLED_WATCHDOG_TIMEOUT=0 -D CONFIG_ASYNC_TCP_USE_WDT=0 ${common_mm.build_flags_S} -Wno-misleading-indentation -Wno-format-truncation -D WLED_RELEASE_NAME=seeed_esp32c3_4MB_S - -DARDUINO_USB_CDC_ON_BOOT=1 ;; enable CDC USB -> needed for debugging over serial USB + -DARDUINO_USB_CDC_ON_BOOT=0 ;; disable CDC USB, as the older framework has problems with it -D WLED_DISABLE_ADALIGHT ;; to disable serial protocols when using CDC USB (Serial RX pin will receive junk commands, unless its pulled down by resistor) -D WLED_DISABLE_INFRARED ;; save flash space ;-D WLED_DISABLE_ALEXA ;; save flash space From 870dc728f1616d1bcc63620b202ffbd7dc029895 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sun, 16 Nov 2025 02:13:29 +0100 Subject: [PATCH 082/170] Disable raw build flags checks for USB mode Commented out raw build flags checks for USB mode. The results would be wrong, because raw build_flags ignore build_unflags. --- pio-scripts/conditional_usb_mode.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/pio-scripts/conditional_usb_mode.py b/pio-scripts/conditional_usb_mode.py index 2d34126e..e3a277bf 100644 --- a/pio-scripts/conditional_usb_mode.py +++ b/pio-scripts/conditional_usb_mode.py @@ -38,10 +38,10 @@ def has_cdc_on_boot_enabled(env): if define[0] == 'ARDUINO_USB_CDC_ON_BOOT' and define[1] == '1': return True - # Check in raw build flags - for flag in build_flags: - if isinstance(flag, str) and 'ARDUINO_USB_CDC_ON_BOOT=1' in flag: - return True + # # Check in raw build flags - results can be misleading, because this ignores build_unflags + # for flag in build_flags: + # if isinstance(flag, str) and 'ARDUINO_USB_CDC_ON_BOOT=1' in flag: + # return True return False @@ -60,10 +60,10 @@ def has_usb_mode_enabled(env): if define[0] == 'ARDUINO_USB_MODE' and define[1] == '1': return True - # Check in raw build flags - for flag in build_flags: - if isinstance(flag, str) and 'ARDUINO_USB_MODE=1' in flag: - return True + # Check in raw build flags - results can be misleading, because this ignores build_unflags + # for flag in build_flags: + # if isinstance(flag, str) and 'ARDUINO_USB_MODE=1' in flag: + # return True return False From 14f0d0a03c25574490489f0ab9a7ecbd90dbc7ae Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sun, 16 Nov 2025 03:02:12 +0100 Subject: [PATCH 083/170] re-enable raw build flags checks for USB mode only checking CPPDEFINES sometimes misses the flag --- pio-scripts/conditional_usb_mode.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/pio-scripts/conditional_usb_mode.py b/pio-scripts/conditional_usb_mode.py index e3a277bf..738a3afa 100644 --- a/pio-scripts/conditional_usb_mode.py +++ b/pio-scripts/conditional_usb_mode.py @@ -39,9 +39,9 @@ def has_cdc_on_boot_enabled(env): return True # # Check in raw build flags - results can be misleading, because this ignores build_unflags - # for flag in build_flags: - # if isinstance(flag, str) and 'ARDUINO_USB_CDC_ON_BOOT=1' in flag: - # return True + for flag in build_flags: + if isinstance(flag, str) and 'ARDUINO_USB_CDC_ON_BOOT=1' in flag: + return True return False @@ -61,9 +61,9 @@ def has_usb_mode_enabled(env): return True # Check in raw build flags - results can be misleading, because this ignores build_unflags - # for flag in build_flags: - # if isinstance(flag, str) and 'ARDUINO_USB_MODE=1' in flag: - # return True + for flag in build_flags: + if isinstance(flag, str) and 'ARDUINO_USB_MODE=1' in flag: + return True return False From 53130f721657d8ccedc0c420797fcafdf1cfd5c5 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sun, 16 Nov 2025 13:28:28 +0100 Subject: [PATCH 084/170] conditional USB mode: first check build_unflags * build_unflags have priority over build_flags, so we first check if the flag is already "unflaged" This finally seems to catch all cases properly :) --- pio-scripts/conditional_usb_mode.py | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/pio-scripts/conditional_usb_mode.py b/pio-scripts/conditional_usb_mode.py index 738a3afa..cb737300 100644 --- a/pio-scripts/conditional_usb_mode.py +++ b/pio-scripts/conditional_usb_mode.py @@ -29,8 +29,14 @@ def has_cdc_on_boot_enabled(env): Returns True if CDC_ON_BOOT=1, False otherwise. This is used to identify boards with USB-OTG (native USB) vs UART-to-USB chips. """ - cpp_defines = env.get('CPPDEFINES', []) + build_unflags = env.get('BUILD_UNFLAGS', []) build_flags = env.get('BUILD_FLAGS', []) + cpp_defines = env.get('CPPDEFINES', []) + + # Check in raw build unflags - unflags have priority over flags + for unflag in build_unflags: + if isinstance(unflag, str) and 'ARDUINO_USB_CDC_ON_BOOT=1' in unflag: + return False # Check in CPPDEFINES for define in cpp_defines: @@ -51,8 +57,13 @@ def has_usb_mode_enabled(env): Returns True if USB_MODE=1, False otherwise. """ - cpp_defines = env.get('CPPDEFINES', []) + build_unflags = env.get('BUILD_UNFLAGS', []) build_flags = env.get('BUILD_FLAGS', []) + cpp_defines = env.get('CPPDEFINES', []) + # Check in raw build unflags - unflags have priority over flags + for unflag in build_unflags: + if isinstance(unflag, str) and 'ARDUINO_USB_MODE=1' in unflag: + return False # Check in CPPDEFINES for define in cpp_defines: From 5b52ee612f404e22cb92c04f260c75bf047f5318 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sun, 16 Nov 2025 14:05:30 +0100 Subject: [PATCH 085/170] clean up handling of USB-CDC Serial when ARDUINO_USB_CDC_ON_BOOT is set, USB-CDC pins are always assigned to 'Serial'. --- wled00/wled_serial.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/wled00/wled_serial.cpp b/wled00/wled_serial.cpp index dfa0bba4..d152ab02 100644 --- a/wled00/wled_serial.cpp +++ b/wled00/wled_serial.cpp @@ -93,9 +93,12 @@ bool canUseSerial(void) { // WLEDMM returns true if Serial can be used for deb void handleSerial() { +#if !ARDUINO_USB_CDC_ON_BOOT + // some USB-CDC boards.json set RX and TX to the USB+ and USB- pins. These pins cannot be assigned to other purposes, so always availeable if (pinManager.isPinAllocated(hardwareRX)) return; - if (!Serial) return; // arduino docs: `if (Serial)` indicates whether or not the USB CDC serial connection is open. For all non-USB CDC ports, this will always return true +#endif if (((pinManager.isPinAllocated(hardwareTX)) && (pinManager.getPinOwner(hardwareTX) != PinOwner::DebugOut))) return; // WLEDMM serial TX is necessary for adalight / TPM2 + if (!Serial) return; // arduino docs: `if (Serial)` indicates whether or not the USB CDC serial connection is open. For all non-USB CDC ports, this will always return true #ifdef WLED_ENABLE_ADALIGHT static auto state = AdaState::Header_A; From 737b7cc4710049d91aa633b2cc27d003c95100b4 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sun, 16 Nov 2025 14:52:18 +0100 Subject: [PATCH 086/170] bus robustness improvement ABL and SerializeConfig explicitly check bus->isOK(), instead of relying on bus->getLength() == 0 --- wled00/FX_fcn.cpp | 1 + wled00/cfg.cpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index b3b9cc54..879b93a2 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -2052,6 +2052,7 @@ void WS2812FX::estimateCurrentAndLimitBri() { for (uint_fast8_t bNum = 0; bNum < busses.getNumBusses(); bNum++) { Bus *bus = busses.getBus(bNum); + if (!bus || !bus->isOk()) continue; // WLEDMM skip busses that are not initialized yet auto btype = bus->getType(); if (EXCLUDE_FROM_ABL(btype)) continue; // WLEDMM exclude non-ABL and network busses uint16_t len = bus->getLength(); diff --git a/wled00/cfg.cpp b/wled00/cfg.cpp index 069b303a..6a6849bd 100644 --- a/wled00/cfg.cpp +++ b/wled00/cfg.cpp @@ -817,7 +817,7 @@ void serializeConfig() { for (uint8_t s = 0; s < busses.getNumBusses(); s++) { Bus *bus = busses.getBus(s); - if (!bus || bus->getLength()==0) break; + if (!bus || !bus->isOk() || bus->getLength()==0) break; // WLEDMM exclude not initialized busses JsonObject ins = hw_led_ins.createNestedObject(); ins["start"] = bus->getStart(); ins["len"] = bus->getLength(); From b443c13ad8433444709d06085cfd2a9b8ca9b2e5 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sun, 16 Nov 2025 15:28:57 +0100 Subject: [PATCH 087/170] revert safety check in cfg.cpp this leads to UI problems in the LEDs setting page. --- wled00/cfg.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wled00/cfg.cpp b/wled00/cfg.cpp index 6a6849bd..069b303a 100644 --- a/wled00/cfg.cpp +++ b/wled00/cfg.cpp @@ -817,7 +817,7 @@ void serializeConfig() { for (uint8_t s = 0; s < busses.getNumBusses(); s++) { Bus *bus = busses.getBus(s); - if (!bus || !bus->isOk() || bus->getLength()==0) break; // WLEDMM exclude not initialized busses + if (!bus || bus->getLength()==0) break; JsonObject ins = hw_led_ins.createNestedObject(); ins["start"] = bus->getStart(); ins["len"] = bus->getLength(); From 2a120e81f83eaa7d9672ccef8f4be5e4bd14ccd3 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sun, 16 Nov 2025 16:08:16 +0100 Subject: [PATCH 088/170] image effect: flicker fixer for WS2812b leds driven by RMT Large file read operations can cause RMT stall leading to flicker. * wait for RMT driver when lading a new gif, and when decoding a new frame. --- wled00/image_loader.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/wled00/image_loader.cpp b/wled00/image_loader.cpp index b6d13efa..96e131d5 100644 --- a/wled00/image_loader.cpp +++ b/wled00/image_loader.cpp @@ -141,6 +141,11 @@ byte renderImageToSegment(Segment &seg) { USER_PRINTF("GIF decoder unsupported file: %s\n", lastFilename); return IMAGE_ERROR_UNSUPPORTED_FORMAT; } + + // flicker fixer: if we have ws2812b leds, lets wait a moment until RMT output is done. + unsigned t0 = millis(); + while (strip.isUpdating() && (millis() - t0 < 100)) delay(1); // up to 100 ms = good enough for up to 1800 LEDs per output + if (file) file.close(); if (!openGif(lastFilename)) { gifDecodeFailed = true; @@ -218,6 +223,10 @@ byte renderImageToSegment(Segment &seg) { // TODO consider handling this on FX level with a different frametime, but that would cause slow gifs to speed up during transitions if (millis() - lastFrameDisplayTime < wait) return IMAGE_ERROR_WAITING; + // flicker fixer: if we have ws2812b leds, lets wait a moment until RMT output is done. + unsigned td0 = millis(); + while (strip.isUpdating() && (millis() - td0 < 20)) delay(1); // wait up to 20ms for LED output to finish + int result = decoder.decodeFrame(false); if (result < 0) { USER_PRINTF("GIF Decoding error %d in decodeFrame().\n", result); From 16540f58b3dd60b9e2b36c4be60572d978e5e2f2 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sun, 16 Nov 2025 19:18:21 +0100 Subject: [PATCH 089/170] (experimental) adjust image scaling when segment options change during playback * move scaling calculation and decoder.setDrawPixelCallback() into a separate function *re-calculate scaling before decoding a new frame * reset gifWidth and gifHeight to zero in endplayback --- wled00/image_loader.cpp | 48 +++++++++++++++++++++++++---------------- 1 file changed, 29 insertions(+), 19 deletions(-) diff --git a/wled00/image_loader.cpp b/wled00/image_loader.cpp index 96e131d5..24e5a003 100644 --- a/wled00/image_loader.cpp +++ b/wled00/image_loader.cpp @@ -49,7 +49,7 @@ bool openGif(const char *filename) { // side-effect: updates "file" } static Segment* activeSeg; -static uint16_t gifWidth, gifHeight; // these two must stay uint16_t, because they are passed by reference +static uint16_t gifWidth = 0, gifHeight = 0; // these two must stay uint16_t, because they are passed by reference static unsigned segCols = 1; static unsigned segRows = 1; static unsigned segLen = 1; // for 1D and 1DExpand support @@ -107,6 +107,29 @@ void drawPixelCallback2D(int16_t x, int16_t y, uint8_t red, uint8_t green, uint8 } } +// calculate image scaling; updates scaling factors and sets the best pixel drawing callback +static void calculateScaling() { + if (gifDecodeFailed) return; + if ((gifWidth > 0 && gifHeight > 0)) { + if (activeSeg->is2D()) { + perPixelX = (segCols + gifWidth -1) / gifWidth; + perPixelY = (segRows + gifHeight-1) / gifHeight; + if (segCols != gifWidth || segRows != gifHeight) { + decoder.setDrawPixelCallback(drawPixelCallback2D); // use 2D callback with scaling + } else { + decoder.setDrawPixelCallback(drawPixelCallbackNoScale2D); // use 2D callback without scaling + } + } else { + int totalImgPix = (int)gifWidth * gifHeight; + if (totalImgPix - segLen == 1) totalImgPix--; // handle off-by-one: skip last pixel instead of first (gifs constructed from 1D input pad last pixel if length is odd) + perPixelX = (segLen + totalImgPix-1) / totalImgPix; + if (totalImgPix != segLen) { + decoder.setDrawPixelCallback(drawPixelCallback1D); // use 1D callback with scaling + } + } + } +} + #define IMAGE_ERROR_NONE 0 #define IMAGE_ERROR_NO_NAME 1 #define IMAGE_ERROR_SEG_LIMIT 2 @@ -192,24 +215,7 @@ byte renderImageToSegment(Segment &seg) { USER_PRINTF("Invalid GIF dimensions: %dx%d\n", gifWidth, gifHeight); return IMAGE_ERROR_GIF_DECODE; } - if (activeSeg->is2D()) { - perPixelX = (segCols + gifWidth -1) / gifWidth; - perPixelY = (segRows + gifHeight-1) / gifHeight; - if (segCols != gifWidth || segRows != gifHeight) { - decoder.setDrawPixelCallback(drawPixelCallback2D); // use 2D callback with scaling - //DEBUG_PRINTLN(F("scaling image")); - } else { - decoder.setDrawPixelCallback(drawPixelCallbackNoScale2D); // use 2D callback without scaling - } - } else { - int totalImgPix = (int)gifWidth * gifHeight; - if (totalImgPix - segLen == 1) totalImgPix--; // handle off-by-one: skip last pixel instead of first (gifs constructed from 1D input pad last pixel if length is odd) - perPixelX = (segLen + totalImgPix-1) / totalImgPix; - if (totalImgPix != segLen) { - decoder.setDrawPixelCallback(drawPixelCallback1D); // use 1D callback with scaling - //DEBUG_PRINTLN(F("scaling image")); - } - } + calculateScaling(); } if (gifDecodeFailed) return IMAGE_ERROR_PREV; @@ -227,6 +233,9 @@ byte renderImageToSegment(Segment &seg) { unsigned td0 = millis(); while (strip.isUpdating() && (millis() - td0 < 20)) delay(1); // wait up to 20ms for LED output to finish + // WLEDMM experimental: segment options might change (mirror, transpose, grouping, spacing) at any time + calculateScaling(); // --> re-calculate scaling for each frame + int result = decoder.decodeFrame(false); if (result < 0) { USER_PRINTF("GIF Decoding error %d in decodeFrame().\n", result); @@ -247,6 +256,7 @@ void endImagePlayback(Segment *seg) { if (!activeSeg || activeSeg != seg) return; if (file) file.close(); decoder.dealloc(); + gifWidth = 0; gifHeight = 0; // WLEDMM clear cached image dimensions gifDecodeFailed = false; activeSeg = nullptr; strcpy(lastFilename, "/"); // reset filename From 47153baa0cecc8b59b6a90a000608f4b62969edf Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sun, 16 Nov 2025 19:30:34 +0100 Subject: [PATCH 090/170] brackets (typo) does the same thing as before, but looks clearer. --- wled00/image_loader.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wled00/image_loader.cpp b/wled00/image_loader.cpp index 24e5a003..a289c722 100644 --- a/wled00/image_loader.cpp +++ b/wled00/image_loader.cpp @@ -110,7 +110,7 @@ void drawPixelCallback2D(int16_t x, int16_t y, uint8_t red, uint8_t green, uint8 // calculate image scaling; updates scaling factors and sets the best pixel drawing callback static void calculateScaling() { if (gifDecodeFailed) return; - if ((gifWidth > 0 && gifHeight > 0)) { + if ((gifWidth > 0) && (gifHeight > 0)) { if (activeSeg->is2D()) { perPixelX = (segCols + gifWidth -1) / gifWidth; perPixelY = (segRows + gifHeight-1) / gifHeight; From e5ab0b60770aa498cc66bbca91e50588658f8815 Mon Sep 17 00:00:00 2001 From: Damian Schneider Date: Thu, 2 Oct 2025 20:40:43 +0200 Subject: [PATCH 091/170] Bugfix for gif player WRT inactive segment and bugfix in copy FX - if a segment is destroyed or turned inactive, disable the gif player: only one gif player instance can run at a time, if a inactive or destroyed segment uses it, the effect is broken for other segments. - copy FX ironically copied the source segment on each call, should use reference not a copy! --- wled00/FX.h | 7 +++++++ wled00/FX_fcn.cpp | 3 +++ 2 files changed, 10 insertions(+) diff --git a/wled00/FX.h b/wled00/FX.h index 32086c50..ad1fd292 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -16,6 +16,10 @@ bool canUseSerial(void); // WLEDMM implemented in wled_serial.cpp void strip_wait_until_idle(String whoCalledMe); // WLEDMM implemented in FX_fcn.cpp bool strip_uses_global_leds(void) __attribute__((pure)); // WLEDMM implemented in FX_fcn.cpp +#ifdef WLED_ENABLE_GIF +struct Segment; // forward declaration +void endImagePlayback(Segment *seg); // implemented in image_loader.cpp +#endif #define FASTLED_INTERNAL //remove annoying pragma messages #define USE_GET_MILLISECOND_TIMER @@ -585,6 +589,9 @@ typedef struct Segment { #ifdef ARDUINO_ARCH_ESP32 strip_wait_until_idle("~Segment()"); #endif + #ifdef WLED_ENABLE_GIF + endImagePlayback(this); + #endif if ((Segment::_globalLeds == nullptr) && !strip_uses_global_leds() && (ledsrgb != nullptr)) {free(ledsrgb); ledsrgb = nullptr;} // WLEDMM we need "!strip_uses_global_leds()" to avoid crashes (#104) if (name) { delete[] name; name = nullptr; } diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index 879b93a2..991ed761 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -542,6 +542,9 @@ void Segment::setUp(uint16_t i1, uint16_t i2, uint8_t grp, uint8_t spc, uint16_t if (stop>start) markForBlank(); //turn old segment range off // WLEDMM stop > start // toDo: check if this can be skipped when boundsUnchanged if (i2 <= i1) { //disable segment + #ifdef WLED_ENABLE_GIF + endImagePlayback(this); + #endif stop = 0; markForReset(); return; From eab946ea8768b3e8fe77c3761ff61db36634cc30 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Mon, 17 Nov 2025 12:29:47 +0100 Subject: [PATCH 092/170] image loader: allow graceful takeover after error Allow decoder "takeover" by another segment a) when last segment has decoding error (unsupported file, etc.) b) when last segment became inactive --- wled00/image_loader.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/wled00/image_loader.cpp b/wled00/image_loader.cpp index a289c722..2f922fea 100644 --- a/wled00/image_loader.cpp +++ b/wled00/image_loader.cpp @@ -146,7 +146,13 @@ byte renderImageToSegment(Segment &seg) { if (!seg.name) return IMAGE_ERROR_NO_NAME; // disable during effect transition, causes flickering, multiple allocations and depending on image, part of old FX remaining //if (seg.mode != seg.currentMode()) return IMAGE_ERROR_WAITING; - if (activeSeg && activeSeg != &seg) return IMAGE_ERROR_SEG_LIMIT; // only one segment at a time + if (activeSeg && activeSeg != &seg) { // only one segment at a time + if (!seg.isActive()) return IMAGE_ERROR_SEG_LIMIT; // sanity check: calling segment must be active + if (gifDecodeFailed || !activeSeg->isActive()) // decoder failed, or last segment became inactive + endImagePlayback(activeSeg); // => allow takeover but clean up first + else + return IMAGE_ERROR_SEG_LIMIT; + } activeSeg = &seg; segCols = activeSeg->virtualWidth(); From d6ee51841b4aebbac7e2e02a68f96fbeddcf0a6e Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Mon, 17 Nov 2025 14:27:08 +0100 Subject: [PATCH 093/170] image loader: avoid message flood on error in case that several "bad" image effect segments competing to use the GIF decoder, we had a flood of repeating user_print messages --- wled00/image_loader.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/wled00/image_loader.cpp b/wled00/image_loader.cpp index 2f922fea..2b4c4745 100644 --- a/wled00/image_loader.cpp +++ b/wled00/image_loader.cpp @@ -167,7 +167,7 @@ byte renderImageToSegment(Segment &seg) { size_t fnameLen = strlen(lastFilename); if ((fnameLen < 4) || strcmp(lastFilename + fnameLen - 4, ".gif") != 0) { // empty segment name, name too short, or name not ending in .gif gifDecodeFailed = true; - USER_PRINTF("GIF decoder unsupported file: %s\n", lastFilename); + DEBUG_PRINTF("GIF decoder unsupported file: %s\n", lastFilename); // can cause message flood if two segments compete over one decoder instance return IMAGE_ERROR_UNSUPPORTED_FORMAT; } @@ -221,6 +221,7 @@ byte renderImageToSegment(Segment &seg) { USER_PRINTF("Invalid GIF dimensions: %dx%d\n", gifWidth, gifHeight); return IMAGE_ERROR_GIF_DECODE; } + USER_PRINTF("Started GIF decoding %dx%d pixels -> %dx%d Segment\n", gifWidth, gifHeight, segCols, segRows); calculateScaling(); } @@ -262,7 +263,7 @@ void endImagePlayback(Segment *seg) { if (!activeSeg || activeSeg != seg) return; if (file) file.close(); decoder.dealloc(); - gifWidth = 0; gifHeight = 0; // WLEDMM clear cached image dimensions + gifWidth = 0; gifHeight = 0; // clear cached image dimensions gifDecodeFailed = false; activeSeg = nullptr; strcpy(lastFilename, "/"); // reset filename From deaee3755969b7aab03e46b36778ba475403115b Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Mon, 17 Nov 2025 14:30:29 +0100 Subject: [PATCH 094/170] (experimental) 2D drawPixel optimizations * add a dedicated callback for 2D downscaling only (no nested for loop) -> up to 10% faster * minor optimizations for 2D up/downscale drawpixel - move repeated calculations out of the inner loop -> small speedup --- wled00/image_loader.cpp | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/wled00/image_loader.cpp b/wled00/image_loader.cpp index 2b4c4745..bc73a8fc 100644 --- a/wled00/image_loader.cpp +++ b/wled00/image_loader.cpp @@ -99,13 +99,28 @@ void drawPixelCallback2D(int16_t x, int16_t y, uint8_t red, uint8_t green, uint8 // Pack coordinates uniquely: outY into upper 16 bits, outX into lower 16 bits if (((outY << 16) | outX) == lastCoordinate) return; // skip setting same coordinate again lastCoordinate = (outY << 16) | outX; // since input is a "scanline" this is sufficient to identify a "unique" coordinate + // pre-calculate final pixel color - avoids repetition inside the loop + red = gamma8(red); green=gamma8(green); blue=gamma8(blue); + uint32_t pColor = RGBW32(red, green, blue, 0); // set multiple pixels if upscaling // softhack007: changed loop x/y order -> minor speedup from better cache locality for (int j = 0; j < perPixelY; j++) { + int pixelY = outY + j; for (int i = 0; i < perPixelX; i++) { - activeSeg->setPixelColorXY(outX + i, outY + j, gamma8(red), gamma8(green), gamma8(blue)); + int pixelX = outX + i; + activeSeg->setPixelColorXY(pixelX, pixelY, pColor); } } } +// WLEDMM 2D without upscaling loop - up to 10% faster +void drawPixelCallbackDownScale2D(int16_t x, int16_t y, uint8_t red, uint8_t green, uint8_t blue) { + // simple nearest-neighbor downscaling + int outX = (int)x * segCols / gifWidth; + int outY = (int)y * segRows / gifHeight; + int32_t newCoordinate = ((outY << 16) | outX); + if (newCoordinate == lastCoordinate) return; // skip setting same coordinate again + lastCoordinate = newCoordinate; + activeSeg->setPixelColorXY(outX, outY, gamma8(red), gamma8(green), gamma8(blue)); +} // calculate image scaling; updates scaling factors and sets the best pixel drawing callback static void calculateScaling() { @@ -115,7 +130,10 @@ static void calculateScaling() { perPixelX = (segCols + gifWidth -1) / gifWidth; perPixelY = (segRows + gifHeight-1) / gifHeight; if (segCols != gifWidth || segRows != gifHeight) { - decoder.setDrawPixelCallback(drawPixelCallback2D); // use 2D callback with scaling + if ((perPixelX <2) && (perPixelY <2)) + decoder.setDrawPixelCallback(drawPixelCallbackDownScale2D);// use 2D callback with downscaling only + else + decoder.setDrawPixelCallback(drawPixelCallback2D); // use 2D callback with full scaling } else { decoder.setDrawPixelCallback(drawPixelCallbackNoScale2D); // use 2D callback without scaling } From 872c38f3c2f1d2817fd70210236f49a2026aa2a2 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Mon, 17 Nov 2025 19:30:52 +0100 Subject: [PATCH 095/170] (experimental) HUB75 small speedups * removed unnecessary sanity checks from sPC and gPC * gPC: use inline color_fade() instead of FastLED .scale8() in my tests on -S3 this gives a small speedup, 2% up to 6% --- wled00/bus_manager.cpp | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/wled00/bus_manager.cpp b/wled00/bus_manager.cpp index bfeb6616..8d4a6f01 100644 --- a/wled00/bus_manager.cpp +++ b/wled00/bus_manager.cpp @@ -923,6 +923,8 @@ BusHub75Matrix::BusHub75Matrix(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWh #endif USER_PRINTF("MatrixPanel_I2S_DMA config - %ux%u (type %u) length: %u, %u bits/pixel.\n", mxconfig.mx_width, mxconfig.mx_height, bc.type, mxconfig.chain_length, mxconfig.getPixelColorDepthBits() * 3); + USER_PRINTF("MatrixPanel_I2S_DMA config - clock phase = %s, latch_blanking = %d, min refresh = %d fps.\n", + mxconfig.clkphase ? "positive edge":"negative edge", int(mxconfig.latch_blanking), int(mxconfig.min_refresh_rate)); DEBUG_PRINT(F("Free heap: ")); DEBUG_PRINTLN(ESP.getFreeHeap()); lastHeap = ESP.getFreeHeap(); // check if we can re-use the existing display driver @@ -1106,26 +1108,31 @@ BusHub75Matrix::BusHub75Matrix(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWh } void __attribute__((hot)) IRAM_ATTR BusHub75Matrix::setPixelColor(uint16_t pix, uint32_t c) { - if ( pix >= _len) return; +// if ( pix >= _len) return; // not necessary - this was already checked at busses.setPixelColor() #if 0 if ((correctWB) && (_cct >= 1900)) c = colorBalanceFromKelvin(_cct, c); //color correction from CCT - reduces framerate by up to 10%. If you still want it, change the line above to "#if 1" #endif - if (_ledBuffer) { +// if (_ledBuffer) { // not necessary - isOk() would return false if buffer is not availeable CRGB fastled_col = CRGB(c); if (_ledBuffer[pix] != fastled_col) { _ledBuffer[pix] = fastled_col; setBitInArray(_ledsDirty, pix, true); // flag pixel as "dirty" } - } +// } } +// needed to mimic NeoPixelBus, which returns scaled-down colours uint32_t IRAM_ATTR BusHub75Matrix::getPixelColor(uint16_t pix) const { - if (pix >= _len || !_ledBuffer) return BLACK; - return uint32_t(_ledBuffer[pix].scale8(_bri)) & 0x00FFFFFF; // scale8() is needed to mimic NeoPixelBus, which returns scaled-down colours +// if (pix >= _len || !_ledBuffer) return BLACK; // not necessary - this was already checked at busses.getPixelColor() +#if defined(WLEDMM_FASTPATH) && !defined(WLEDMM_SAVE_FLASH) + return color_fade(uint32_t(_ledBuffer[pix]) & 0x00FFFFFF, _bri); // this is slightly faster if we have inline color_fade() +#else + return uint32_t(_ledBuffer[pix].scale8(_bri)) & 0x00FFFFFF; // do it the FastLED way +#endif } uint32_t __attribute__((hot)) IRAM_ATTR BusHub75Matrix::getPixelColorRestored(uint16_t pix) const { - if (pix >= _len || !_ledBuffer) return BLACK; +// if (pix >= _len || !_ledBuffer) return BLACK; // not necessary - this was already checked at busses.getPixelColorRestored() return uint32_t(_ledBuffer[pix]) & 0x00FFFFFF; } From bc7a96d7d42382236dfaa14468b210247196669d Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Tue, 18 Nov 2025 23:13:47 +0100 Subject: [PATCH 096/170] strip wait function: increase idle wait time to 120ms Updated strip wait function to use longer idle wait time (similar to the timeout used by upstream WLED 0.16) --- wled00/FX_fcn.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index 991ed761..46b37eef 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -56,13 +56,13 @@ static portMUX_TYPE s_wled_strip_mux = portMUX_INITIALIZER_UNLOCKED; // to prote #error "Max segments must be at least max number of busses!" #endif -// WLEDMM experimental . this is a "C style" wrapper for strip.waitUntilIdle() +// WLEDMM experimental . this is a "C style" wrapper for strip.() // This workaround is just needed for the segment class, that does't know about "strip" void strip_wait_until_idle(String whoCalledMe) { #if defined(ARDUINO_ARCH_ESP32) && defined(WLEDMM_PROTECT_SERVICE) // WLEDMM experimental if (strip.isServicing() && (strncmp(pcTaskGetTaskName(NULL), "loopTask", 8) != 0)) { // if we are in looptask (arduino loop), its safe to proceed without waiting USER_PRINTLN(whoCalledMe + String(": strip is still drawing effects.")); - strip.waitUntilIdle(); + strip.(); } #endif } @@ -1893,7 +1893,8 @@ void WS2812FX::finalizeInit(void) // WLEDMM wait until strip is idle (=not servicing). // on 8266 this function does nothing, because we can only do "busy waiting" on ESP32 -#define MAX_IDLE_WAIT_MS 50 // seems to work in most cases +//#define MAX_IDLE_WAIT_MS 50 // seems to work in most cases +#define MAX_IDLE_WAIT_MS 120 // better safe than sorry - similar to the timeout used by upstream WLED void WS2812FX::waitUntilIdle(void) { #if defined(ARDUINO_ARCH_ESP32) && defined(WLEDMM_PROTECT_SERVICE) if (isServicing()) { From 1583452c8690ab9c30736b30704c35139b55210f Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Tue, 18 Nov 2025 23:19:25 +0100 Subject: [PATCH 097/170] oops fixes a mistake in previous commit --- wled00/FX_fcn.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index 46b37eef..73eea00c 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -56,13 +56,13 @@ static portMUX_TYPE s_wled_strip_mux = portMUX_INITIALIZER_UNLOCKED; // to prote #error "Max segments must be at least max number of busses!" #endif -// WLEDMM experimental . this is a "C style" wrapper for strip.() +// WLEDMM experimental . this is a "C style" wrapper for strip.waitUntilIdle(); // This workaround is just needed for the segment class, that does't know about "strip" void strip_wait_until_idle(String whoCalledMe) { #if defined(ARDUINO_ARCH_ESP32) && defined(WLEDMM_PROTECT_SERVICE) // WLEDMM experimental if (strip.isServicing() && (strncmp(pcTaskGetTaskName(NULL), "loopTask", 8) != 0)) { // if we are in looptask (arduino loop), its safe to proceed without waiting USER_PRINTLN(whoCalledMe + String(": strip is still drawing effects.")); - strip.(); + strip.waitUntilIdle(); } #endif } From 0a0ca506eb18f762d28445e579786874da9723c4 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Tue, 18 Nov 2025 23:35:15 +0100 Subject: [PATCH 098/170] Add WLEDMM_FASTPATH definition for all esp32 builds force all esp32 builds to use WLEDMM_FASTPATH. The code is proven in use, while non-fastpath is becoming obsolete. --- wled00/wled.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/wled00/wled.h b/wled00/wled.h index 2778ed21..138157a7 100644 --- a/wled00/wled.h +++ b/wled00/wled.h @@ -87,6 +87,9 @@ // WLEDMM MANDATORY flags #define WLEDMM_PROTECT_SERVICE // prevents crashes when effects are drawing while asyncWebServer tries to modify segments at the same time +#if !defined(WLEDMM_FASTPATH) && !defined(ESP8266) +#define WLEDMM_FASTPATH // all WLED-MM build are FASTPATH +#endif // Library inclusions. #include From 219355d047d35c77eadd727cf665a40cd627e3c9 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Tue, 18 Nov 2025 23:57:44 +0100 Subject: [PATCH 099/170] AR audio sync: improved sequence check for audio packet handling currently just a comment so I don't forget about it :-) needs some testing but very sure this will work. --- usermods/audioreactive/audio_reactive.h | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/usermods/audioreactive/audio_reactive.h b/usermods/audioreactive/audio_reactive.h index 406ae316..9a9a4e7d 100644 --- a/usermods/audioreactive/audio_reactive.h +++ b/usermods/audioreactive/audio_reactive.h @@ -1754,7 +1754,15 @@ class AudioReactive : public Usermod { // add info for UI if ((receivedPacket.frameCounter > 0) && (lastFrameCounter > 0)) receivedFormat = 3; // v2+ else receivedFormat = 2; // v2 - // check sequence + + // Simpler 8-bit rollover-safe sequence check: + // (int8_t)(cur - prev) > 0 => cur is ahead of prev by 1..127 + // 0 => duplicate, + // < 0 => older + // bool sequenceOK = !audioSyncSequence || receivedPacket.frameCounter == 0 || // always accept legacy "0" + // ((int8_t)(receivedPacket.frameCounter - lastFrameCounter) > 0); + + // check sequence bool sequenceOK = false; if(receivedPacket.frameCounter > lastFrameCounter) sequenceOK = true; // sequence OK if((lastFrameCounter < 12) && (receivedPacket.frameCounter > 248)) sequenceOK = false; // prevent sequence "roll-back" due to late packets (1->254) From 43ab0dd468100872af2348f56b00ed1661694e86 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Wed, 19 Nov 2025 17:07:30 +0100 Subject: [PATCH 100/170] Full Codepage 437 support part1: * enable all bitmaps already defined in the font files (increases firmware by ~7KB) * add traslation for unicode -> codepage437 (as used by font files) --- wled00/src/font/codepage437.cpp | 211 ++ wled00/src/font/codepages.h | 5 + wled00/src/font/console_font_4x6.h | 1949 +++++++------- wled00/src/font/console_font_5x12.h | 3884 ++++++++++++++------------- wled00/src/font/console_font_5x8.h | 2595 +++++++++--------- wled00/src/font/console_font_6x8.h | 2596 +++++++++--------- wled00/src/font/console_font_7x9.h | 2919 ++++++++++---------- 7 files changed, 7230 insertions(+), 6929 deletions(-) create mode 100644 wled00/src/font/codepage437.cpp create mode 100644 wled00/src/font/codepages.h diff --git a/wled00/src/font/codepage437.cpp b/wled00/src/font/codepage437.cpp new file mode 100644 index 00000000..cea00454 --- /dev/null +++ b/wled00/src/font/codepage437.cpp @@ -0,0 +1,211 @@ +#if defined(WLED_ENABLE_FULL_FONTS) + +#include "codepages.h" + +// translates unicode 2-byte (UTF-16) "code points" into corresponding characters in codepage 347 (IBM PC aka PC-8) +// based on a table from https://en.wikipedia.org/wiki/Code_page_437#Character_set +uint16_t wchar16ToCodepage437(uint16_t wideChar) { + + // codes up to 126 are same as ASCII + if (wideChar < 127) return wideChar; + + switch (wideChar) { + // characters 1 - 31 + case 0x263A: return 0x01; break; // ☺︎ + case 0x263B: return 0x02; break; // ☻ + case 0x2665: return 0x03; break; // ♥︎ + case 0x2666: return 0x04; break; // ♦︎ + case 0x2663: return 0x05; break; // ♣︎ + case 0x2660: return 0x06; break; // ♠︎ + case 0x2022: return 0x07; break; // • + case 0x25D8: return 0x08; break; // ◘ + case 0x25CB: return 0x09; break; // ○ + case 0x25D9: return 0x0A; break; // ◙ + case 0x2642: return 0x0B; break; // ♂︎ + case 0x2640: return 0x0C; break; // ♀︎ + case 0x266A: return 0x0D; break; // ♪ + case 0x266B: return 0x0E; break; // ♫ + case 0x263C: return 0x0F; break; // ☼ + case 0x25BA: return 0x10; break; // ► + case 0x25C4: return 0x11; break; // ◄ + case 0x2195: return 0x12; break; // ↕︎ + case 0x203C: return 0x13; break; // ‼︎ + case 0x00B6: return 0x14; break; // ¶ + case 0x00A7: return 0x15; break; // § + case 0x25AC: return 0x16; break; // ▬ + case 0x21A8: return 0x17; break; // ↨ + case 0x2191: return 0x18; break; // ↑ + case 0x2193: return 0x19; break; // ↓ + case 0x2192: return 0x1A; break; // → + case 0x2190: return 0x1B; break; // ← + case 0x221F: return 0x1C; break; // ∟ + case 0x2194: return 0x1D; break; // ↔︎ + case 0x25B2: return 0x1E; break; // ▲ + case 0x25BC: return 0x1F; break; // ▼ + + // characters 127 - 254 + case 0x2302: return 0x7F; break; // ⌂ + case 0x00C7: return 0x80; break; // Ç + case 0x00FC: return 0x81; break; // ü + case 0x00E9: return 0x82; break; // é + case 0x00E2: return 0x83; break; // â + case 0x00E4: return 0x84; break; // ä + case 0x00E0: return 0x85; break; // à + case 0x00E5: return 0x86; break; // å + case 0x00E7: return 0x87; break; // ç + case 0x00EA: return 0x88; break; // ê + case 0x00EB: return 0x89; break; // ë + case 0x00E8: return 0x8A; break; // è + case 0x00EF: return 0x8B; break; // ï + case 0x00EE: return 0x8C; break; // î + case 0x00EC: return 0x8D; break; // ì + case 0x00C4: return 0x8E; break; // Ä + case 0x00C5: return 0x8F; break; // Å + case 0x00C9: return 0x90; break; // É + case 0x00E6: return 0x91; break; // æ + case 0x00C6: return 0x92; break; // Æ + case 0x00F4: return 0x93; break; // ô + case 0x00F6: return 0x94; break; // ö + case 0x00F2: return 0x95; break; // ò + case 0x00FB: return 0x96; break; // û + case 0x00F9: return 0x97; break; // ù + case 0x00FF: return 0x98; break; // ÿ + case 0x00D6: return 0x99; break; // Ö + case 0x00DC: return 0x9A; break; // Ü + case 0x00A2: return 0x9B; break; // ¢ + case 0x00A3: return 0x9C; break; // £ + case 0x00A5: return 0x9D; break; // ¥ + case 0x20A7: return 0x9E; break; // ₧ + case 0x0192: return 0x9F; break; // ƒ + case 0x00E1: return 0xA0; break; // á + case 0x00ED: return 0xA1; break; // í + case 0x00F3: return 0xA2; break; // ó + case 0x00FA: return 0xA3; break; // ú + case 0x00F1: return 0xA4; break; // ñ + case 0x00D1: return 0xA5; break; // Ñ + case 0x00AA: return 0xA6; break; // ª + case 0x00BA: return 0xA7; break; // º + case 0x00BF: return 0xA8; break; // ¿ + case 0x2310: return 0xA9; break; // ⌐ + case 0x00AC: return 0xAA; break; // ¬ + case 0x00BD: return 0xAB; break; // ½ + case 0x00BC: return 0xAC; break; // ¼ + case 0x00A1: return 0xAD; break; // ¡ + case 0x00AB: return 0xAE; break; // « + case 0x00BB: return 0xAF; break; // » + case 0x2591: return 0xB0; break; // ░ + case 0x2592: return 0xB1; break; // ▒ + case 0x2593: return 0xB2; break; // ▓ + case 0x2502: return 0xB3; break; // │ + case 0x2524: return 0xB4; break; // ┤ + case 0x2561: return 0xB5; break; // ╡ + case 0x2562: return 0xB6; break; // ╢ + case 0x2556: return 0xB7; break; // ╖ + case 0x2555: return 0xB8; break; // ╕ + case 0x2563: return 0xB9; break; // ╣ + case 0x2551: return 0xBA; break; // ║ + case 0x2557: return 0xBB; break; // ╗ + case 0x255D: return 0xBC; break; // ╝ + case 0x255C: return 0xBD; break; // ╜ + case 0x255B: return 0xBE; break; // ╛ + case 0x2510: return 0xBF; break; // ┐ + case 0x2514: return 0xC0; break; // └ + case 0x2534: return 0xC1; break; // ┴ + case 0x252C: return 0xC2; break; // ┬ + case 0x251C: return 0xC3; break; // ├ + case 0x2500: return 0xC4; break; // ─ + case 0x253C: return 0xC5; break; // ┼ + case 0x255E: return 0xC6; break; // ╞ + case 0x255F: return 0xC7; break; // ╟ + case 0x255A: return 0xC8; break; // ╚ + case 0x2554: return 0xC9; break; // ╔ + case 0x2569: return 0xCA; break; // ╩ + case 0x2566: return 0xCB; break; // ╦ + case 0x2560: return 0xCC; break; // ╠ + case 0x2550: return 0xCD; break; // ═ + case 0x256C: return 0xCE; break; // ╬ + case 0x2567: return 0xCF; break; // ╧ + case 0x2568: return 0xD0; break; // ╨ + case 0x2564: return 0xD1; break; // ╤ + case 0x2565: return 0xD2; break; // ╥ + case 0x2559: return 0xD3; break; // ╙ + case 0x2558: return 0xD4; break; // ╘ + case 0x2552: return 0xD5; break; // ╒ + case 0x2553: return 0xD6; break; // ╓ + case 0x256B: return 0xD7; break; // ╫ + case 0x256A: return 0xD8; break; // ╪ + case 0x2518: return 0xD9; break; // ┘ + case 0x250C: return 0xDA; break; // ┌ + case 0x2588: return 0xDB; break; // █ + case 0x2584: return 0xDC; break; // ▄ + case 0x258C: return 0xDD; break; // ▌ + case 0x2590: return 0xDE; break; // ▐ + case 0x2580: return 0xDF; break; // ▀ + case 0x03B1: return 0xE0; break; // α + case 0x00DF: return 0xE1; break; // ß + case 0x0393: return 0xE2; break; // Γ + case 0x03C0: return 0xE3; break; // π + case 0x03A3: return 0xE4; break; // Σ + case 0x03C3: return 0xE5; break; // σ + case 0x00B5: return 0xE6; break; // µ + case 0x03C4: return 0xE7; break; // τ + case 0x03A6: return 0xE8; break; // Φ + case 0x0398: return 0xE9; break; // Θ + case 0x03A9: return 0xEA; break; // Ω + case 0x03B4: return 0xEB; break; // δ + case 0x221E: return 0xEC; break; // ∞ + case 0x03C6: return 0xED; break; // φ + case 0x03B5: return 0xEE; break; // ε + case 0x2229: return 0xEF; break; // ∩ + case 0x2261: return 0xF0; break; // ≡ + case 0x00B1: return 0xF1; break; // ± + case 0x2265: return 0xF2; break; // ≥ + case 0x2264: return 0xF3; break; // ≤ + case 0x2320: return 0xF4; break; // ⌠ + case 0x2321: return 0xF5; break; // ⌡ + case 0x00F7: return 0xF6; break; // ÷ + case 0x2248: return 0xF7; break; // ≈ + case 0x00B0: return 0xF8; break; // ° + case 0x2219: return 0xF9; break; // ∙ multiplication dot + case 0x00B7: return 0xFA; break; // · middle dot + case 0x221A: return 0xFB; break; // √ + case 0x207F: return 0xFC; break; // ⁿ + case 0x00B2: return 0xFD; break; // ² + case 0x25A0: return 0xFE; break; // ■ + + // special mappings for very similar characters + case 0x00A6: return 0x7C; break; // broken bar -> bar + case 0x266C: return 14; break; // musical notes + case 0x0394: return 127; break; // greek capital delta Δ + case 0x23AE: return 179; break; // integral extension ⎮ + case 0x03B2: return 225; break; // greek small beta β => sz umlaut ß + case 0x03A0: return 227; break; // greek capital PI Π + case 0x220F: return 227; break; // math product ∏ + case 0x2211: return 228; break; // math sum ∑ + case 0x03BC: return 230; break; // greek mu small μ + case 0x2126: return 234; break; // Ohm Ω + case 0x00F0: return 235; break; // small eth ð + case 0x2202: return 235; break; // math partial derivate ∂ + case 0x03D5: return 237; break; // greek phi small ϕ + case 0x2205: return 237; break; // empty set ∅ + case 0x2300: return 237; break; // diameter ⌀ + case 0x00D8: return 237; break; // 0 strikethrough Ø + case 0x00F8: return 237; break; // 0 strikethrough small ø + case 0x2208: return 238; break; // element-of ∈ + case 0x017F: return 244; break; // long S ſ + + case 0x00A0: return 32; break; // NBSP => blank + case 0x20AC: return 238; break; // Euro € + case 0x2713: return 251; break; // check mark ✓ + + // everything else: unknown + //default: return 32; // blank + default: return 250; // small middle dot · + } + +} + + + + +#endif \ No newline at end of file diff --git a/wled00/src/font/codepages.h b/wled00/src/font/codepages.h new file mode 100644 index 00000000..4ed5799e --- /dev/null +++ b/wled00/src/font/codepages.h @@ -0,0 +1,5 @@ +#include +#include + +// translates unicode 2-byte (UTF-16) "code points" into corresponding characters in codepage 347 (IBM PC aka PC-8) +uint16_t wchar16ToCodepage437(uint16_t wideChar); // codepage437.cpp \ No newline at end of file diff --git a/wled00/src/font/console_font_4x6.h b/wled00/src/font/console_font_4x6.h index f3cc1dc4..348b2a4b 100644 --- a/wled00/src/font/console_font_4x6.h +++ b/wled00/src/font/console_font_4x6.h @@ -1,329 +1,340 @@ +#if !defined(WLED_ENABLE_FULL_FONTS) +constexpr uint16_t console_font_4x6_first = 32; // index 0 = code 32 "" +constexpr uint16_t console_font_4x6_last = 126; // last index = code 126 "~" +#else +constexpr uint16_t console_font_4x6_first = 1; // index 0 = code 1 "☺︎" +constexpr uint16_t console_font_4x6_last = 254; // last index = code 254 "■" +#endif + // font courtesy of https://github.com/idispatch/raster-fonts static const unsigned char console_font_4x6[] PROGMEM = { // code points 0-31 and 127-255 are commented out to save memory, they contain extra characters (CP437), // which could be used with an UTF-8 to CP437 conversion +#if 0 // skip 0 // /* // * code=0, hex=0x00, ascii="^@" // */ - // 0x00, /* 0000 */ - // 0x00, /* 0000 */ - // 0x00, /* 0000 */ - // 0x00, /* 0000 */ - // 0x00, /* 0000 */ - // 0x00, /* 0000 */ + 0x00, /* 0000 */ + 0x00, /* 0000 */ + 0x00, /* 0000 */ + 0x00, /* 0000 */ + 0x00, /* 0000 */ + 0x00, /* 0000 */ +#endif +#if defined(WLED_ENABLE_FULL_FONTS) // /* // * code=1, hex=0x01, ascii="^A" // */ - // 0x20, /* 0010 */ - // 0x50, /* 0101 */ - // 0x70, /* 0111 */ - // 0x50, /* 0101 */ - // 0x20, /* 0010 */ - // 0x00, /* 0000 */ + 0x20, /* 0010 */ + 0x50, /* 0101 */ + 0x70, /* 0111 */ + 0x50, /* 0101 */ + 0x20, /* 0010 */ + 0x00, /* 0000 */ // /* // * code=2, hex=0x02, ascii="^B" // */ - // 0x20, /* 0010 */ - // 0x70, /* 0111 */ - // 0x50, /* 0101 */ - // 0x70, /* 0111 */ - // 0x20, /* 0010 */ - // 0x00, /* 0000 */ + 0x20, /* 0010 */ + 0x70, /* 0111 */ + 0x50, /* 0101 */ + 0x70, /* 0111 */ + 0x20, /* 0010 */ + 0x00, /* 0000 */ // /* // * code=3, hex=0x03, ascii="^C" // */ - // 0x00, /* 0000 */ - // 0x50, /* 0101 */ - // 0x70, /* 0111 */ - // 0x70, /* 0111 */ - // 0x20, /* 0010 */ - // 0x00, /* 0000 */ + 0x00, /* 0000 */ + 0x50, /* 0101 */ + 0x70, /* 0111 */ + 0x70, /* 0111 */ + 0x20, /* 0010 */ + 0x00, /* 0000 */ // /* // * code=4, hex=0x04, ascii="^D" // */ - // 0x00, /* 0000 */ - // 0x20, /* 0010 */ - // 0x70, /* 0111 */ - // 0x70, /* 0111 */ - // 0x20, /* 0010 */ - // 0x00, /* 0000 */ + 0x00, /* 0000 */ + 0x20, /* 0010 */ + 0x70, /* 0111 */ + 0x70, /* 0111 */ + 0x20, /* 0010 */ + 0x00, /* 0000 */ // /* // * code=5, hex=0x05, ascii="^E" // */ - // 0x20, /* 0010 */ - // 0x70, /* 0111 */ - // 0x70, /* 0111 */ - // 0x20, /* 0010 */ - // 0x70, /* 0111 */ - // 0x00, /* 0000 */ + 0x20, /* 0010 */ + 0x70, /* 0111 */ + 0x70, /* 0111 */ + 0x20, /* 0010 */ + 0x70, /* 0111 */ + 0x00, /* 0000 */ // /* // * code=6, hex=0x06, ascii="^F" // */ - // 0x20, /* 0010 */ - // 0x20, /* 0010 */ - // 0x70, /* 0111 */ - // 0x20, /* 0010 */ - // 0x70, /* 0111 */ - // 0x00, /* 0000 */ + 0x20, /* 0010 */ + 0x20, /* 0010 */ + 0x70, /* 0111 */ + 0x20, /* 0010 */ + 0x70, /* 0111 */ + 0x00, /* 0000 */ // /* // * code=7, hex=0x07, ascii="^G" // */ - // 0x00, /* 0000 */ - // 0x00, /* 0000 */ - // 0x20, /* 0010 */ - // 0x00, /* 0000 */ - // 0x00, /* 0000 */ - // 0x00, /* 0000 */ + 0x00, /* 0000 */ + 0x00, /* 0000 */ + 0x20, /* 0010 */ + 0x00, /* 0000 */ + 0x00, /* 0000 */ + 0x00, /* 0000 */ // /* // * code=8, hex=0x08, ascii="^H" // */ - // 0xF0, /* 1111 */ - // 0xF0, /* 1111 */ - // 0xD0, /* 1101 */ - // 0xF0, /* 1111 */ - // 0xF0, /* 1111 */ - // 0xF0, /* 1111 */ + 0xF0, /* 1111 */ + 0xF0, /* 1111 */ + 0xD0, /* 1101 */ + 0xF0, /* 1111 */ + 0xF0, /* 1111 */ + 0xF0, /* 1111 */ // /* // * code=9, hex=0x09, ascii="^I" // */ - // 0x00, /* 0000 */ - // 0x70, /* 0111 */ - // 0x50, /* 0101 */ - // 0x70, /* 0111 */ - // 0x00, /* 0000 */ - // 0x00, /* 0000 */ + 0x00, /* 0000 */ + 0x70, /* 0111 */ + 0x50, /* 0101 */ + 0x70, /* 0111 */ + 0x00, /* 0000 */ + 0x00, /* 0000 */ // /* // * code=10, hex=0x0A, ascii="^J" // */ - // 0xF0, /* 1111 */ - // 0x80, /* 1000 */ - // 0xA0, /* 1010 */ - // 0x80, /* 1000 */ - // 0xF0, /* 1111 */ - // 0xF0, /* 1111 */ + 0xF0, /* 1111 */ + 0x80, /* 1000 */ + 0xA0, /* 1010 */ + 0x80, /* 1000 */ + 0xF0, /* 1111 */ + 0xF0, /* 1111 */ // /* // * code=11, hex=0x0B, ascii="^K" // */ - // 0x00, /* 0000 */ - // 0x30, /* 0011 */ - // 0x10, /* 0001 */ - // 0x60, /* 0110 */ - // 0x60, /* 0110 */ - // 0x00, /* 0000 */ + 0x00, /* 0000 */ + 0x30, /* 0011 */ + 0x10, /* 0001 */ + 0x60, /* 0110 */ + 0x60, /* 0110 */ + 0x00, /* 0000 */ // /* // * code=12, hex=0x0C, ascii="^L" // */ - // 0x20, /* 0010 */ - // 0x50, /* 0101 */ - // 0x20, /* 0010 */ - // 0x70, /* 0111 */ - // 0x20, /* 0010 */ - // 0x00, /* 0000 */ + 0x20, /* 0010 */ + 0x50, /* 0101 */ + 0x20, /* 0010 */ + 0x70, /* 0111 */ + 0x20, /* 0010 */ + 0x00, /* 0000 */ // /* // * code=13, hex=0x0D, ascii="^M" // */ - // 0x20, /* 0010 */ - // 0x30, /* 0011 */ - // 0x20, /* 0010 */ - // 0x20, /* 0010 */ - // 0x60, /* 0110 */ - // 0x00, /* 0000 */ + 0x20, /* 0010 */ + 0x30, /* 0011 */ + 0x20, /* 0010 */ + 0x20, /* 0010 */ + 0x60, /* 0110 */ + 0x00, /* 0000 */ // /* // * code=14, hex=0x0E, ascii="^N" // */ - // 0x20, /* 0010 */ - // 0x30, /* 0011 */ - // 0x50, /* 0101 */ - // 0x10, /* 0001 */ - // 0x20, /* 0010 */ - // 0x00, /* 0000 */ + 0x20, /* 0010 */ + 0x30, /* 0011 */ + 0x50, /* 0101 */ + 0x10, /* 0001 */ + 0x20, /* 0010 */ + 0x00, /* 0000 */ // /* // * code=15, hex=0x0F, ascii="^O" // */ - // 0x20, /* 0010 */ - // 0x70, /* 0111 */ - // 0x50, /* 0101 */ - // 0x70, /* 0111 */ - // 0x20, /* 0010 */ - // 0x00, /* 0000 */ + 0x20, /* 0010 */ + 0x70, /* 0111 */ + 0x50, /* 0101 */ + 0x70, /* 0111 */ + 0x20, /* 0010 */ + 0x00, /* 0000 */ // /* // * code=16, hex=0x10, ascii="^P" // */ - // 0x40, /* 0100 */ - // 0x60, /* 0110 */ - // 0x70, /* 0111 */ - // 0x60, /* 0110 */ - // 0x40, /* 0100 */ - // 0x00, /* 0000 */ + 0x40, /* 0100 */ + 0x60, /* 0110 */ + 0x70, /* 0111 */ + 0x60, /* 0110 */ + 0x40, /* 0100 */ + 0x00, /* 0000 */ // /* // * code=17, hex=0x11, ascii="^Q" // */ - // 0x10, /* 0001 */ - // 0x30, /* 0011 */ - // 0x70, /* 0111 */ - // 0x30, /* 0011 */ - // 0x10, /* 0001 */ - // 0x00, /* 0000 */ + 0x10, /* 0001 */ + 0x30, /* 0011 */ + 0x70, /* 0111 */ + 0x30, /* 0011 */ + 0x10, /* 0001 */ + 0x00, /* 0000 */ // /* // * code=18, hex=0x12, ascii="^R" // */ - // 0x20, /* 0010 */ - // 0x70, /* 0111 */ - // 0x20, /* 0010 */ - // 0x70, /* 0111 */ - // 0x20, /* 0010 */ - // 0x00, /* 0000 */ + 0x20, /* 0010 */ + 0x70, /* 0111 */ + 0x20, /* 0010 */ + 0x70, /* 0111 */ + 0x20, /* 0010 */ + 0x00, /* 0000 */ // /* // * code=19, hex=0x13, ascii="^S" // */ - // 0x50, /* 0101 */ - // 0x50, /* 0101 */ - // 0x50, /* 0101 */ - // 0x00, /* 0000 */ - // 0x50, /* 0101 */ - // 0x00, /* 0000 */ + 0x50, /* 0101 */ + 0x50, /* 0101 */ + 0x50, /* 0101 */ + 0x00, /* 0000 */ + 0x50, /* 0101 */ + 0x00, /* 0000 */ // /* // * code=20, hex=0x14, ascii="^T" // */ - // 0x70, /* 0111 */ - // 0xD0, /* 1101 */ - // 0xD0, /* 1101 */ - // 0x50, /* 0101 */ - // 0x50, /* 0101 */ - // 0x00, /* 0000 */ + 0x70, /* 0111 */ + 0xD0, /* 1101 */ + 0xD0, /* 1101 */ + 0x50, /* 0101 */ + 0x50, /* 0101 */ + 0x00, /* 0000 */ // /* // * code=21, hex=0x15, ascii="^U" // */ - // 0x30, /* 0011 */ - // 0x60, /* 0110 */ - // 0x50, /* 0101 */ - // 0x30, /* 0011 */ - // 0x60, /* 0110 */ - // 0x00, /* 0000 */ + 0x30, /* 0011 */ + 0x60, /* 0110 */ + 0x50, /* 0101 */ + 0x30, /* 0011 */ + 0x60, /* 0110 */ + 0x00, /* 0000 */ // /* // * code=22, hex=0x16, ascii="^V" // */ - // 0x00, /* 0000 */ - // 0x00, /* 0000 */ - // 0x00, /* 0000 */ - // 0x00, /* 0000 */ - // 0x70, /* 0111 */ - // 0x00, /* 0000 */ + 0x00, /* 0000 */ + 0x00, /* 0000 */ + 0x00, /* 0000 */ + 0x00, /* 0000 */ + 0x70, /* 0111 */ + 0x00, /* 0000 */ // /* // * code=23, hex=0x17, ascii="^W" // */ - // 0x20, /* 0010 */ - // 0x70, /* 0111 */ - // 0x20, /* 0010 */ - // 0x70, /* 0111 */ - // 0x20, /* 0010 */ - // 0x70, /* 0111 */ + 0x20, /* 0010 */ + 0x70, /* 0111 */ + 0x20, /* 0010 */ + 0x70, /* 0111 */ + 0x20, /* 0010 */ + 0x70, /* 0111 */ // /* // * code=24, hex=0x18, ascii="^X" // */ - // 0x20, /* 0010 */ - // 0x70, /* 0111 */ - // 0x20, /* 0010 */ - // 0x20, /* 0010 */ - // 0x20, /* 0010 */ - // 0x00, /* 0000 */ + 0x20, /* 0010 */ + 0x70, /* 0111 */ + 0x20, /* 0010 */ + 0x20, /* 0010 */ + 0x20, /* 0010 */ + 0x00, /* 0000 */ // /* // * code=25, hex=0x19, ascii="^Y" // */ - // 0x20, /* 0010 */ - // 0x20, /* 0010 */ - // 0x20, /* 0010 */ - // 0x70, /* 0111 */ - // 0x20, /* 0010 */ - // 0x00, /* 0000 */ + 0x20, /* 0010 */ + 0x20, /* 0010 */ + 0x20, /* 0010 */ + 0x70, /* 0111 */ + 0x20, /* 0010 */ + 0x00, /* 0000 */ // /* // * code=26, hex=0x1A, ascii="^Z" // */ - // 0x00, /* 0000 */ - // 0x20, /* 0010 */ - // 0xF0, /* 1111 */ - // 0x20, /* 0010 */ - // 0x00, /* 0000 */ - // 0x00, /* 0000 */ + 0x00, /* 0000 */ + 0x20, /* 0010 */ + 0xF0, /* 1111 */ + 0x20, /* 0010 */ + 0x00, /* 0000 */ + 0x00, /* 0000 */ // /* // * code=27, hex=0x1B, ascii="^[" // */ - // 0x00, /* 0000 */ - // 0x40, /* 0100 */ - // 0xF0, /* 1111 */ - // 0x40, /* 0100 */ - // 0x00, /* 0000 */ - // 0x00, /* 0000 */ + 0x00, /* 0000 */ + 0x40, /* 0100 */ + 0xF0, /* 1111 */ + 0x40, /* 0100 */ + 0x00, /* 0000 */ + 0x00, /* 0000 */ // /* // * code=28, hex=0x1C, ascii="^\" // */ - // 0x00, /* 0000 */ - // 0x00, /* 0000 */ - // 0x40, /* 0100 */ - // 0x70, /* 0111 */ - // 0x00, /* 0000 */ - // 0x00, /* 0000 */ + 0x00, /* 0000 */ + 0x00, /* 0000 */ + 0x40, /* 0100 */ + 0x70, /* 0111 */ + 0x00, /* 0000 */ + 0x00, /* 0000 */ // /* // * code=29, hex=0x1D, ascii="^]" // */ - // 0x00, /* 0000 */ - // 0x50, /* 0101 */ - // 0x70, /* 0111 */ - // 0x50, /* 0101 */ - // 0x00, /* 0000 */ - // 0x00, /* 0000 */ + 0x00, /* 0000 */ + 0x50, /* 0101 */ + 0x70, /* 0111 */ + 0x50, /* 0101 */ + 0x00, /* 0000 */ + 0x00, /* 0000 */ // /* // * code=30, hex=0x1E, ascii="^^" // */ - // 0x00, /* 0000 */ - // 0x20, /* 0010 */ - // 0x70, /* 0111 */ - // 0x70, /* 0111 */ - // 0x00, /* 0000 */ - // 0x00, /* 0000 */ + 0x00, /* 0000 */ + 0x20, /* 0010 */ + 0x70, /* 0111 */ + 0x70, /* 0111 */ + 0x00, /* 0000 */ + 0x00, /* 0000 */ // /* // * code=31, hex=0x1F, ascii="^_" // */ - // 0x00, /* 0000 */ - // 0x70, /* 0111 */ - // 0x70, /* 0111 */ - // 0x20, /* 0010 */ - // 0x00, /* 0000 */ - // 0x00, /* 0000 */ - + 0x00, /* 0000 */ + 0x70, /* 0111 */ + 0x70, /* 0111 */ + 0x20, /* 0010 */ + 0x00, /* 0000 */ + 0x00, /* 0000 */ +#endif /* * code=32, hex=0x20, ascii=" " */ @@ -1274,1293 +1285,1297 @@ static const unsigned char console_font_4x6[] PROGMEM = { 0x00, /* 0000 */ 0x00, /* 0000 */ +#if defined(WLED_ENABLE_FULL_FONTS) // /* // * code=127, hex=0x7F, ascii="^?" // */ - // 0x00, /* 0000 */ - // 0x20, /* 0010 */ - // 0x50, /* 0101 */ - // 0x70, /* 0111 */ - // 0x00, /* 0000 */ - // 0x00, /* 0000 */ + 0x00, /* 0000 */ + 0x20, /* 0010 */ + 0x50, /* 0101 */ + 0x70, /* 0111 */ + 0x00, /* 0000 */ + 0x00, /* 0000 */ // /* // * code=128, hex=0x80, ascii="!^@" // */ - // 0x30, /* 0011 */ - // 0x40, /* 0100 */ - // 0x40, /* 0100 */ - // 0x70, /* 0111 */ - // 0x20, /* 0010 */ - // 0x40, /* 0100 */ + 0x30, /* 0011 */ + 0x40, /* 0100 */ + 0x40, /* 0100 */ + 0x70, /* 0111 */ + 0x20, /* 0010 */ + 0x40, /* 0100 */ // /* // * code=129, hex=0x81, ascii="!^A" // */ - // 0x50, /* 0101 */ - // 0x00, /* 0000 */ - // 0x50, /* 0101 */ - // 0x50, /* 0101 */ - // 0x30, /* 0011 */ - // 0x00, /* 0000 */ + 0x50, /* 0101 */ + 0x00, /* 0000 */ + 0x50, /* 0101 */ + 0x50, /* 0101 */ + 0x30, /* 0011 */ + 0x00, /* 0000 */ // /* // * code=130, hex=0x82, ascii="!^B" // */ - // 0x10, /* 0001 */ - // 0x20, /* 0010 */ - // 0x70, /* 0111 */ - // 0x60, /* 0110 */ - // 0x30, /* 0011 */ - // 0x00, /* 0000 */ + 0x10, /* 0001 */ + 0x20, /* 0010 */ + 0x70, /* 0111 */ + 0x60, /* 0110 */ + 0x30, /* 0011 */ + 0x00, /* 0000 */ // /* // * code=131, hex=0x83, ascii="!^C" // */ - // 0x20, /* 0010 */ - // 0x50, /* 0101 */ - // 0x30, /* 0011 */ - // 0x50, /* 0101 */ - // 0x70, /* 0111 */ - // 0x00, /* 0000 */ + 0x20, /* 0010 */ + 0x50, /* 0101 */ + 0x30, /* 0011 */ + 0x50, /* 0101 */ + 0x70, /* 0111 */ + 0x00, /* 0000 */ // /* // * code=132, hex=0x84, ascii="!^D" // */ - // 0x50, /* 0101 */ - // 0x00, /* 0000 */ - // 0x30, /* 0011 */ - // 0x50, /* 0101 */ - // 0x70, /* 0111 */ - // 0x00, /* 0000 */ + 0x50, /* 0101 */ + 0x00, /* 0000 */ + 0x30, /* 0011 */ + 0x50, /* 0101 */ + 0x70, /* 0111 */ + 0x00, /* 0000 */ // /* // * code=133, hex=0x85, ascii="!^E" // */ - // 0x40, /* 0100 */ - // 0x20, /* 0010 */ - // 0x30, /* 0011 */ - // 0x50, /* 0101 */ - // 0x70, /* 0111 */ - // 0x00, /* 0000 */ + 0x40, /* 0100 */ + 0x20, /* 0010 */ + 0x30, /* 0011 */ + 0x50, /* 0101 */ + 0x70, /* 0111 */ + 0x00, /* 0000 */ // /* // * code=134, hex=0x86, ascii="!^F" // */ - // 0x20, /* 0010 */ - // 0x00, /* 0000 */ - // 0x30, /* 0011 */ - // 0x50, /* 0101 */ - // 0x70, /* 0111 */ - // 0x00, /* 0000 */ + 0x20, /* 0010 */ + 0x00, /* 0000 */ + 0x30, /* 0011 */ + 0x50, /* 0101 */ + 0x70, /* 0111 */ + 0x00, /* 0000 */ // /* // * code=135, hex=0x87, ascii="!^G" // */ - // 0x00, /* 0000 */ - // 0x70, /* 0111 */ - // 0x40, /* 0100 */ - // 0x70, /* 0111 */ - // 0x20, /* 0010 */ - // 0x60, /* 0110 */ + 0x00, /* 0000 */ + 0x70, /* 0111 */ + 0x40, /* 0100 */ + 0x70, /* 0111 */ + 0x20, /* 0010 */ + 0x60, /* 0110 */ // /* // * code=136, hex=0x88, ascii="!^H" // */ - // 0x20, /* 0010 */ - // 0x50, /* 0101 */ - // 0x70, /* 0111 */ - // 0x60, /* 0110 */ - // 0x30, /* 0011 */ - // 0x00, /* 0000 */ + 0x20, /* 0010 */ + 0x50, /* 0101 */ + 0x70, /* 0111 */ + 0x60, /* 0110 */ + 0x30, /* 0011 */ + 0x00, /* 0000 */ // /* // * code=137, hex=0x89, ascii="!^I" // */ - // 0x50, /* 0101 */ - // 0x00, /* 0000 */ - // 0x70, /* 0111 */ - // 0x60, /* 0110 */ - // 0x30, /* 0011 */ - // 0x00, /* 0000 */ + 0x50, /* 0101 */ + 0x00, /* 0000 */ + 0x70, /* 0111 */ + 0x60, /* 0110 */ + 0x30, /* 0011 */ + 0x00, /* 0000 */ // /* // * code=138, hex=0x8A, ascii="!^J" // */ - // 0x40, /* 0100 */ - // 0x20, /* 0010 */ - // 0x70, /* 0111 */ - // 0x60, /* 0110 */ - // 0x30, /* 0011 */ - // 0x00, /* 0000 */ + 0x40, /* 0100 */ + 0x20, /* 0010 */ + 0x70, /* 0111 */ + 0x60, /* 0110 */ + 0x30, /* 0011 */ + 0x00, /* 0000 */ // /* // * code=139, hex=0x8B, ascii="!^K" // */ - // 0x50, /* 0101 */ - // 0x00, /* 0000 */ - // 0x20, /* 0010 */ - // 0x20, /* 0010 */ - // 0x20, /* 0010 */ - // 0x00, /* 0000 */ + 0x50, /* 0101 */ + 0x00, /* 0000 */ + 0x20, /* 0010 */ + 0x20, /* 0010 */ + 0x20, /* 0010 */ + 0x00, /* 0000 */ // /* // * code=140, hex=0x8C, ascii="!^L" // */ - // 0x20, /* 0010 */ - // 0x50, /* 0101 */ - // 0x00, /* 0000 */ - // 0x20, /* 0010 */ - // 0x20, /* 0010 */ - // 0x00, /* 0000 */ + 0x20, /* 0010 */ + 0x50, /* 0101 */ + 0x00, /* 0000 */ + 0x20, /* 0010 */ + 0x20, /* 0010 */ + 0x00, /* 0000 */ // /* // * code=141, hex=0x8D, ascii="!^M" // */ - // 0x40, /* 0100 */ - // 0x20, /* 0010 */ - // 0x00, /* 0000 */ - // 0x20, /* 0010 */ - // 0x20, /* 0010 */ - // 0x00, /* 0000 */ + 0x40, /* 0100 */ + 0x20, /* 0010 */ + 0x00, /* 0000 */ + 0x20, /* 0010 */ + 0x20, /* 0010 */ + 0x00, /* 0000 */ // /* // * code=142, hex=0x8E, ascii="!^N" // */ - // 0x50, /* 0101 */ - // 0x20, /* 0010 */ - // 0x50, /* 0101 */ - // 0x70, /* 0111 */ - // 0x50, /* 0101 */ - // 0x00, /* 0000 */ + 0x50, /* 0101 */ + 0x20, /* 0010 */ + 0x50, /* 0101 */ + 0x70, /* 0111 */ + 0x50, /* 0101 */ + 0x00, /* 0000 */ // /* // * code=143, hex=0x8F, ascii="!^O" // */ - // 0x20, /* 0010 */ - // 0x20, /* 0010 */ - // 0x50, /* 0101 */ - // 0x70, /* 0111 */ - // 0x50, /* 0101 */ - // 0x00, /* 0000 */ + 0x20, /* 0010 */ + 0x20, /* 0010 */ + 0x50, /* 0101 */ + 0x70, /* 0111 */ + 0x50, /* 0101 */ + 0x00, /* 0000 */ // /* // * code=144, hex=0x90, ascii="!^P" // */ - // 0x10, /* 0001 */ - // 0x20, /* 0010 */ - // 0x70, /* 0111 */ - // 0x60, /* 0110 */ - // 0x70, /* 0111 */ - // 0x00, /* 0000 */ + 0x10, /* 0001 */ + 0x20, /* 0010 */ + 0x70, /* 0111 */ + 0x60, /* 0110 */ + 0x70, /* 0111 */ + 0x00, /* 0000 */ // /* // * code=145, hex=0x91, ascii="!^Q" // */ - // 0x00, /* 0000 */ - // 0x00, /* 0000 */ - // 0x30, /* 0011 */ - // 0x70, /* 0111 */ - // 0x60, /* 0110 */ - // 0x00, /* 0000 */ + 0x00, /* 0000 */ + 0x00, /* 0000 */ + 0x30, /* 0011 */ + 0x70, /* 0111 */ + 0x60, /* 0110 */ + 0x00, /* 0000 */ // /* // * code=146, hex=0x92, ascii="!^R" // */ - // 0x30, /* 0011 */ - // 0x60, /* 0110 */ - // 0x70, /* 0111 */ - // 0x60, /* 0110 */ - // 0x70, /* 0111 */ - // 0x00, /* 0000 */ + 0x30, /* 0011 */ + 0x60, /* 0110 */ + 0x70, /* 0111 */ + 0x60, /* 0110 */ + 0x70, /* 0111 */ + 0x00, /* 0000 */ // /* // * code=147, hex=0x93, ascii="!^S" // */ - // 0x20, /* 0010 */ - // 0x50, /* 0101 */ - // 0x20, /* 0010 */ - // 0x50, /* 0101 */ - // 0x20, /* 0010 */ - // 0x00, /* 0000 */ + 0x20, /* 0010 */ + 0x50, /* 0101 */ + 0x20, /* 0010 */ + 0x50, /* 0101 */ + 0x20, /* 0010 */ + 0x00, /* 0000 */ // /* // * code=148, hex=0x94, ascii="!^T" // */ - // 0x50, /* 0101 */ - // 0x00, /* 0000 */ - // 0x20, /* 0010 */ - // 0x50, /* 0101 */ - // 0x20, /* 0010 */ - // 0x00, /* 0000 */ + 0x50, /* 0101 */ + 0x00, /* 0000 */ + 0x20, /* 0010 */ + 0x50, /* 0101 */ + 0x20, /* 0010 */ + 0x00, /* 0000 */ // /* // * code=149, hex=0x95, ascii="!^U" // */ - // 0x40, /* 0100 */ - // 0x20, /* 0010 */ - // 0x20, /* 0010 */ - // 0x50, /* 0101 */ - // 0x20, /* 0010 */ - // 0x00, /* 0000 */ + 0x40, /* 0100 */ + 0x20, /* 0010 */ + 0x20, /* 0010 */ + 0x50, /* 0101 */ + 0x20, /* 0010 */ + 0x00, /* 0000 */ // /* // * code=150, hex=0x96, ascii="!^V" // */ - // 0x20, /* 0010 */ - // 0x50, /* 0101 */ - // 0x00, /* 0000 */ - // 0x50, /* 0101 */ - // 0x70, /* 0111 */ - // 0x00, /* 0000 */ + 0x20, /* 0010 */ + 0x50, /* 0101 */ + 0x00, /* 0000 */ + 0x50, /* 0101 */ + 0x70, /* 0111 */ + 0x00, /* 0000 */ // /* // * code=151, hex=0x97, ascii="!^W" // */ - // 0x40, /* 0100 */ - // 0x20, /* 0010 */ - // 0x50, /* 0101 */ - // 0x50, /* 0101 */ - // 0x70, /* 0111 */ - // 0x00, /* 0000 */ + 0x40, /* 0100 */ + 0x20, /* 0010 */ + 0x50, /* 0101 */ + 0x50, /* 0101 */ + 0x70, /* 0111 */ + 0x00, /* 0000 */ // /* // * code=152, hex=0x98, ascii="!^X" // */ - // 0x50, /* 0101 */ - // 0x00, /* 0000 */ - // 0x50, /* 0101 */ - // 0x50, /* 0101 */ - // 0x20, /* 0010 */ - // 0x40, /* 0100 */ + 0x50, /* 0101 */ + 0x00, /* 0000 */ + 0x50, /* 0101 */ + 0x50, /* 0101 */ + 0x20, /* 0010 */ + 0x40, /* 0100 */ // /* // * code=153, hex=0x99, ascii="!^Y" // */ - // 0x50, /* 0101 */ - // 0x20, /* 0010 */ - // 0x50, /* 0101 */ - // 0x50, /* 0101 */ - // 0x20, /* 0010 */ - // 0x00, /* 0000 */ + 0x50, /* 0101 */ + 0x20, /* 0010 */ + 0x50, /* 0101 */ + 0x50, /* 0101 */ + 0x20, /* 0010 */ + 0x00, /* 0000 */ // /* // * code=154, hex=0x9A, ascii="!^Z" // */ - // 0x50, /* 0101 */ - // 0x00, /* 0000 */ - // 0x50, /* 0101 */ - // 0x50, /* 0101 */ - // 0x70, /* 0111 */ - // 0x00, /* 0000 */ + 0x50, /* 0101 */ + 0x00, /* 0000 */ + 0x50, /* 0101 */ + 0x50, /* 0101 */ + 0x70, /* 0111 */ + 0x00, /* 0000 */ // /* // * code=155, hex=0x9B, ascii="!^[" // */ - // 0x20, /* 0010 */ - // 0x70, /* 0111 */ - // 0x40, /* 0100 */ - // 0x70, /* 0111 */ - // 0x20, /* 0010 */ - // 0x00, /* 0000 */ + 0x20, /* 0010 */ + 0x70, /* 0111 */ + 0x40, /* 0100 */ + 0x70, /* 0111 */ + 0x20, /* 0010 */ + 0x00, /* 0000 */ // /* // * code=156, hex=0x9C, ascii="!^\" // */ - // 0x10, /* 0001 */ - // 0x20, /* 0010 */ - // 0x70, /* 0111 */ - // 0x20, /* 0010 */ - // 0x70, /* 0111 */ - // 0x00, /* 0000 */ + 0x10, /* 0001 */ + 0x20, /* 0010 */ + 0x70, /* 0111 */ + 0x20, /* 0010 */ + 0x70, /* 0111 */ + 0x00, /* 0000 */ // /* // * code=157, hex=0x9D, ascii="!^]" // */ - // 0x50, /* 0101 */ - // 0x70, /* 0111 */ - // 0x20, /* 0010 */ - // 0x70, /* 0111 */ - // 0x20, /* 0010 */ - // 0x00, /* 0000 */ + 0x50, /* 0101 */ + 0x70, /* 0111 */ + 0x20, /* 0010 */ + 0x70, /* 0111 */ + 0x20, /* 0010 */ + 0x00, /* 0000 */ // /* // * code=158, hex=0x9E, ascii="!^^" // */ - // 0x00, /* 0000 */ - // 0x60, /* 0110 */ - // 0x60, /* 0110 */ - // 0x50, /* 0101 */ - // 0x50, /* 0101 */ - // 0x00, /* 0000 */ + 0x00, /* 0000 */ + 0x60, /* 0110 */ + 0x60, /* 0110 */ + 0x50, /* 0101 */ + 0x50, /* 0101 */ + 0x00, /* 0000 */ // /* // * code=159, hex=0x9F, ascii="!^_" // */ - // 0x30, /* 0011 */ - // 0x20, /* 0010 */ - // 0x30, /* 0011 */ - // 0x20, /* 0010 */ - // 0x60, /* 0110 */ - // 0x00, /* 0000 */ + 0x30, /* 0011 */ + 0x20, /* 0010 */ + 0x30, /* 0011 */ + 0x20, /* 0010 */ + 0x60, /* 0110 */ + 0x00, /* 0000 */ // /* // * code=160, hex=0xA0, ascii="! " // */ - // 0x10, /* 0001 */ - // 0x20, /* 0010 */ - // 0x30, /* 0011 */ - // 0x50, /* 0101 */ - // 0x70, /* 0111 */ - // 0x00, /* 0000 */ + 0x10, /* 0001 */ + 0x20, /* 0010 */ + 0x30, /* 0011 */ + 0x50, /* 0101 */ + 0x70, /* 0111 */ + 0x00, /* 0000 */ // /* // * code=161, hex=0xA1, ascii="!!" // */ - // 0x10, /* 0001 */ - // 0x20, /* 0010 */ - // 0x00, /* 0000 */ - // 0x20, /* 0010 */ - // 0x20, /* 0010 */ - // 0x00, /* 0000 */ + 0x10, /* 0001 */ + 0x20, /* 0010 */ + 0x00, /* 0000 */ + 0x20, /* 0010 */ + 0x20, /* 0010 */ + 0x00, /* 0000 */ // /* // * code=162, hex=0xA2, ascii="!"" // */ - // 0x10, /* 0001 */ - // 0x20, /* 0010 */ - // 0x70, /* 0111 */ - // 0x50, /* 0101 */ - // 0x70, /* 0111 */ - // 0x00, /* 0000 */ + 0x10, /* 0001 */ + 0x20, /* 0010 */ + 0x70, /* 0111 */ + 0x50, /* 0101 */ + 0x70, /* 0111 */ + 0x00, /* 0000 */ // /* // * code=163, hex=0xA3, ascii="!#" // */ - // 0x10, /* 0001 */ - // 0x20, /* 0010 */ - // 0x00, /* 0000 */ - // 0x50, /* 0101 */ - // 0x70, /* 0111 */ - // 0x00, /* 0000 */ + 0x10, /* 0001 */ + 0x20, /* 0010 */ + 0x00, /* 0000 */ + 0x50, /* 0101 */ + 0x70, /* 0111 */ + 0x00, /* 0000 */ // /* // * code=164, hex=0xA4, ascii="!$" // */ - // 0x70, /* 0111 */ - // 0x00, /* 0000 */ - // 0x70, /* 0111 */ - // 0x50, /* 0101 */ - // 0x50, /* 0101 */ - // 0x00, /* 0000 */ + 0x70, /* 0111 */ + 0x00, /* 0000 */ + 0x70, /* 0111 */ + 0x50, /* 0101 */ + 0x50, /* 0101 */ + 0x00, /* 0000 */ // /* // * code=165, hex=0xA5, ascii="!%" // */ - // 0x70, /* 0111 */ - // 0x00, /* 0000 */ - // 0x50, /* 0101 */ - // 0x70, /* 0111 */ - // 0x50, /* 0101 */ - // 0x00, /* 0000 */ + 0x70, /* 0111 */ + 0x00, /* 0000 */ + 0x50, /* 0101 */ + 0x70, /* 0111 */ + 0x50, /* 0101 */ + 0x00, /* 0000 */ // /* // * code=166, hex=0xA6, ascii="!&" // */ - // 0x30, /* 0011 */ - // 0x50, /* 0101 */ - // 0x70, /* 0111 */ - // 0x00, /* 0000 */ - // 0x70, /* 0111 */ - // 0x00, /* 0000 */ + 0x30, /* 0011 */ + 0x50, /* 0101 */ + 0x70, /* 0111 */ + 0x00, /* 0000 */ + 0x70, /* 0111 */ + 0x00, /* 0000 */ // /* // * code=167, hex=0xA7, ascii="!'" // */ - // 0x20, /* 0010 */ - // 0x50, /* 0101 */ - // 0x20, /* 0010 */ - // 0x00, /* 0000 */ - // 0x70, /* 0111 */ - // 0x00, /* 0000 */ + 0x20, /* 0010 */ + 0x50, /* 0101 */ + 0x20, /* 0010 */ + 0x00, /* 0000 */ + 0x70, /* 0111 */ + 0x00, /* 0000 */ // /* // * code=168, hex=0xA8, ascii="!(" // */ - // 0x20, /* 0010 */ - // 0x00, /* 0000 */ - // 0x20, /* 0010 */ - // 0x40, /* 0100 */ - // 0x30, /* 0011 */ - // 0x00, /* 0000 */ + 0x20, /* 0010 */ + 0x00, /* 0000 */ + 0x20, /* 0010 */ + 0x40, /* 0100 */ + 0x30, /* 0011 */ + 0x00, /* 0000 */ // /* // * code=169, hex=0xA9, ascii="!)" // */ - // 0x00, /* 0000 */ - // 0x70, /* 0111 */ - // 0x40, /* 0100 */ - // 0x40, /* 0100 */ - // 0x00, /* 0000 */ - // 0x00, /* 0000 */ + 0x00, /* 0000 */ + 0x70, /* 0111 */ + 0x40, /* 0100 */ + 0x40, /* 0100 */ + 0x00, /* 0000 */ + 0x00, /* 0000 */ // /* // * code=170, hex=0xAA, ascii="!*" // */ - // 0x00, /* 0000 */ - // 0xE0, /* 1110 */ - // 0x20, /* 0010 */ - // 0x20, /* 0010 */ - // 0x00, /* 0000 */ - // 0x00, /* 0000 */ + 0x00, /* 0000 */ + 0xE0, /* 1110 */ + 0x20, /* 0010 */ + 0x20, /* 0010 */ + 0x00, /* 0000 */ + 0x00, /* 0000 */ // /* // * code=171, hex=0xAB, ascii="!+" // */ - // 0x40, /* 0100 */ - // 0x50, /* 0101 */ - // 0x20, /* 0010 */ - // 0x50, /* 0101 */ - // 0x30, /* 0011 */ - // 0x00, /* 0000 */ + 0x40, /* 0100 */ + 0x50, /* 0101 */ + 0x20, /* 0010 */ + 0x50, /* 0101 */ + 0x30, /* 0011 */ + 0x00, /* 0000 */ // /* // * code=172, hex=0xAC, ascii="!," // */ - // 0x40, /* 0100 */ - // 0x50, /* 0101 */ - // 0x20, /* 0010 */ - // 0x70, /* 0111 */ - // 0x10, /* 0001 */ - // 0x00, /* 0000 */ + 0x40, /* 0100 */ + 0x50, /* 0101 */ + 0x20, /* 0010 */ + 0x70, /* 0111 */ + 0x10, /* 0001 */ + 0x00, /* 0000 */ // /* // * code=173, hex=0xAD, ascii="!-" // */ - // 0x20, /* 0010 */ - // 0x00, /* 0000 */ - // 0x20, /* 0010 */ - // 0x20, /* 0010 */ - // 0x20, /* 0010 */ - // 0x00, /* 0000 */ + 0x20, /* 0010 */ + 0x00, /* 0000 */ + 0x20, /* 0010 */ + 0x20, /* 0010 */ + 0x20, /* 0010 */ + 0x00, /* 0000 */ // /* // * code=174, hex=0xAE, ascii="!." // */ - // 0x00, /* 0000 */ - // 0x50, /* 0101 */ - // 0xA0, /* 1010 */ - // 0x50, /* 0101 */ - // 0x00, /* 0000 */ - // 0x00, /* 0000 */ + 0x00, /* 0000 */ + 0x50, /* 0101 */ + 0xA0, /* 1010 */ + 0x50, /* 0101 */ + 0x00, /* 0000 */ + 0x00, /* 0000 */ // /* // * code=175, hex=0xAF, ascii="!/" // */ - // 0x00, /* 0000 */ - // 0xA0, /* 1010 */ - // 0x50, /* 0101 */ - // 0xA0, /* 1010 */ - // 0x00, /* 0000 */ - // 0x00, /* 0000 */ + 0x00, /* 0000 */ + 0xA0, /* 1010 */ + 0x50, /* 0101 */ + 0xA0, /* 1010 */ + 0x00, /* 0000 */ + 0x00, /* 0000 */ // /* // * code=176, hex=0xB0, ascii="!0" // */ - // 0x40, /* 0100 */ - // 0x10, /* 0001 */ - // 0x40, /* 0100 */ - // 0x10, /* 0001 */ - // 0x40, /* 0100 */ - // 0x10, /* 0001 */ + 0x40, /* 0100 */ + 0x10, /* 0001 */ + 0x40, /* 0100 */ + 0x10, /* 0001 */ + 0x40, /* 0100 */ + 0x10, /* 0001 */ // /* // * code=177, hex=0xB1, ascii="!1" // */ - // 0x50, /* 0101 */ - // 0xA0, /* 1010 */ - // 0x50, /* 0101 */ - // 0xA0, /* 1010 */ - // 0x50, /* 0101 */ - // 0xA0, /* 1010 */ + 0x50, /* 0101 */ + 0xA0, /* 1010 */ + 0x50, /* 0101 */ + 0xA0, /* 1010 */ + 0x50, /* 0101 */ + 0xA0, /* 1010 */ // /* // * code=178, hex=0xB2, ascii="!2" // */ - // 0xB0, /* 1011 */ - // 0xE0, /* 1110 */ - // 0xB0, /* 1011 */ - // 0xE0, /* 1110 */ - // 0xB0, /* 1011 */ - // 0xE0, /* 1110 */ + 0xB0, /* 1011 */ + 0xE0, /* 1110 */ + 0xB0, /* 1011 */ + 0xE0, /* 1110 */ + 0xB0, /* 1011 */ + 0xE0, /* 1110 */ // /* // * code=179, hex=0xB3, ascii="!3" // */ - // 0x20, /* 0010 */ - // 0x20, /* 0010 */ - // 0x20, /* 0010 */ - // 0x20, /* 0010 */ - // 0x20, /* 0010 */ - // 0x20, /* 0010 */ + 0x20, /* 0010 */ + 0x20, /* 0010 */ + 0x20, /* 0010 */ + 0x20, /* 0010 */ + 0x20, /* 0010 */ + 0x20, /* 0010 */ // /* // * code=180, hex=0xB4, ascii="!4" // */ - // 0x20, /* 0010 */ - // 0x20, /* 0010 */ - // 0xE0, /* 1110 */ - // 0x20, /* 0010 */ - // 0x20, /* 0010 */ - // 0x20, /* 0010 */ + 0x20, /* 0010 */ + 0x20, /* 0010 */ + 0xE0, /* 1110 */ + 0x20, /* 0010 */ + 0x20, /* 0010 */ + 0x20, /* 0010 */ // /* // * code=181, hex=0xB5, ascii="!5" // */ - // 0x20, /* 0010 */ - // 0xE0, /* 1110 */ - // 0x20, /* 0010 */ - // 0xE0, /* 1110 */ - // 0x20, /* 0010 */ - // 0x20, /* 0010 */ + 0x20, /* 0010 */ + 0xE0, /* 1110 */ + 0x20, /* 0010 */ + 0xE0, /* 1110 */ + 0x20, /* 0010 */ + 0x20, /* 0010 */ // /* // * code=182, hex=0xB6, ascii="!6" // */ - // 0x50, /* 0101 */ - // 0x50, /* 0101 */ - // 0xD0, /* 1101 */ - // 0x50, /* 0101 */ - // 0x50, /* 0101 */ - // 0x50, /* 0101 */ + 0x50, /* 0101 */ + 0x50, /* 0101 */ + 0xD0, /* 1101 */ + 0x50, /* 0101 */ + 0x50, /* 0101 */ + 0x50, /* 0101 */ // /* // * code=183, hex=0xB7, ascii="!7" // */ - // 0x00, /* 0000 */ - // 0x00, /* 0000 */ - // 0xF0, /* 1111 */ - // 0x50, /* 0101 */ - // 0x50, /* 0101 */ - // 0x50, /* 0101 */ + 0x00, /* 0000 */ + 0x00, /* 0000 */ + 0xF0, /* 1111 */ + 0x50, /* 0101 */ + 0x50, /* 0101 */ + 0x50, /* 0101 */ // /* // * code=184, hex=0xB8, ascii="!8" // */ - // 0x00, /* 0000 */ - // 0xE0, /* 1110 */ - // 0x20, /* 0010 */ - // 0xE0, /* 1110 */ - // 0x20, /* 0010 */ - // 0x20, /* 0010 */ + 0x00, /* 0000 */ + 0xE0, /* 1110 */ + 0x20, /* 0010 */ + 0xE0, /* 1110 */ + 0x20, /* 0010 */ + 0x20, /* 0010 */ // /* // * code=185, hex=0xB9, ascii="!9" // */ - // 0x50, /* 0101 */ - // 0xD0, /* 1101 */ - // 0x10, /* 0001 */ - // 0xD0, /* 1101 */ - // 0x50, /* 0101 */ - // 0x50, /* 0101 */ + 0x50, /* 0101 */ + 0xD0, /* 1101 */ + 0x10, /* 0001 */ + 0xD0, /* 1101 */ + 0x50, /* 0101 */ + 0x50, /* 0101 */ // /* // * code=186, hex=0xBA, ascii="!:" // */ - // 0x50, /* 0101 */ - // 0x50, /* 0101 */ - // 0x50, /* 0101 */ - // 0x50, /* 0101 */ - // 0x50, /* 0101 */ - // 0x50, /* 0101 */ + 0x50, /* 0101 */ + 0x50, /* 0101 */ + 0x50, /* 0101 */ + 0x50, /* 0101 */ + 0x50, /* 0101 */ + 0x50, /* 0101 */ // /* // * code=187, hex=0xBB, ascii="!;" // */ - // 0x00, /* 0000 */ - // 0xF0, /* 1111 */ - // 0x10, /* 0001 */ - // 0xD0, /* 1101 */ - // 0x50, /* 0101 */ - // 0x50, /* 0101 */ + 0x00, /* 0000 */ + 0xF0, /* 1111 */ + 0x10, /* 0001 */ + 0xD0, /* 1101 */ + 0x50, /* 0101 */ + 0x50, /* 0101 */ // /* // * code=188, hex=0xBC, ascii="!<" // */ - // 0x50, /* 0101 */ - // 0xD0, /* 1101 */ - // 0x10, /* 0001 */ - // 0xF0, /* 1111 */ - // 0x00, /* 0000 */ - // 0x00, /* 0000 */ + 0x50, /* 0101 */ + 0xD0, /* 1101 */ + 0x10, /* 0001 */ + 0xF0, /* 1111 */ + 0x00, /* 0000 */ + 0x00, /* 0000 */ // /* // * code=189, hex=0xBD, ascii="!=" // */ - // 0x50, /* 0101 */ - // 0x50, /* 0101 */ - // 0xF0, /* 1111 */ - // 0x00, /* 0000 */ - // 0x00, /* 0000 */ - // 0x00, /* 0000 */ + 0x50, /* 0101 */ + 0x50, /* 0101 */ + 0xF0, /* 1111 */ + 0x00, /* 0000 */ + 0x00, /* 0000 */ + 0x00, /* 0000 */ // /* // * code=190, hex=0xBE, ascii="!>" // */ - // 0x20, /* 0010 */ - // 0xE0, /* 1110 */ - // 0x20, /* 0010 */ - // 0xE0, /* 1110 */ - // 0x00, /* 0000 */ - // 0x00, /* 0000 */ + 0x20, /* 0010 */ + 0xE0, /* 1110 */ + 0x20, /* 0010 */ + 0xE0, /* 1110 */ + 0x00, /* 0000 */ + 0x00, /* 0000 */ // /* // * code=191, hex=0xBF, ascii="!?" // */ - // 0x00, /* 0000 */ - // 0x00, /* 0000 */ - // 0xE0, /* 1110 */ - // 0x20, /* 0010 */ - // 0x20, /* 0010 */ - // 0x20, /* 0010 */ + 0x00, /* 0000 */ + 0x00, /* 0000 */ + 0xE0, /* 1110 */ + 0x20, /* 0010 */ + 0x20, /* 0010 */ + 0x20, /* 0010 */ // /* // * code=192, hex=0xC0, ascii="!@" // */ - // 0x20, /* 0010 */ - // 0x20, /* 0010 */ - // 0x30, /* 0011 */ - // 0x00, /* 0000 */ - // 0x00, /* 0000 */ - // 0x00, /* 0000 */ + 0x20, /* 0010 */ + 0x20, /* 0010 */ + 0x30, /* 0011 */ + 0x00, /* 0000 */ + 0x00, /* 0000 */ + 0x00, /* 0000 */ // /* // * code=193, hex=0xC1, ascii="!A" // */ - // 0x20, /* 0010 */ - // 0x20, /* 0010 */ - // 0xF0, /* 1111 */ - // 0x00, /* 0000 */ - // 0x00, /* 0000 */ - // 0x00, /* 0000 */ + 0x20, /* 0010 */ + 0x20, /* 0010 */ + 0xF0, /* 1111 */ + 0x00, /* 0000 */ + 0x00, /* 0000 */ + 0x00, /* 0000 */ // /* // * code=194, hex=0xC2, ascii="!B" // */ - // 0x00, /* 0000 */ - // 0x00, /* 0000 */ - // 0xF0, /* 1111 */ - // 0x20, /* 0010 */ - // 0x20, /* 0010 */ - // 0x20, /* 0010 */ + 0x00, /* 0000 */ + 0x00, /* 0000 */ + 0xF0, /* 1111 */ + 0x20, /* 0010 */ + 0x20, /* 0010 */ + 0x20, /* 0010 */ // /* // * code=195, hex=0xC3, ascii="!C" // */ - // 0x20, /* 0010 */ - // 0x20, /* 0010 */ - // 0x30, /* 0011 */ - // 0x20, /* 0010 */ - // 0x20, /* 0010 */ - // 0x20, /* 0010 */ + 0x20, /* 0010 */ + 0x20, /* 0010 */ + 0x30, /* 0011 */ + 0x20, /* 0010 */ + 0x20, /* 0010 */ + 0x20, /* 0010 */ // /* // * code=196, hex=0xC4, ascii="!D" // */ - // 0x00, /* 0000 */ - // 0x00, /* 0000 */ - // 0xF0, /* 1111 */ - // 0x00, /* 0000 */ - // 0x00, /* 0000 */ - // 0x00, /* 0000 */ + 0x00, /* 0000 */ + 0x00, /* 0000 */ + 0xF0, /* 1111 */ + 0x00, /* 0000 */ + 0x00, /* 0000 */ + 0x00, /* 0000 */ // /* // * code=197, hex=0xC5, ascii="!E" // */ - // 0x20, /* 0010 */ - // 0x20, /* 0010 */ - // 0xF0, /* 1111 */ - // 0x20, /* 0010 */ - // 0x20, /* 0010 */ - // 0x20, /* 0010 */ + 0x20, /* 0010 */ + 0x20, /* 0010 */ + 0xF0, /* 1111 */ + 0x20, /* 0010 */ + 0x20, /* 0010 */ + 0x20, /* 0010 */ // /* // * code=198, hex=0xC6, ascii="!F" // */ - // 0x20, /* 0010 */ - // 0x30, /* 0011 */ - // 0x20, /* 0010 */ - // 0x30, /* 0011 */ - // 0x20, /* 0010 */ - // 0x20, /* 0010 */ + 0x20, /* 0010 */ + 0x30, /* 0011 */ + 0x20, /* 0010 */ + 0x30, /* 0011 */ + 0x20, /* 0010 */ + 0x20, /* 0010 */ // /* // * code=199, hex=0xC7, ascii="!G" // */ - // 0x50, /* 0101 */ - // 0x50, /* 0101 */ - // 0x50, /* 0101 */ - // 0x50, /* 0101 */ - // 0x50, /* 0101 */ - // 0x50, /* 0101 */ + 0x50, /* 0101 */ + 0x50, /* 0101 */ + 0x50, /* 0101 */ + 0x50, /* 0101 */ + 0x50, /* 0101 */ + 0x50, /* 0101 */ // /* // * code=200, hex=0xC8, ascii="!H" // */ - // 0x50, /* 0101 */ - // 0x50, /* 0101 */ - // 0x40, /* 0100 */ - // 0x70, /* 0111 */ - // 0x00, /* 0000 */ - // 0x00, /* 0000 */ + 0x50, /* 0101 */ + 0x50, /* 0101 */ + 0x40, /* 0100 */ + 0x70, /* 0111 */ + 0x00, /* 0000 */ + 0x00, /* 0000 */ // /* // * code=201, hex=0xC9, ascii="!I" // */ - // 0x00, /* 0000 */ - // 0x70, /* 0111 */ - // 0x40, /* 0100 */ - // 0x50, /* 0101 */ - // 0x50, /* 0101 */ - // 0x50, /* 0101 */ + 0x00, /* 0000 */ + 0x70, /* 0111 */ + 0x40, /* 0100 */ + 0x50, /* 0101 */ + 0x50, /* 0101 */ + 0x50, /* 0101 */ // /* // * code=202, hex=0xCA, ascii="!J" // */ - // 0x50, /* 0101 */ - // 0xD0, /* 1101 */ - // 0x00, /* 0000 */ - // 0xF0, /* 1111 */ - // 0x00, /* 0000 */ - // 0x00, /* 0000 */ + 0x50, /* 0101 */ + 0xD0, /* 1101 */ + 0x00, /* 0000 */ + 0xF0, /* 1111 */ + 0x00, /* 0000 */ + 0x00, /* 0000 */ // /* // * code=203, hex=0xCB, ascii="!K" // */ - // 0x00, /* 0000 */ - // 0xF0, /* 1111 */ - // 0x00, /* 0000 */ - // 0xD0, /* 1101 */ - // 0x50, /* 0101 */ - // 0x50, /* 0101 */ + 0x00, /* 0000 */ + 0xF0, /* 1111 */ + 0x00, /* 0000 */ + 0xD0, /* 1101 */ + 0x50, /* 0101 */ + 0x50, /* 0101 */ // /* // * code=204, hex=0xCC, ascii="!L" // */ - // 0x50, /* 0101 */ - // 0x50, /* 0101 */ - // 0x40, /* 0100 */ - // 0x50, /* 0101 */ - // 0x50, /* 0101 */ - // 0x50, /* 0101 */ + 0x50, /* 0101 */ + 0x50, /* 0101 */ + 0x40, /* 0100 */ + 0x50, /* 0101 */ + 0x50, /* 0101 */ + 0x50, /* 0101 */ // /* // * code=205, hex=0xCD, ascii="!M" // */ - // 0x00, /* 0000 */ - // 0xF0, /* 1111 */ - // 0x00, /* 0000 */ - // 0xF0, /* 1111 */ - // 0x00, /* 0000 */ - // 0x00, /* 0000 */ + 0x00, /* 0000 */ + 0xF0, /* 1111 */ + 0x00, /* 0000 */ + 0xF0, /* 1111 */ + 0x00, /* 0000 */ + 0x00, /* 0000 */ // /* // * code=206, hex=0xCE, ascii="!N" // */ - // 0x50, /* 0101 */ - // 0xD0, /* 1101 */ - // 0x00, /* 0000 */ - // 0xD0, /* 1101 */ - // 0x50, /* 0101 */ - // 0x50, /* 0101 */ + 0x50, /* 0101 */ + 0xD0, /* 1101 */ + 0x00, /* 0000 */ + 0xD0, /* 1101 */ + 0x50, /* 0101 */ + 0x50, /* 0101 */ // /* // * code=207, hex=0xCF, ascii="!O" // */ - // 0x20, /* 0010 */ - // 0xF0, /* 1111 */ - // 0x00, /* 0000 */ - // 0xF0, /* 1111 */ - // 0x00, /* 0000 */ - // 0x00, /* 0000 */ + 0x20, /* 0010 */ + 0xF0, /* 1111 */ + 0x00, /* 0000 */ + 0xF0, /* 1111 */ + 0x00, /* 0000 */ + 0x00, /* 0000 */ // /* // * code=208, hex=0xD0, ascii="!P" // */ - // 0x50, /* 0101 */ - // 0x50, /* 0101 */ - // 0xF0, /* 1111 */ - // 0x00, /* 0000 */ - // 0x00, /* 0000 */ - // 0x00, /* 0000 */ + 0x50, /* 0101 */ + 0x50, /* 0101 */ + 0xF0, /* 1111 */ + 0x00, /* 0000 */ + 0x00, /* 0000 */ + 0x00, /* 0000 */ // /* // * code=209, hex=0xD1, ascii="!Q" // */ - // 0x00, /* 0000 */ - // 0xF0, /* 1111 */ - // 0x00, /* 0000 */ - // 0xF0, /* 1111 */ - // 0x20, /* 0010 */ - // 0x20, /* 0010 */ + 0x00, /* 0000 */ + 0xF0, /* 1111 */ + 0x00, /* 0000 */ + 0xF0, /* 1111 */ + 0x20, /* 0010 */ + 0x20, /* 0010 */ // /* // * code=210, hex=0xD2, ascii="!R" // */ - // 0x00, /* 0000 */ - // 0x00, /* 0000 */ - // 0xF0, /* 1111 */ - // 0x50, /* 0101 */ - // 0x50, /* 0101 */ - // 0x50, /* 0101 */ + 0x00, /* 0000 */ + 0x00, /* 0000 */ + 0xF0, /* 1111 */ + 0x50, /* 0101 */ + 0x50, /* 0101 */ + 0x50, /* 0101 */ // /* // * code=211, hex=0xD3, ascii="!S" // */ - // 0x50, /* 0101 */ - // 0x50, /* 0101 */ - // 0x70, /* 0111 */ - // 0x00, /* 0000 */ - // 0x00, /* 0000 */ - // 0x00, /* 0000 */ + 0x50, /* 0101 */ + 0x50, /* 0101 */ + 0x70, /* 0111 */ + 0x00, /* 0000 */ + 0x00, /* 0000 */ + 0x00, /* 0000 */ // /* // * code=212, hex=0xD4, ascii="!T" // */ - // 0x20, /* 0010 */ - // 0x30, /* 0011 */ - // 0x20, /* 0010 */ - // 0x30, /* 0011 */ - // 0x00, /* 0000 */ - // 0x00, /* 0000 */ + 0x20, /* 0010 */ + 0x30, /* 0011 */ + 0x20, /* 0010 */ + 0x30, /* 0011 */ + 0x00, /* 0000 */ + 0x00, /* 0000 */ // /* // * code=213, hex=0xD5, ascii="!U" // */ - // 0x00, /* 0000 */ - // 0x30, /* 0011 */ - // 0x20, /* 0010 */ - // 0x30, /* 0011 */ - // 0x20, /* 0010 */ - // 0x20, /* 0010 */ + 0x00, /* 0000 */ + 0x30, /* 0011 */ + 0x20, /* 0010 */ + 0x30, /* 0011 */ + 0x20, /* 0010 */ + 0x20, /* 0010 */ // /* // * code=214, hex=0xD6, ascii="!V" // */ - // 0x00, /* 0000 */ - // 0x00, /* 0000 */ - // 0x70, /* 0111 */ - // 0x50, /* 0101 */ - // 0x50, /* 0101 */ - // 0x50, /* 0101 */ + 0x00, /* 0000 */ + 0x00, /* 0000 */ + 0x70, /* 0111 */ + 0x50, /* 0101 */ + 0x50, /* 0101 */ + 0x50, /* 0101 */ // /* // * code=215, hex=0xD7, ascii="!W" // */ - // 0x50, /* 0101 */ - // 0x50, /* 0101 */ - // 0xD0, /* 1101 */ - // 0x50, /* 0101 */ - // 0x50, /* 0101 */ - // 0x50, /* 0101 */ + 0x50, /* 0101 */ + 0x50, /* 0101 */ + 0xD0, /* 1101 */ + 0x50, /* 0101 */ + 0x50, /* 0101 */ + 0x50, /* 0101 */ // /* // * code=216, hex=0xD8, ascii="!X" // */ - // 0x20, /* 0010 */ - // 0xF0, /* 1111 */ - // 0x00, /* 0000 */ - // 0xF0, /* 1111 */ - // 0x20, /* 0010 */ - // 0x20, /* 0010 */ + 0x20, /* 0010 */ + 0xF0, /* 1111 */ + 0x00, /* 0000 */ + 0xF0, /* 1111 */ + 0x20, /* 0010 */ + 0x20, /* 0010 */ // /* // * code=217, hex=0xD9, ascii="!Y" // */ - // 0x20, /* 0010 */ - // 0x20, /* 0010 */ - // 0xE0, /* 1110 */ - // 0x00, /* 0000 */ - // 0x00, /* 0000 */ - // 0x00, /* 0000 */ + 0x20, /* 0010 */ + 0x20, /* 0010 */ + 0xE0, /* 1110 */ + 0x00, /* 0000 */ + 0x00, /* 0000 */ + 0x00, /* 0000 */ // /* // * code=218, hex=0xDA, ascii="!Z" // */ - // 0x00, /* 0000 */ - // 0x00, /* 0000 */ - // 0x30, /* 0011 */ - // 0x20, /* 0010 */ - // 0x20, /* 0010 */ - // 0x20, /* 0010 */ + 0x00, /* 0000 */ + 0x00, /* 0000 */ + 0x30, /* 0011 */ + 0x20, /* 0010 */ + 0x20, /* 0010 */ + 0x20, /* 0010 */ // /* // * code=219, hex=0xDB, ascii="![" // */ - // 0xF0, /* 1111 */ - // 0xF0, /* 1111 */ - // 0xF0, /* 1111 */ - // 0xF0, /* 1111 */ - // 0xF0, /* 1111 */ - // 0xF0, /* 1111 */ + 0xF0, /* 1111 */ + 0xF0, /* 1111 */ + 0xF0, /* 1111 */ + 0xF0, /* 1111 */ + 0xF0, /* 1111 */ + 0xF0, /* 1111 */ // /* // * code=220, hex=0xDC, ascii="!\" // */ - // 0x00, /* 0000 */ - // 0x00, /* 0000 */ - // 0x00, /* 0000 */ - // 0xF0, /* 1111 */ - // 0xF0, /* 1111 */ - // 0xF0, /* 1111 */ + 0x00, /* 0000 */ + 0x00, /* 0000 */ + 0x00, /* 0000 */ + 0xF0, /* 1111 */ + 0xF0, /* 1111 */ + 0xF0, /* 1111 */ // /* // * code=221, hex=0xDD, ascii="!]" // */ - // 0xC0, /* 1100 */ - // 0xC0, /* 1100 */ - // 0xC0, /* 1100 */ - // 0xC0, /* 1100 */ - // 0xC0, /* 1100 */ - // 0xC0, /* 1100 */ + 0xC0, /* 1100 */ + 0xC0, /* 1100 */ + 0xC0, /* 1100 */ + 0xC0, /* 1100 */ + 0xC0, /* 1100 */ + 0xC0, /* 1100 */ // /* // * code=222, hex=0xDE, ascii="!^" // */ - // 0x30, /* 0011 */ - // 0x30, /* 0011 */ - // 0x30, /* 0011 */ - // 0x30, /* 0011 */ - // 0x30, /* 0011 */ - // 0x30, /* 0011 */ + 0x30, /* 0011 */ + 0x30, /* 0011 */ + 0x30, /* 0011 */ + 0x30, /* 0011 */ + 0x30, /* 0011 */ + 0x30, /* 0011 */ // /* // * code=223, hex=0xDF, ascii="!_" // */ - // 0xF0, /* 1111 */ - // 0xF0, /* 1111 */ - // 0xF0, /* 1111 */ - // 0x00, /* 0000 */ - // 0x00, /* 0000 */ - // 0x00, /* 0000 */ + 0xF0, /* 1111 */ + 0xF0, /* 1111 */ + 0xF0, /* 1111 */ + 0x00, /* 0000 */ + 0x00, /* 0000 */ + 0x00, /* 0000 */ // /* // * code=224, hex=0xE0, ascii="!`" // */ - // 0x00, /* 0000 */ - // 0x00, /* 0000 */ - // 0x70, /* 0111 */ - // 0x60, /* 0110 */ - // 0x70, /* 0111 */ - // 0x00, /* 0000 */ + 0x00, /* 0000 */ + 0x00, /* 0000 */ + 0x70, /* 0111 */ + 0x60, /* 0110 */ + 0x70, /* 0111 */ + 0x00, /* 0000 */ // /* // * code=225, hex=0xE1, ascii="!a" // */ - // 0x20, /* 0010 */ - // 0x50, /* 0101 */ - // 0x60, /* 0110 */ - // 0x50, /* 0101 */ - // 0x60, /* 0110 */ - // 0x40, /* 0100 */ + 0x20, /* 0010 */ + 0x50, /* 0101 */ + 0x60, /* 0110 */ + 0x50, /* 0101 */ + 0x60, /* 0110 */ + 0x40, /* 0100 */ // /* // * code=226, hex=0xE2, ascii="!b" // */ - // 0x70, /* 0111 */ - // 0x50, /* 0101 */ - // 0x40, /* 0100 */ - // 0x40, /* 0100 */ - // 0x40, /* 0100 */ - // 0x00, /* 0000 */ + 0x70, /* 0111 */ + 0x50, /* 0101 */ + 0x40, /* 0100 */ + 0x40, /* 0100 */ + 0x40, /* 0100 */ + 0x00, /* 0000 */ // /* // * code=227, hex=0xE3, ascii="!c" // */ - // 0x70, /* 0111 */ - // 0x50, /* 0101 */ - // 0x50, /* 0101 */ - // 0x50, /* 0101 */ - // 0x50, /* 0101 */ - // 0x00, /* 0000 */ + 0x70, /* 0111 */ + 0x50, /* 0101 */ + 0x50, /* 0101 */ + 0x50, /* 0101 */ + 0x50, /* 0101 */ + 0x00, /* 0000 */ // /* // * code=228, hex=0xE4, ascii="!d" // */ - // 0x70, /* 0111 */ - // 0x40, /* 0100 */ - // 0x20, /* 0010 */ - // 0x40, /* 0100 */ - // 0x70, /* 0111 */ - // 0x00, /* 0000 */ + 0x70, /* 0111 */ + 0x40, /* 0100 */ + 0x20, /* 0010 */ + 0x40, /* 0100 */ + 0x70, /* 0111 */ + 0x00, /* 0000 */ // /* // * code=229, hex=0xE5, ascii="!e" // */ - // 0x00, /* 0000 */ - // 0x00, /* 0000 */ - // 0x30, /* 0011 */ - // 0x50, /* 0101 */ - // 0x20, /* 0010 */ - // 0x00, /* 0000 */ + 0x00, /* 0000 */ + 0x00, /* 0000 */ + 0x30, /* 0011 */ + 0x50, /* 0101 */ + 0x20, /* 0010 */ + 0x00, /* 0000 */ // /* // * code=230, hex=0xE6, ascii="!f" // */ - // 0x00, /* 0000 */ - // 0x00, /* 0000 */ - // 0x50, /* 0101 */ - // 0x50, /* 0101 */ - // 0x70, /* 0111 */ - // 0x40, /* 0100 */ + 0x00, /* 0000 */ + 0x00, /* 0000 */ + 0x50, /* 0101 */ + 0x50, /* 0101 */ + 0x70, /* 0111 */ + 0x40, /* 0100 */ // /* // * code=231, hex=0xE7, ascii="!g" // */ - // 0x00, /* 0000 */ - // 0x10, /* 0001 */ - // 0x60, /* 0110 */ - // 0x20, /* 0010 */ - // 0x20, /* 0010 */ - // 0x00, /* 0000 */ + 0x00, /* 0000 */ + 0x10, /* 0001 */ + 0x60, /* 0110 */ + 0x20, /* 0010 */ + 0x20, /* 0010 */ + 0x00, /* 0000 */ // /* // * code=232, hex=0xE8, ascii="!h" // */ - // 0x70, /* 0111 */ - // 0x20, /* 0010 */ - // 0x50, /* 0101 */ - // 0x20, /* 0010 */ - // 0x70, /* 0111 */ - // 0x00, /* 0000 */ + 0x70, /* 0111 */ + 0x20, /* 0010 */ + 0x50, /* 0101 */ + 0x20, /* 0010 */ + 0x70, /* 0111 */ + 0x00, /* 0000 */ // /* // * code=233, hex=0xE9, ascii="!i" // */ - // 0x20, /* 0010 */ - // 0x50, /* 0101 */ - // 0x70, /* 0111 */ - // 0x50, /* 0101 */ - // 0x20, /* 0010 */ - // 0x00, /* 0000 */ + 0x20, /* 0010 */ + 0x50, /* 0101 */ + 0x70, /* 0111 */ + 0x50, /* 0101 */ + 0x20, /* 0010 */ + 0x00, /* 0000 */ // /* // * code=234, hex=0xEA, ascii="!j" // */ - // 0x00, /* 0000 */ - // 0x20, /* 0010 */ - // 0x50, /* 0101 */ - // 0x50, /* 0101 */ - // 0x50, /* 0101 */ - // 0x00, /* 0000 */ + 0x00, /* 0000 */ + 0x20, /* 0010 */ + 0x50, /* 0101 */ + 0x50, /* 0101 */ + 0x50, /* 0101 */ + 0x00, /* 0000 */ // /* // * code=235, hex=0xEB, ascii="!k" // */ - // 0x30, /* 0011 */ - // 0x40, /* 0100 */ - // 0x20, /* 0010 */ - // 0x50, /* 0101 */ - // 0x20, /* 0010 */ - // 0x00, /* 0000 */ + 0x30, /* 0011 */ + 0x40, /* 0100 */ + 0x20, /* 0010 */ + 0x50, /* 0101 */ + 0x20, /* 0010 */ + 0x00, /* 0000 */ // /* // * code=236, hex=0xEC, ascii="!l" // */ - // 0x00, /* 0000 */ - // 0x00, /* 0000 */ - // 0x70, /* 0111 */ - // 0x50, /* 0101 */ - // 0x70, /* 0111 */ - // 0x00, /* 0000 */ + 0x00, /* 0000 */ + 0x00, /* 0000 */ + 0x70, /* 0111 */ + 0x50, /* 0101 */ + 0x70, /* 0111 */ + 0x00, /* 0000 */ // /* // * code=237, hex=0xED, ascii="!m" // */ - // 0x20, /* 0010 */ - // 0x70, /* 0111 */ - // 0x50, /* 0101 */ - // 0x70, /* 0111 */ - // 0x20, /* 0010 */ - // 0x00, /* 0000 */ + 0x20, /* 0010 */ + 0x70, /* 0111 */ + 0x50, /* 0101 */ + 0x70, /* 0111 */ + 0x20, /* 0010 */ + 0x00, /* 0000 */ // /* // * code=238, hex=0xEE, ascii="!n" // */ - // 0x30, /* 0011 */ - // 0x40, /* 0100 */ - // 0x70, /* 0111 */ - // 0x40, /* 0100 */ - // 0x30, /* 0011 */ - // 0x00, /* 0000 */ + 0x30, /* 0011 */ + 0x40, /* 0100 */ + 0x70, /* 0111 */ + 0x40, /* 0100 */ + 0x30, /* 0011 */ + 0x00, /* 0000 */ // /* // * code=239, hex=0xEF, ascii="!o" // */ - // 0x20, /* 0010 */ - // 0x50, /* 0101 */ - // 0x50, /* 0101 */ - // 0x50, /* 0101 */ - // 0x50, /* 0101 */ - // 0x00, /* 0000 */ + 0x20, /* 0010 */ + 0x50, /* 0101 */ + 0x50, /* 0101 */ + 0x50, /* 0101 */ + 0x50, /* 0101 */ + 0x00, /* 0000 */ // /* // * code=240, hex=0xF0, ascii="!p" // */ - // 0x70, /* 0111 */ - // 0x00, /* 0000 */ - // 0x70, /* 0111 */ - // 0x00, /* 0000 */ - // 0x70, /* 0111 */ - // 0x00, /* 0000 */ + 0x70, /* 0111 */ + 0x00, /* 0000 */ + 0x70, /* 0111 */ + 0x00, /* 0000 */ + 0x70, /* 0111 */ + 0x00, /* 0000 */ // /* // * code=241, hex=0xF1, ascii="!q" // */ - // 0x20, /* 0010 */ - // 0x70, /* 0111 */ - // 0x20, /* 0010 */ - // 0x00, /* 0000 */ - // 0x70, /* 0111 */ - // 0x00, /* 0000 */ + 0x20, /* 0010 */ + 0x70, /* 0111 */ + 0x20, /* 0010 */ + 0x00, /* 0000 */ + 0x70, /* 0111 */ + 0x00, /* 0000 */ // /* // * code=242, hex=0xF2, ascii="!r" // */ - // 0x60, /* 0110 */ - // 0x10, /* 0001 */ - // 0x60, /* 0110 */ - // 0x00, /* 0000 */ - // 0x70, /* 0111 */ - // 0x00, /* 0000 */ + 0x60, /* 0110 */ + 0x10, /* 0001 */ + 0x60, /* 0110 */ + 0x00, /* 0000 */ + 0x70, /* 0111 */ + 0x00, /* 0000 */ // /* // * code=243, hex=0xF3, ascii="!s" // */ - // 0x30, /* 0011 */ - // 0x40, /* 0100 */ - // 0x30, /* 0011 */ - // 0x00, /* 0000 */ - // 0x70, /* 0111 */ - // 0x00, /* 0000 */ + 0x30, /* 0011 */ + 0x40, /* 0100 */ + 0x30, /* 0011 */ + 0x00, /* 0000 */ + 0x70, /* 0111 */ + 0x00, /* 0000 */ // /* // * code=244, hex=0xF4, ascii="!t" // */ - // 0x00, /* 0000 */ - // 0x10, /* 0001 */ - // 0x20, /* 0010 */ - // 0x20, /* 0010 */ - // 0x20, /* 0010 */ - // 0x20, /* 0010 */ + 0x00, /* 0000 */ + 0x10, /* 0001 */ + 0x20, /* 0010 */ + 0x20, /* 0010 */ + 0x20, /* 0010 */ + 0x20, /* 0010 */ // /* // * code=245, hex=0xF5, ascii="!u" // */ - // 0x20, /* 0010 */ - // 0x20, /* 0010 */ - // 0x20, /* 0010 */ - // 0x20, /* 0010 */ - // 0x40, /* 0100 */ - // 0x00, /* 0000 */ + 0x20, /* 0010 */ + 0x20, /* 0010 */ + 0x20, /* 0010 */ + 0x20, /* 0010 */ + 0x40, /* 0100 */ + 0x00, /* 0000 */ // /* // * code=246, hex=0xF6, ascii="!v" // */ - // 0x20, /* 0010 */ - // 0x00, /* 0000 */ - // 0x70, /* 0111 */ - // 0x00, /* 0000 */ - // 0x20, /* 0010 */ - // 0x00, /* 0000 */ + 0x20, /* 0010 */ + 0x00, /* 0000 */ + 0x70, /* 0111 */ + 0x00, /* 0000 */ + 0x20, /* 0010 */ + 0x00, /* 0000 */ // /* // * code=247, hex=0xF7, ascii="!w" // */ - // 0x00, /* 0000 */ - // 0x50, /* 0101 */ - // 0xA0, /* 1010 */ - // 0x50, /* 0101 */ - // 0xA0, /* 1010 */ - // 0x00, /* 0000 */ + 0x00, /* 0000 */ + 0x50, /* 0101 */ + 0xA0, /* 1010 */ + 0x50, /* 0101 */ + 0xA0, /* 1010 */ + 0x00, /* 0000 */ // /* // * code=248, hex=0xF8, ascii="!x" // */ - // 0x20, /* 0010 */ - // 0x50, /* 0101 */ - // 0x20, /* 0010 */ - // 0x00, /* 0000 */ - // 0x00, /* 0000 */ - // 0x00, /* 0000 */ + 0x20, /* 0010 */ + 0x50, /* 0101 */ + 0x20, /* 0010 */ + 0x00, /* 0000 */ + 0x00, /* 0000 */ + 0x00, /* 0000 */ // /* // * code=249, hex=0xF9, ascii="!y" // */ - // 0x00, /* 0000 */ - // 0x20, /* 0010 */ - // 0x70, /* 0111 */ - // 0x20, /* 0010 */ - // 0x00, /* 0000 */ - // 0x00, /* 0000 */ + 0x00, /* 0000 */ + 0x20, /* 0010 */ + 0x70, /* 0111 */ + 0x20, /* 0010 */ + 0x00, /* 0000 */ + 0x00, /* 0000 */ // /* // * code=250, hex=0xFA, ascii="!z" // */ - // 0x00, /* 0000 */ - // 0x00, /* 0000 */ - // 0x20, /* 0010 */ - // 0x00, /* 0000 */ - // 0x00, /* 0000 */ - // 0x00, /* 0000 */ + 0x00, /* 0000 */ + 0x00, /* 0000 */ + 0x20, /* 0010 */ + 0x00, /* 0000 */ + 0x00, /* 0000 */ + 0x00, /* 0000 */ // /* // * code=251, hex=0xFB, ascii="!{" // */ - // 0x30, /* 0011 */ - // 0x20, /* 0010 */ - // 0x20, /* 0010 */ - // 0x60, /* 0110 */ - // 0x20, /* 0010 */ - // 0x00, /* 0000 */ + 0x30, /* 0011 */ + 0x20, /* 0010 */ + 0x20, /* 0010 */ + 0x60, /* 0110 */ + 0x20, /* 0010 */ + 0x00, /* 0000 */ // /* // * code=252, hex=0xFC, ascii="!|" // */ - // 0x70, /* 0111 */ - // 0x50, /* 0101 */ - // 0x50, /* 0101 */ - // 0x00, /* 0000 */ - // 0x00, /* 0000 */ - // 0x00, /* 0000 */ + 0x70, /* 0111 */ + 0x50, /* 0101 */ + 0x50, /* 0101 */ + 0x00, /* 0000 */ + 0x00, /* 0000 */ + 0x00, /* 0000 */ // /* // * code=253, hex=0xFD, ascii="!}" // */ - // 0x60, /* 0110 */ - // 0x20, /* 0010 */ - // 0x40, /* 0100 */ - // 0x60, /* 0110 */ - // 0x00, /* 0000 */ - // 0x00, /* 0000 */ + 0x60, /* 0110 */ + 0x20, /* 0010 */ + 0x40, /* 0100 */ + 0x60, /* 0110 */ + 0x00, /* 0000 */ + 0x00, /* 0000 */ // /* // * code=254, hex=0xFE, ascii="!~" // */ - // 0x00, /* 0000 */ - // 0x00, /* 0000 */ - // 0x60, /* 0110 */ - // 0x60, /* 0110 */ - // 0x00, /* 0000 */ - // 0x00, /* 0000 */ + 0x00, /* 0000 */ + 0x00, /* 0000 */ + 0x60, /* 0110 */ + 0x60, /* 0110 */ + 0x00, /* 0000 */ + 0x00, /* 0000 */ +#endif +#if 0 // skip 255 = NBSP // /* // * code=255, hex=0xFF, ascii="!^Ÿ" // */ - // 0x00, /* 0000 */ - // 0x00, /* 0000 */ - // 0x00, /* 0000 */ - // 0x00, /* 0000 */ - // 0x00, /* 0000 */ - // 0x00, /* 0000 */ + 0x00, /* 0000 */ + 0x00, /* 0000 */ + 0x00, /* 0000 */ + 0x00, /* 0000 */ + 0x00, /* 0000 */ + 0x00, /* 0000 */ +#endif }; diff --git a/wled00/src/font/console_font_5x12.h b/wled00/src/font/console_font_5x12.h index 4ea56410..7c14ae5b 100644 --- a/wled00/src/font/console_font_5x12.h +++ b/wled00/src/font/console_font_5x12.h @@ -1,521 +1,533 @@ + +#if !defined(WLED_ENABLE_FULL_FONTS) +constexpr uint16_t console_font_5x12_first = 32; // index 0 = code 32 "" +constexpr uint16_t console_font_5x12_last = 126; // last index = code 126 "~" +#else +constexpr uint16_t console_font_5x12_first = 1; // index 0 = code 1 "☺︎" +constexpr uint16_t console_font_5x12_last = 254; // last index = code 254 "■" +#endif + // font courtesy of https://github.com/idispatch/raster-fonts static const unsigned char console_font_5x12[] PROGMEM = { // code points 0-31 and 127-255 are commented out to save memory, they contain extra characters (CP437), // which could be used with an UTF-8 to CP437 conversion +#if 0 // /* // * code=0, hex=0x00, ascii="^@" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ +#endif +#if defined(WLED_ENABLE_FULL_FONTS) // /* // * code=1, hex=0x01, ascii="^A" // */ - // 0x70, /* 01110 */ - // 0x88, /* 10001 */ - // 0x88, /* 10001 */ - // 0xD8, /* 11011 */ - // 0x88, /* 10001 */ - // 0x88, /* 10001 */ - // 0xD8, /* 11011 */ - // 0xA8, /* 10101 */ - // 0x88, /* 10001 */ - // 0x70, /* 01110 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x70, /* 01110 */ + 0x88, /* 10001 */ + 0x88, /* 10001 */ + 0xD8, /* 11011 */ + 0x88, /* 10001 */ + 0x88, /* 10001 */ + 0xD8, /* 11011 */ + 0xA8, /* 10101 */ + 0x88, /* 10001 */ + 0x70, /* 01110 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=2, hex=0x02, ascii="^B" // */ - // 0x70, /* 01110 */ - // 0xF8, /* 11111 */ - // 0xF8, /* 11111 */ - // 0xA8, /* 10101 */ - // 0xF8, /* 11111 */ - // 0xF8, /* 11111 */ - // 0xA8, /* 10101 */ - // 0xD8, /* 11011 */ - // 0xF8, /* 11111 */ - // 0x70, /* 01110 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x70, /* 01110 */ + 0xF8, /* 11111 */ + 0xF8, /* 11111 */ + 0xA8, /* 10101 */ + 0xF8, /* 11111 */ + 0xF8, /* 11111 */ + 0xA8, /* 10101 */ + 0xD8, /* 11011 */ + 0xF8, /* 11111 */ + 0x70, /* 01110 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=3, hex=0x03, ascii="^C" // */ - // 0x00, /* 00000 */ - // 0x50, /* 01010 */ - // 0xD8, /* 11011 */ - // 0xF8, /* 11111 */ - // 0xF8, /* 11111 */ - // 0xF8, /* 11111 */ - // 0xF8, /* 11111 */ - // 0x70, /* 01110 */ - // 0x70, /* 01110 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x50, /* 01010 */ + 0xD8, /* 11011 */ + 0xF8, /* 11111 */ + 0xF8, /* 11111 */ + 0xF8, /* 11111 */ + 0xF8, /* 11111 */ + 0x70, /* 01110 */ + 0x70, /* 01110 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x00, /* 00000 */ // /* // * code=4, hex=0x04, ascii="^D" // */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x70, /* 01110 */ - // 0x70, /* 01110 */ - // 0xF8, /* 11111 */ - // 0xF8, /* 11111 */ - // 0xF8, /* 11111 */ - // 0x70, /* 01110 */ - // 0x70, /* 01110 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x00, /* 00000 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x70, /* 01110 */ + 0x70, /* 01110 */ + 0xF8, /* 11111 */ + 0xF8, /* 11111 */ + 0xF8, /* 11111 */ + 0x70, /* 01110 */ + 0x70, /* 01110 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x00, /* 00000 */ // /* // * code=5, hex=0x05, ascii="^E" // */ - // 0x20, /* 00100 */ - // 0x70, /* 01110 */ - // 0x70, /* 01110 */ - // 0x70, /* 01110 */ - // 0x20, /* 00100 */ - // 0xF8, /* 11111 */ - // 0xF8, /* 11111 */ - // 0x70, /* 01110 */ - // 0x20, /* 00100 */ - // 0x70, /* 01110 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x20, /* 00100 */ + 0x70, /* 01110 */ + 0x70, /* 01110 */ + 0x70, /* 01110 */ + 0x20, /* 00100 */ + 0xF8, /* 11111 */ + 0xF8, /* 11111 */ + 0x70, /* 01110 */ + 0x20, /* 00100 */ + 0x70, /* 01110 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=6, hex=0x06, ascii="^F" // */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x70, /* 01110 */ - // 0x70, /* 01110 */ - // 0xF8, /* 11111 */ - // 0xF8, /* 11111 */ - // 0xF8, /* 11111 */ - // 0x70, /* 01110 */ - // 0x20, /* 00100 */ - // 0x70, /* 01110 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x70, /* 01110 */ + 0x70, /* 01110 */ + 0xF8, /* 11111 */ + 0xF8, /* 11111 */ + 0xF8, /* 11111 */ + 0x70, /* 01110 */ + 0x20, /* 00100 */ + 0x70, /* 01110 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=7, hex=0x07, ascii="^G" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x60, /* 01100 */ - // 0x60, /* 01100 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x60, /* 01100 */ + 0x60, /* 01100 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=8, hex=0x08, ascii="^H" // */ - // 0xF8, /* 11111 */ - // 0xF8, /* 11111 */ - // 0xF8, /* 11111 */ - // 0xF8, /* 11111 */ - // 0xF8, /* 11111 */ - // 0x98, /* 10011 */ - // 0x98, /* 10011 */ - // 0xF8, /* 11111 */ - // 0xF8, /* 11111 */ - // 0xF8, /* 11111 */ - // 0xF8, /* 11111 */ - // 0xF8, /* 11111 */ + 0xF8, /* 11111 */ + 0xF8, /* 11111 */ + 0xF8, /* 11111 */ + 0xF8, /* 11111 */ + 0xF8, /* 11111 */ + 0x98, /* 10011 */ + 0x98, /* 10011 */ + 0xF8, /* 11111 */ + 0xF8, /* 11111 */ + 0xF8, /* 11111 */ + 0xF8, /* 11111 */ + 0xF8, /* 11111 */ // /* // * code=9, hex=0x09, ascii="^I" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x70, /* 01110 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x70, /* 01110 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x70, /* 01110 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x70, /* 01110 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=10, hex=0x0A, ascii="^J" // */ - // 0xF8, /* 11111 */ - // 0xF8, /* 11111 */ - // 0xF8, /* 11111 */ - // 0xF8, /* 11111 */ - // 0x88, /* 10001 */ - // 0xA8, /* 10101 */ - // 0xA8, /* 10101 */ - // 0x88, /* 10001 */ - // 0xF8, /* 11111 */ - // 0xF8, /* 11111 */ - // 0xF8, /* 11111 */ - // 0xF8, /* 11111 */ + 0xF8, /* 11111 */ + 0xF8, /* 11111 */ + 0xF8, /* 11111 */ + 0xF8, /* 11111 */ + 0x88, /* 10001 */ + 0xA8, /* 10101 */ + 0xA8, /* 10101 */ + 0x88, /* 10001 */ + 0xF8, /* 11111 */ + 0xF8, /* 11111 */ + 0xF8, /* 11111 */ + 0xF8, /* 11111 */ // /* // * code=11, hex=0x0B, ascii="^K" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x38, /* 00111 */ - // 0x18, /* 00011 */ - // 0x28, /* 00101 */ - // 0x60, /* 01100 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x60, /* 01100 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x38, /* 00111 */ + 0x18, /* 00011 */ + 0x28, /* 00101 */ + 0x60, /* 01100 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x60, /* 01100 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=12, hex=0x0C, ascii="^L" // */ - // 0x00, /* 00000 */ - // 0x60, /* 01100 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x60, /* 01100 */ - // 0x40, /* 01000 */ - // 0x40, /* 01000 */ - // 0xE0, /* 11100 */ - // 0x40, /* 01000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x60, /* 01100 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x60, /* 01100 */ + 0x40, /* 01000 */ + 0x40, /* 01000 */ + 0xE0, /* 11100 */ + 0x40, /* 01000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=13, hex=0x0D, ascii="^M" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x20, /* 00100 */ - // 0x30, /* 00110 */ - // 0x30, /* 00110 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0xE0, /* 11100 */ - // 0xC0, /* 11000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x20, /* 00100 */ + 0x30, /* 00110 */ + 0x30, /* 00110 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0xE0, /* 11100 */ + 0xC0, /* 11000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=14, hex=0x0E, ascii="^N" // */ - // 0x30, /* 00110 */ - // 0x50, /* 01010 */ - // 0x70, /* 01110 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x70, /* 01110 */ - // 0x70, /* 01110 */ - // 0xC0, /* 11000 */ - // 0xC0, /* 11000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x30, /* 00110 */ + 0x50, /* 01010 */ + 0x70, /* 01110 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x70, /* 01110 */ + 0x70, /* 01110 */ + 0xC0, /* 11000 */ + 0xC0, /* 11000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=15, hex=0x0F, ascii="^O" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0xA8, /* 10101 */ - // 0x70, /* 01110 */ - // 0x88, /* 10001 */ - // 0x70, /* 01110 */ - // 0xA8, /* 10101 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0xA8, /* 10101 */ + 0x70, /* 01110 */ + 0x88, /* 10001 */ + 0x70, /* 01110 */ + 0xA8, /* 10101 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=16, hex=0x10, ascii="^P" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x80, /* 10000 */ - // 0xC0, /* 11000 */ - // 0xE0, /* 11100 */ - // 0xF0, /* 11110 */ - // 0xE0, /* 11100 */ - // 0xC0, /* 11000 */ - // 0x80, /* 10000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x80, /* 10000 */ + 0xC0, /* 11000 */ + 0xE0, /* 11100 */ + 0xF0, /* 11110 */ + 0xE0, /* 11100 */ + 0xC0, /* 11000 */ + 0x80, /* 10000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=17, hex=0x11, ascii="^Q" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x10, /* 00010 */ - // 0x30, /* 00110 */ - // 0x70, /* 01110 */ - // 0xF0, /* 11110 */ - // 0x70, /* 01110 */ - // 0x30, /* 00110 */ - // 0x10, /* 00010 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x10, /* 00010 */ + 0x30, /* 00110 */ + 0x70, /* 01110 */ + 0xF0, /* 11110 */ + 0x70, /* 01110 */ + 0x30, /* 00110 */ + 0x10, /* 00010 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=18, hex=0x12, ascii="^R" // */ - // 0x00, /* 00000 */ - // 0x20, /* 00100 */ - // 0x70, /* 01110 */ - // 0xA8, /* 10101 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0xA8, /* 10101 */ - // 0x70, /* 01110 */ - // 0x20, /* 00100 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x20, /* 00100 */ + 0x70, /* 01110 */ + 0xA8, /* 10101 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0xA8, /* 10101 */ + 0x70, /* 01110 */ + 0x20, /* 00100 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=19, hex=0x13, ascii="^S" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x00, /* 00000 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x00, /* 00000 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=20, hex=0x14, ascii="^T" // */ - // 0x00, /* 00000 */ - // 0x70, /* 01110 */ - // 0xD0, /* 11010 */ - // 0xD0, /* 11010 */ - // 0xD0, /* 11010 */ - // 0xD0, /* 11010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x70, /* 01110 */ + 0xD0, /* 11010 */ + 0xD0, /* 11010 */ + 0xD0, /* 11010 */ + 0xD0, /* 11010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=21, hex=0x15, ascii="^U" // */ - // 0x00, /* 00000 */ - // 0x60, /* 01100 */ - // 0x90, /* 10010 */ - // 0x80, /* 10000 */ - // 0x60, /* 01100 */ - // 0x90, /* 10010 */ - // 0x60, /* 01100 */ - // 0x10, /* 00010 */ - // 0x90, /* 10010 */ - // 0x60, /* 01100 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x60, /* 01100 */ + 0x90, /* 10010 */ + 0x80, /* 10000 */ + 0x60, /* 01100 */ + 0x90, /* 10010 */ + 0x60, /* 01100 */ + 0x10, /* 00010 */ + 0x90, /* 10010 */ + 0x60, /* 01100 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=22, hex=0x16, ascii="^V" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0xF0, /* 11110 */ - // 0xF0, /* 11110 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0xF0, /* 11110 */ + 0xF0, /* 11110 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=23, hex=0x17, ascii="^W" // */ - // 0x00, /* 00000 */ - // 0x20, /* 00100 */ - // 0x70, /* 01110 */ - // 0xA8, /* 10101 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0xA8, /* 10101 */ - // 0x70, /* 01110 */ - // 0x20, /* 00100 */ - // 0xF8, /* 11111 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x20, /* 00100 */ + 0x70, /* 01110 */ + 0xA8, /* 10101 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0xA8, /* 10101 */ + 0x70, /* 01110 */ + 0x20, /* 00100 */ + 0xF8, /* 11111 */ + 0x00, /* 00000 */ // /* // * code=24, hex=0x18, ascii="^X" // */ - // 0x00, /* 00000 */ - // 0x20, /* 00100 */ - // 0x70, /* 01110 */ - // 0xA8, /* 10101 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x20, /* 00100 */ + 0x70, /* 01110 */ + 0xA8, /* 10101 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=25, hex=0x19, ascii="^Y" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0xA8, /* 10101 */ - // 0x70, /* 01110 */ - // 0x20, /* 00100 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0xA8, /* 10101 */ + 0x70, /* 01110 */ + 0x20, /* 00100 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=26, hex=0x1A, ascii="^Z" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x40, /* 01000 */ - // 0x20, /* 00100 */ - // 0xF0, /* 11110 */ - // 0x20, /* 00100 */ - // 0x40, /* 01000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x40, /* 01000 */ + 0x20, /* 00100 */ + 0xF0, /* 11110 */ + 0x20, /* 00100 */ + 0x40, /* 01000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=27, hex=0x1B, ascii="^[" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x20, /* 00100 */ - // 0x40, /* 01000 */ - // 0xF0, /* 11110 */ - // 0x40, /* 01000 */ - // 0x20, /* 00100 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x20, /* 00100 */ + 0x40, /* 01000 */ + 0xF0, /* 11110 */ + 0x40, /* 01000 */ + 0x20, /* 00100 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=28, hex=0x1C, ascii="^\" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x80, /* 10000 */ - // 0x80, /* 10000 */ - // 0xF0, /* 11110 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x80, /* 10000 */ + 0x80, /* 10000 */ + 0xF0, /* 11110 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=29, hex=0x1D, ascii="^]" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0xF8, /* 11111 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0xF8, /* 11111 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=30, hex=0x1E, ascii="^^" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x70, /* 01110 */ - // 0x70, /* 01110 */ - // 0xF8, /* 11111 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x70, /* 01110 */ + 0x70, /* 01110 */ + 0xF8, /* 11111 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=31, hex=0x1F, ascii="^_" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0xF8, /* 11111 */ - // 0x70, /* 01110 */ - // 0x70, /* 01110 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0xF8, /* 11111 */ + 0x70, /* 01110 */ + 0x70, /* 01110 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ +#endif /* * code=32, hex=0x20, ascii=" " */ @@ -2035,2068 +2047,2072 @@ static const unsigned char console_font_5x12[] PROGMEM = { 0x00, /* 00000 */ 0x00, /* 00000 */ 0x00, /* 00000 */ - +#if defined(WLED_ENABLE_FULL_FONTS) // /* // * code=127, hex=0x7F, ascii="^?" // */ - // 0x00, /* 00000 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x88, /* 10001 */ - // 0x88, /* 10001 */ - // 0x88, /* 10001 */ - // 0x88, /* 10001 */ - // 0xF8, /* 11111 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x88, /* 10001 */ + 0x88, /* 10001 */ + 0x88, /* 10001 */ + 0x88, /* 10001 */ + 0xF8, /* 11111 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=128, hex=0x80, ascii="!^@" // */ - // 0x00, /* 00000 */ - // 0x60, /* 01100 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x80, /* 10000 */ - // 0x80, /* 10000 */ - // 0x80, /* 10000 */ - // 0x80, /* 10000 */ - // 0x90, /* 10010 */ - // 0x60, /* 01100 */ - // 0x20, /* 00100 */ - // 0x40, /* 01000 */ + 0x00, /* 00000 */ + 0x60, /* 01100 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x80, /* 10000 */ + 0x80, /* 10000 */ + 0x80, /* 10000 */ + 0x80, /* 10000 */ + 0x90, /* 10010 */ + 0x60, /* 01100 */ + 0x20, /* 00100 */ + 0x40, /* 01000 */ // /* // * code=129, hex=0x81, ascii="!^A" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x50, /* 01010 */ - // 0x00, /* 00000 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x70, /* 01110 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x50, /* 01010 */ + 0x00, /* 00000 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x70, /* 01110 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=130, hex=0x82, ascii="!^B" // */ - // 0x00, /* 00000 */ - // 0x30, /* 00110 */ - // 0x40, /* 01000 */ - // 0x00, /* 00000 */ - // 0x60, /* 01100 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0xF0, /* 11110 */ - // 0x80, /* 10000 */ - // 0x70, /* 01110 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x30, /* 00110 */ + 0x40, /* 01000 */ + 0x00, /* 00000 */ + 0x60, /* 01100 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0xF0, /* 11110 */ + 0x80, /* 10000 */ + 0x70, /* 01110 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=131, hex=0x83, ascii="!^C" // */ - // 0x00, /* 00000 */ - // 0x60, /* 01100 */ - // 0x90, /* 10010 */ - // 0x00, /* 00000 */ - // 0x60, /* 01100 */ - // 0x90, /* 10010 */ - // 0x10, /* 00010 */ - // 0x70, /* 01110 */ - // 0x90, /* 10010 */ - // 0x70, /* 01110 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x60, /* 01100 */ + 0x90, /* 10010 */ + 0x00, /* 00000 */ + 0x60, /* 01100 */ + 0x90, /* 10010 */ + 0x10, /* 00010 */ + 0x70, /* 01110 */ + 0x90, /* 10010 */ + 0x70, /* 01110 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=132, hex=0x84, ascii="!^D" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x50, /* 01010 */ - // 0x00, /* 00000 */ - // 0x60, /* 01100 */ - // 0x90, /* 10010 */ - // 0x10, /* 00010 */ - // 0x70, /* 01110 */ - // 0x90, /* 10010 */ - // 0x70, /* 01110 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x50, /* 01010 */ + 0x00, /* 00000 */ + 0x60, /* 01100 */ + 0x90, /* 10010 */ + 0x10, /* 00010 */ + 0x70, /* 01110 */ + 0x90, /* 10010 */ + 0x70, /* 01110 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=133, hex=0x85, ascii="!^E" // */ - // 0x00, /* 00000 */ - // 0xC0, /* 11000 */ - // 0x20, /* 00100 */ - // 0x00, /* 00000 */ - // 0x60, /* 01100 */ - // 0x90, /* 10010 */ - // 0x10, /* 00010 */ - // 0x70, /* 01110 */ - // 0x90, /* 10010 */ - // 0x70, /* 01110 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0xC0, /* 11000 */ + 0x20, /* 00100 */ + 0x00, /* 00000 */ + 0x60, /* 01100 */ + 0x90, /* 10010 */ + 0x10, /* 00010 */ + 0x70, /* 01110 */ + 0x90, /* 10010 */ + 0x70, /* 01110 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=134, hex=0x86, ascii="!^F" // */ - // 0x00, /* 00000 */ - // 0x20, /* 00100 */ - // 0x50, /* 01010 */ - // 0x20, /* 00100 */ - // 0x60, /* 01100 */ - // 0x90, /* 10010 */ - // 0x10, /* 00010 */ - // 0x70, /* 01110 */ - // 0x90, /* 10010 */ - // 0x70, /* 01110 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x20, /* 00100 */ + 0x50, /* 01010 */ + 0x20, /* 00100 */ + 0x60, /* 01100 */ + 0x90, /* 10010 */ + 0x10, /* 00010 */ + 0x70, /* 01110 */ + 0x90, /* 10010 */ + 0x70, /* 01110 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=135, hex=0x87, ascii="!^G" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x70, /* 01110 */ - // 0x80, /* 10000 */ - // 0x80, /* 10000 */ - // 0x80, /* 10000 */ - // 0x80, /* 10000 */ - // 0x70, /* 01110 */ - // 0x20, /* 00100 */ - // 0xC0, /* 11000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x70, /* 01110 */ + 0x80, /* 10000 */ + 0x80, /* 10000 */ + 0x80, /* 10000 */ + 0x80, /* 10000 */ + 0x70, /* 01110 */ + 0x20, /* 00100 */ + 0xC0, /* 11000 */ // /* // * code=136, hex=0x88, ascii="!^H" // */ - // 0x00, /* 00000 */ - // 0x60, /* 01100 */ - // 0x90, /* 10010 */ - // 0x00, /* 00000 */ - // 0x60, /* 01100 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0xF0, /* 11110 */ - // 0x80, /* 10000 */ - // 0x70, /* 01110 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x60, /* 01100 */ + 0x90, /* 10010 */ + 0x00, /* 00000 */ + 0x60, /* 01100 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0xF0, /* 11110 */ + 0x80, /* 10000 */ + 0x70, /* 01110 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=137, hex=0x89, ascii="!^I" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x50, /* 01010 */ - // 0x00, /* 00000 */ - // 0x60, /* 01100 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0xF0, /* 11110 */ - // 0x80, /* 10000 */ - // 0x70, /* 01110 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x50, /* 01010 */ + 0x00, /* 00000 */ + 0x60, /* 01100 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0xF0, /* 11110 */ + 0x80, /* 10000 */ + 0x70, /* 01110 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=138, hex=0x8A, ascii="!^J" // */ - // 0x00, /* 00000 */ - // 0xC0, /* 11000 */ - // 0x20, /* 00100 */ - // 0x00, /* 00000 */ - // 0x60, /* 01100 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0xF0, /* 11110 */ - // 0x80, /* 10000 */ - // 0x70, /* 01110 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0xC0, /* 11000 */ + 0x20, /* 00100 */ + 0x00, /* 00000 */ + 0x60, /* 01100 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0xF0, /* 11110 */ + 0x80, /* 10000 */ + 0x70, /* 01110 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=139, hex=0x8B, ascii="!^K" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x50, /* 01010 */ - // 0x00, /* 00000 */ - // 0x60, /* 01100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x70, /* 01110 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x50, /* 01010 */ + 0x00, /* 00000 */ + 0x60, /* 01100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x70, /* 01110 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=140, hex=0x8C, ascii="!^L" // */ - // 0x00, /* 00000 */ - // 0x60, /* 01100 */ - // 0x90, /* 10010 */ - // 0x00, /* 00000 */ - // 0x60, /* 01100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x70, /* 01110 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x60, /* 01100 */ + 0x90, /* 10010 */ + 0x00, /* 00000 */ + 0x60, /* 01100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x70, /* 01110 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=141, hex=0x8D, ascii="!^M" // */ - // 0x00, /* 00000 */ - // 0x60, /* 01100 */ - // 0x10, /* 00010 */ - // 0x00, /* 00000 */ - // 0x60, /* 01100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x70, /* 01110 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x60, /* 01100 */ + 0x10, /* 00010 */ + 0x00, /* 00000 */ + 0x60, /* 01100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x70, /* 01110 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=142, hex=0x8E, ascii="!^N" // */ - // 0x50, /* 01010 */ - // 0x00, /* 00000 */ - // 0x60, /* 01100 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0xF0, /* 11110 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x50, /* 01010 */ + 0x00, /* 00000 */ + 0x60, /* 01100 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0xF0, /* 11110 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=143, hex=0x8F, ascii="!^O" // */ - // 0x20, /* 00100 */ - // 0x50, /* 01010 */ - // 0x20, /* 00100 */ - // 0x60, /* 01100 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0xF0, /* 11110 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x20, /* 00100 */ + 0x50, /* 01010 */ + 0x20, /* 00100 */ + 0x60, /* 01100 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0xF0, /* 11110 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=144, hex=0x90, ascii="!^P" // */ - // 0x30, /* 00110 */ - // 0x40, /* 01000 */ - // 0x00, /* 00000 */ - // 0xF0, /* 11110 */ - // 0x80, /* 10000 */ - // 0x80, /* 10000 */ - // 0xF0, /* 11110 */ - // 0x80, /* 10000 */ - // 0x80, /* 10000 */ - // 0xF0, /* 11110 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x30, /* 00110 */ + 0x40, /* 01000 */ + 0x00, /* 00000 */ + 0xF0, /* 11110 */ + 0x80, /* 10000 */ + 0x80, /* 10000 */ + 0xF0, /* 11110 */ + 0x80, /* 10000 */ + 0x80, /* 10000 */ + 0xF0, /* 11110 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=145, hex=0x91, ascii="!^Q" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x70, /* 01110 */ - // 0x28, /* 00101 */ - // 0x28, /* 00101 */ - // 0x70, /* 01110 */ - // 0xA0, /* 10100 */ - // 0x50, /* 01010 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x70, /* 01110 */ + 0x28, /* 00101 */ + 0x28, /* 00101 */ + 0x70, /* 01110 */ + 0xA0, /* 10100 */ + 0x50, /* 01010 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=146, hex=0x92, ascii="!^R" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x70, /* 01110 */ - // 0xE0, /* 11100 */ - // 0xA0, /* 10100 */ - // 0xA0, /* 10100 */ - // 0xF0, /* 11110 */ - // 0xA0, /* 10100 */ - // 0xA0, /* 10100 */ - // 0xB0, /* 10110 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x70, /* 01110 */ + 0xE0, /* 11100 */ + 0xA0, /* 10100 */ + 0xA0, /* 10100 */ + 0xF0, /* 11110 */ + 0xA0, /* 10100 */ + 0xA0, /* 10100 */ + 0xB0, /* 10110 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=147, hex=0x93, ascii="!^S" // */ - // 0x00, /* 00000 */ - // 0x60, /* 01100 */ - // 0x90, /* 10010 */ - // 0x00, /* 00000 */ - // 0x60, /* 01100 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x60, /* 01100 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x60, /* 01100 */ + 0x90, /* 10010 */ + 0x00, /* 00000 */ + 0x60, /* 01100 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x60, /* 01100 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=148, hex=0x94, ascii="!^T" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x50, /* 01010 */ - // 0x00, /* 00000 */ - // 0x60, /* 01100 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x60, /* 01100 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x50, /* 01010 */ + 0x00, /* 00000 */ + 0x60, /* 01100 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x60, /* 01100 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=149, hex=0x95, ascii="!^U" // */ - // 0x00, /* 00000 */ - // 0x60, /* 01100 */ - // 0x10, /* 00010 */ - // 0x00, /* 00000 */ - // 0x60, /* 01100 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x60, /* 01100 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x60, /* 01100 */ + 0x10, /* 00010 */ + 0x00, /* 00000 */ + 0x60, /* 01100 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x60, /* 01100 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=150, hex=0x96, ascii="!^V" // */ - // 0x00, /* 00000 */ - // 0x60, /* 01100 */ - // 0x90, /* 10010 */ - // 0x00, /* 00000 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x70, /* 01110 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x60, /* 01100 */ + 0x90, /* 10010 */ + 0x00, /* 00000 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x70, /* 01110 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=151, hex=0x97, ascii="!^W" // */ - // 0x00, /* 00000 */ - // 0xC0, /* 11000 */ - // 0x20, /* 00100 */ - // 0x00, /* 00000 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x70, /* 01110 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0xC0, /* 11000 */ + 0x20, /* 00100 */ + 0x00, /* 00000 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x70, /* 01110 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=152, hex=0x98, ascii="!^X" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x50, /* 01010 */ - // 0x00, /* 00000 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x70, /* 01110 */ - // 0x10, /* 00010 */ - // 0xE0, /* 11100 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x50, /* 01010 */ + 0x00, /* 00000 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x70, /* 01110 */ + 0x10, /* 00010 */ + 0xE0, /* 11100 */ // /* // * code=153, hex=0x99, ascii="!^Y" // */ - // 0x50, /* 01010 */ - // 0x00, /* 00000 */ - // 0x60, /* 01100 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x60, /* 01100 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x50, /* 01010 */ + 0x00, /* 00000 */ + 0x60, /* 01100 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x60, /* 01100 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=154, hex=0x9A, ascii="!^Z" // */ - // 0x50, /* 01010 */ - // 0x00, /* 00000 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x70, /* 01110 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x50, /* 01010 */ + 0x00, /* 00000 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x70, /* 01110 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=155, hex=0x9B, ascii="!^[" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x20, /* 00100 */ - // 0x70, /* 01110 */ - // 0x88, /* 10001 */ - // 0x80, /* 10000 */ - // 0x88, /* 10001 */ - // 0x70, /* 01110 */ - // 0x20, /* 00100 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x20, /* 00100 */ + 0x70, /* 01110 */ + 0x88, /* 10001 */ + 0x80, /* 10000 */ + 0x88, /* 10001 */ + 0x70, /* 01110 */ + 0x20, /* 00100 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=156, hex=0x9C, ascii="!^\" // */ - // 0x00, /* 00000 */ - // 0x20, /* 00100 */ - // 0x50, /* 01010 */ - // 0x40, /* 01000 */ - // 0x40, /* 01000 */ - // 0xE0, /* 11100 */ - // 0x40, /* 01000 */ - // 0x40, /* 01000 */ - // 0xD0, /* 11010 */ - // 0xF0, /* 11110 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x20, /* 00100 */ + 0x50, /* 01010 */ + 0x40, /* 01000 */ + 0x40, /* 01000 */ + 0xE0, /* 11100 */ + 0x40, /* 01000 */ + 0x40, /* 01000 */ + 0xD0, /* 11010 */ + 0xF0, /* 11110 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=157, hex=0x9D, ascii="!^]" // */ - // 0x00, /* 00000 */ - // 0x88, /* 10001 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0xF8, /* 11111 */ - // 0x20, /* 00100 */ - // 0xF8, /* 11111 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x88, /* 10001 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0xF8, /* 11111 */ + 0x20, /* 00100 */ + 0xF8, /* 11111 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=158, hex=0x9E, ascii="!^^" // */ - // 0x00, /* 00000 */ - // 0xE0, /* 11100 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0xE0, /* 11100 */ - // 0x90, /* 10010 */ - // 0xB8, /* 10111 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0xE0, /* 11100 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0xE0, /* 11100 */ + 0x90, /* 10010 */ + 0xB8, /* 10111 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=159, hex=0x9F, ascii="!^_" // */ - // 0x10, /* 00010 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x70, /* 01110 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0xA0, /* 10100 */ - // 0x40, /* 01000 */ + 0x10, /* 00010 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x70, /* 01110 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0xA0, /* 10100 */ + 0x40, /* 01000 */ // /* // * code=160, hex=0xA0, ascii="! " // */ - // 0x00, /* 00000 */ - // 0x30, /* 00110 */ - // 0x40, /* 01000 */ - // 0x00, /* 00000 */ - // 0x60, /* 01100 */ - // 0x90, /* 10010 */ - // 0x10, /* 00010 */ - // 0x70, /* 01110 */ - // 0x90, /* 10010 */ - // 0x70, /* 01110 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x30, /* 00110 */ + 0x40, /* 01000 */ + 0x00, /* 00000 */ + 0x60, /* 01100 */ + 0x90, /* 10010 */ + 0x10, /* 00010 */ + 0x70, /* 01110 */ + 0x90, /* 10010 */ + 0x70, /* 01110 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=161, hex=0xA1, ascii="!!" // */ - // 0x00, /* 00000 */ - // 0x30, /* 00110 */ - // 0x40, /* 01000 */ - // 0x00, /* 00000 */ - // 0x60, /* 01100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x70, /* 01110 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x30, /* 00110 */ + 0x40, /* 01000 */ + 0x00, /* 00000 */ + 0x60, /* 01100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x70, /* 01110 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=162, hex=0xA2, ascii="!"" // */ - // 0x00, /* 00000 */ - // 0x30, /* 00110 */ - // 0x40, /* 01000 */ - // 0x00, /* 00000 */ - // 0x60, /* 01100 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x60, /* 01100 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x30, /* 00110 */ + 0x40, /* 01000 */ + 0x00, /* 00000 */ + 0x60, /* 01100 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x60, /* 01100 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=163, hex=0xA3, ascii="!#" // */ - // 0x00, /* 00000 */ - // 0x30, /* 00110 */ - // 0x40, /* 01000 */ - // 0x00, /* 00000 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x70, /* 01110 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x30, /* 00110 */ + 0x40, /* 01000 */ + 0x00, /* 00000 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x70, /* 01110 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=164, hex=0xA4, ascii="!$" // */ - // 0x00, /* 00000 */ - // 0x50, /* 01010 */ - // 0xA0, /* 10100 */ - // 0x00, /* 00000 */ - // 0xA0, /* 10100 */ - // 0xD0, /* 11010 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x50, /* 01010 */ + 0xA0, /* 10100 */ + 0x00, /* 00000 */ + 0xA0, /* 10100 */ + 0xD0, /* 11010 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=165, hex=0xA5, ascii="!%" // */ - // 0x50, /* 01010 */ - // 0xA0, /* 10100 */ - // 0x00, /* 00000 */ - // 0x90, /* 10010 */ - // 0xD0, /* 11010 */ - // 0xF0, /* 11110 */ - // 0xB0, /* 10110 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x50, /* 01010 */ + 0xA0, /* 10100 */ + 0x00, /* 00000 */ + 0x90, /* 10010 */ + 0xD0, /* 11010 */ + 0xF0, /* 11110 */ + 0xB0, /* 10110 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=166, hex=0xA6, ascii="!&" // */ - // 0x00, /* 00000 */ - // 0x60, /* 01100 */ - // 0x10, /* 00010 */ - // 0x70, /* 01110 */ - // 0x90, /* 10010 */ - // 0x70, /* 01110 */ - // 0x00, /* 00000 */ - // 0xF0, /* 11110 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x60, /* 01100 */ + 0x10, /* 00010 */ + 0x70, /* 01110 */ + 0x90, /* 10010 */ + 0x70, /* 01110 */ + 0x00, /* 00000 */ + 0xF0, /* 11110 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=167, hex=0xA7, ascii="!'" // */ - // 0x00, /* 00000 */ - // 0x60, /* 01100 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x60, /* 01100 */ - // 0x00, /* 00000 */ - // 0xF0, /* 11110 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x60, /* 01100 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x60, /* 01100 */ + 0x00, /* 00000 */ + 0xF0, /* 11110 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=168, hex=0xA8, ascii="!(" // */ - // 0x00, /* 00000 */ - // 0x40, /* 01000 */ - // 0x40, /* 01000 */ - // 0x00, /* 00000 */ - // 0x40, /* 01000 */ - // 0x40, /* 01000 */ - // 0x80, /* 10000 */ - // 0x80, /* 10000 */ - // 0x90, /* 10010 */ - // 0x60, /* 01100 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x40, /* 01000 */ + 0x40, /* 01000 */ + 0x00, /* 00000 */ + 0x40, /* 01000 */ + 0x40, /* 01000 */ + 0x80, /* 10000 */ + 0x80, /* 10000 */ + 0x90, /* 10010 */ + 0x60, /* 01100 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=169, hex=0xA9, ascii="!)" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0xF0, /* 11110 */ - // 0x80, /* 10000 */ - // 0x80, /* 10000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0xF0, /* 11110 */ + 0x80, /* 10000 */ + 0x80, /* 10000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=170, hex=0xAA, ascii="!*" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0xF0, /* 11110 */ - // 0x10, /* 00010 */ - // 0x10, /* 00010 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0xF0, /* 11110 */ + 0x10, /* 00010 */ + 0x10, /* 00010 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=171, hex=0xAB, ascii="!+" // */ - // 0x00, /* 00000 */ - // 0x40, /* 01000 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x20, /* 00100 */ - // 0x40, /* 01000 */ - // 0x70, /* 01110 */ - // 0x90, /* 10010 */ - // 0xA0, /* 10100 */ - // 0x30, /* 00110 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x40, /* 01000 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x20, /* 00100 */ + 0x40, /* 01000 */ + 0x70, /* 01110 */ + 0x90, /* 10010 */ + 0xA0, /* 10100 */ + 0x30, /* 00110 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=172, hex=0xAC, ascii="!," // */ - // 0x00, /* 00000 */ - // 0x40, /* 01000 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x20, /* 00100 */ - // 0x40, /* 01000 */ - // 0x50, /* 01010 */ - // 0xB0, /* 10110 */ - // 0xB0, /* 10110 */ - // 0x10, /* 00010 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x40, /* 01000 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x20, /* 00100 */ + 0x40, /* 01000 */ + 0x50, /* 01010 */ + 0xB0, /* 10110 */ + 0xB0, /* 10110 */ + 0x10, /* 00010 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=173, hex=0xAD, ascii="!-" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x20, /* 00100 */ - // 0x00, /* 00000 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x20, /* 00100 */ + 0x00, /* 00000 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=174, hex=0xAE, ascii="!." // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0xA0, /* 10100 */ - // 0xA0, /* 10100 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0xA0, /* 10100 */ + 0xA0, /* 10100 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=175, hex=0xAF, ascii="!/" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0xA0, /* 10100 */ - // 0xA0, /* 10100 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0xA0, /* 10100 */ - // 0xA0, /* 10100 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0xA0, /* 10100 */ + 0xA0, /* 10100 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0xA0, /* 10100 */ + 0xA0, /* 10100 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=176, hex=0xB0, ascii="!0" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0xA8, /* 10101 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x50, /* 01010 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0xA8, /* 10101 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x50, /* 01010 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0xA8, /* 10101 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x50, /* 01010 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0xA8, /* 10101 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x50, /* 01010 */ // /* // * code=177, hex=0xB1, ascii="!1" // */ - // 0x00, /* 00000 */ - // 0x50, /* 01010 */ - // 0x00, /* 00000 */ - // 0xA8, /* 10101 */ - // 0x00, /* 00000 */ - // 0x50, /* 01010 */ - // 0x00, /* 00000 */ - // 0xA8, /* 10101 */ - // 0x00, /* 00000 */ - // 0x50, /* 01010 */ - // 0x00, /* 00000 */ - // 0xA8, /* 10101 */ + 0x00, /* 00000 */ + 0x50, /* 01010 */ + 0x00, /* 00000 */ + 0xA8, /* 10101 */ + 0x00, /* 00000 */ + 0x50, /* 01010 */ + 0x00, /* 00000 */ + 0xA8, /* 10101 */ + 0x00, /* 00000 */ + 0x50, /* 01010 */ + 0x00, /* 00000 */ + 0xA8, /* 10101 */ // /* // * code=178, hex=0xB2, ascii="!2" // */ - // 0x50, /* 01010 */ - // 0xA8, /* 10101 */ - // 0x50, /* 01010 */ - // 0xA8, /* 10101 */ - // 0x50, /* 01010 */ - // 0xA8, /* 10101 */ - // 0x50, /* 01010 */ - // 0xA8, /* 10101 */ - // 0x50, /* 01010 */ - // 0xA8, /* 10101 */ - // 0x50, /* 01010 */ - // 0xA8, /* 10101 */ + 0x50, /* 01010 */ + 0xA8, /* 10101 */ + 0x50, /* 01010 */ + 0xA8, /* 10101 */ + 0x50, /* 01010 */ + 0xA8, /* 10101 */ + 0x50, /* 01010 */ + 0xA8, /* 10101 */ + 0x50, /* 01010 */ + 0xA8, /* 10101 */ + 0x50, /* 01010 */ + 0xA8, /* 10101 */ // /* // * code=179, hex=0xB3, ascii="!3" // */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ // /* // * code=180, hex=0xB4, ascii="!4" // */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0xE0, /* 11100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0xE0, /* 11100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ // /* // * code=181, hex=0xB5, ascii="!5" // */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0xE0, /* 11100 */ - // 0x20, /* 00100 */ - // 0xE0, /* 11100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0xE0, /* 11100 */ + 0x20, /* 00100 */ + 0xE0, /* 11100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ // /* // * code=182, hex=0xB6, ascii="!6" // */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0xD0, /* 11010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0xD0, /* 11010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ // /* // * code=183, hex=0xB7, ascii="!7" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0xF0, /* 11110 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0xF0, /* 11110 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ // /* // * code=184, hex=0xB8, ascii="!8" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0xE0, /* 11100 */ - // 0x20, /* 00100 */ - // 0xE0, /* 11100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0xE0, /* 11100 */ + 0x20, /* 00100 */ + 0xE0, /* 11100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ // /* // * code=185, hex=0xB9, ascii="!9" // */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0xD0, /* 11010 */ - // 0x10, /* 00010 */ - // 0xD0, /* 11010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0xD0, /* 11010 */ + 0x10, /* 00010 */ + 0xD0, /* 11010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ // /* // * code=186, hex=0xBA, ascii="!:" // */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ // /* // * code=187, hex=0xBB, ascii="!;" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0xF0, /* 11110 */ - // 0x10, /* 00010 */ - // 0xD0, /* 11010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0xF0, /* 11110 */ + 0x10, /* 00010 */ + 0xD0, /* 11010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ // /* // * code=188, hex=0xBC, ascii="!<" // */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0xD0, /* 11010 */ - // 0x10, /* 00010 */ - // 0xF0, /* 11110 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0xD0, /* 11010 */ + 0x10, /* 00010 */ + 0xF0, /* 11110 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=189, hex=0xBD, ascii="!=" // */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0xF0, /* 11110 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0xF0, /* 11110 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=190, hex=0xBE, ascii="!>" // */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0xE0, /* 11100 */ - // 0x20, /* 00100 */ - // 0xE0, /* 11100 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0xE0, /* 11100 */ + 0x20, /* 00100 */ + 0xE0, /* 11100 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=191, hex=0xBF, ascii="!?" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0xE0, /* 11100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0xE0, /* 11100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ // /* // * code=192, hex=0xC0, ascii="!@" // */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x38, /* 00111 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x38, /* 00111 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=193, hex=0xC1, ascii="!A" // */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0xF8, /* 11111 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0xF8, /* 11111 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=194, hex=0xC2, ascii="!B" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0xF8, /* 11111 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0xF8, /* 11111 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ // /* // * code=195, hex=0xC3, ascii="!C" // */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x38, /* 00111 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x38, /* 00111 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ // /* // * code=196, hex=0xC4, ascii="!D" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0xF8, /* 11111 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0xF8, /* 11111 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=197, hex=0xC5, ascii="!E" // */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0xF8, /* 11111 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0xF8, /* 11111 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ // /* // * code=198, hex=0xC6, ascii="!F" // */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x38, /* 00111 */ - // 0x20, /* 00100 */ - // 0x38, /* 00111 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x38, /* 00111 */ + 0x20, /* 00100 */ + 0x38, /* 00111 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ // /* // * code=199, hex=0xC7, ascii="!G" // */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x58, /* 01011 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x58, /* 01011 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ // /* // * code=200, hex=0xC8, ascii="!H" // */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x58, /* 01011 */ - // 0x40, /* 01000 */ - // 0x78, /* 01111 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x58, /* 01011 */ + 0x40, /* 01000 */ + 0x78, /* 01111 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=201, hex=0xC9, ascii="!I" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x78, /* 01111 */ - // 0x40, /* 01000 */ - // 0x58, /* 01011 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x78, /* 01111 */ + 0x40, /* 01000 */ + 0x58, /* 01011 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ // /* // * code=202, hex=0xCA, ascii="!J" // */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0xD8, /* 11011 */ - // 0x00, /* 00000 */ - // 0xF8, /* 11111 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0xD8, /* 11011 */ + 0x00, /* 00000 */ + 0xF8, /* 11111 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=203, hex=0xCB, ascii="!K" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0xF8, /* 11111 */ - // 0x00, /* 00000 */ - // 0xD8, /* 11011 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0xF8, /* 11111 */ + 0x00, /* 00000 */ + 0xD8, /* 11011 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ // /* // * code=204, hex=0xCC, ascii="!L" // */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x58, /* 01011 */ - // 0x40, /* 01000 */ - // 0x58, /* 01011 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x58, /* 01011 */ + 0x40, /* 01000 */ + 0x58, /* 01011 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ // /* // * code=205, hex=0xCD, ascii="!M" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0xF8, /* 11111 */ - // 0x00, /* 00000 */ - // 0xF8, /* 11111 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0xF8, /* 11111 */ + 0x00, /* 00000 */ + 0xF8, /* 11111 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=206, hex=0xCE, ascii="!N" // */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0xD8, /* 11011 */ - // 0x00, /* 00000 */ - // 0xD8, /* 11011 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0xD8, /* 11011 */ + 0x00, /* 00000 */ + 0xD8, /* 11011 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ // /* // * code=207, hex=0xCF, ascii="!O" // */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0xF8, /* 11111 */ - // 0x00, /* 00000 */ - // 0xF8, /* 11111 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0xF8, /* 11111 */ + 0x00, /* 00000 */ + 0xF8, /* 11111 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=208, hex=0xD0, ascii="!P" // */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0xF8, /* 11111 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0xF8, /* 11111 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=209, hex=0xD1, ascii="!Q" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0xF8, /* 11111 */ - // 0x00, /* 00000 */ - // 0xF8, /* 11111 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0xF8, /* 11111 */ + 0x00, /* 00000 */ + 0xF8, /* 11111 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ // /* // * code=210, hex=0xD2, ascii="!R" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0xF8, /* 11111 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0xF8, /* 11111 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ // /* // * code=211, hex=0xD3, ascii="!S" // */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x78, /* 01111 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x78, /* 01111 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=212, hex=0xD4, ascii="!T" // */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x38, /* 00111 */ - // 0x20, /* 00100 */ - // 0x38, /* 00111 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x38, /* 00111 */ + 0x20, /* 00100 */ + 0x38, /* 00111 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=213, hex=0xD5, ascii="!U" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x38, /* 00111 */ - // 0x20, /* 00100 */ - // 0x38, /* 00111 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x38, /* 00111 */ + 0x20, /* 00100 */ + 0x38, /* 00111 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ // /* // * code=214, hex=0xD6, ascii="!V" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x78, /* 01111 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x78, /* 01111 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ // /* // * code=215, hex=0xD7, ascii="!W" // */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0xD8, /* 11011 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0xD8, /* 11011 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ // /* // * code=216, hex=0xD8, ascii="!X" // */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0xF8, /* 11111 */ - // 0x00, /* 00000 */ - // 0xF8, /* 11111 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0xF8, /* 11111 */ + 0x00, /* 00000 */ + 0xF8, /* 11111 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ // /* // * code=217, hex=0xD9, ascii="!Y" // */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0xE0, /* 11100 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0xE0, /* 11100 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=218, hex=0xDA, ascii="!Z" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x38, /* 00111 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x38, /* 00111 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ // /* // * code=219, hex=0xDB, ascii="![" // */ - // 0xF8, /* 11111 */ - // 0xF8, /* 11111 */ - // 0xF8, /* 11111 */ - // 0xF8, /* 11111 */ - // 0xF8, /* 11111 */ - // 0xF8, /* 11111 */ - // 0xF8, /* 11111 */ - // 0xF8, /* 11111 */ - // 0xF8, /* 11111 */ - // 0xF8, /* 11111 */ - // 0xF8, /* 11111 */ - // 0xF8, /* 11111 */ + 0xF8, /* 11111 */ + 0xF8, /* 11111 */ + 0xF8, /* 11111 */ + 0xF8, /* 11111 */ + 0xF8, /* 11111 */ + 0xF8, /* 11111 */ + 0xF8, /* 11111 */ + 0xF8, /* 11111 */ + 0xF8, /* 11111 */ + 0xF8, /* 11111 */ + 0xF8, /* 11111 */ + 0xF8, /* 11111 */ // /* // * code=220, hex=0xDC, ascii="!\" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0xF8, /* 11111 */ - // 0xF8, /* 11111 */ - // 0xF8, /* 11111 */ - // 0xF8, /* 11111 */ - // 0xF8, /* 11111 */ - // 0xF8, /* 11111 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0xF8, /* 11111 */ + 0xF8, /* 11111 */ + 0xF8, /* 11111 */ + 0xF8, /* 11111 */ + 0xF8, /* 11111 */ + 0xF8, /* 11111 */ // /* // * code=221, hex=0xDD, ascii="!]" // */ - // 0xE0, /* 11100 */ - // 0xE0, /* 11100 */ - // 0xE0, /* 11100 */ - // 0xE0, /* 11100 */ - // 0xE0, /* 11100 */ - // 0xE0, /* 11100 */ - // 0xE0, /* 11100 */ - // 0xE0, /* 11100 */ - // 0xE0, /* 11100 */ - // 0xE0, /* 11100 */ - // 0xE0, /* 11100 */ - // 0xE0, /* 11100 */ + 0xE0, /* 11100 */ + 0xE0, /* 11100 */ + 0xE0, /* 11100 */ + 0xE0, /* 11100 */ + 0xE0, /* 11100 */ + 0xE0, /* 11100 */ + 0xE0, /* 11100 */ + 0xE0, /* 11100 */ + 0xE0, /* 11100 */ + 0xE0, /* 11100 */ + 0xE0, /* 11100 */ + 0xE0, /* 11100 */ // /* // * code=222, hex=0xDE, ascii="!^" // */ - // 0x38, /* 00111 */ - // 0x38, /* 00111 */ - // 0x38, /* 00111 */ - // 0x38, /* 00111 */ - // 0x38, /* 00111 */ - // 0x38, /* 00111 */ - // 0x38, /* 00111 */ - // 0x38, /* 00111 */ - // 0x38, /* 00111 */ - // 0x38, /* 00111 */ - // 0x38, /* 00111 */ - // 0x38, /* 00111 */ + 0x38, /* 00111 */ + 0x38, /* 00111 */ + 0x38, /* 00111 */ + 0x38, /* 00111 */ + 0x38, /* 00111 */ + 0x38, /* 00111 */ + 0x38, /* 00111 */ + 0x38, /* 00111 */ + 0x38, /* 00111 */ + 0x38, /* 00111 */ + 0x38, /* 00111 */ + 0x38, /* 00111 */ // /* // * code=223, hex=0xDF, ascii="!_" // */ - // 0xF8, /* 11111 */ - // 0xF8, /* 11111 */ - // 0xF8, /* 11111 */ - // 0xF8, /* 11111 */ - // 0xF8, /* 11111 */ - // 0xF8, /* 11111 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0xF8, /* 11111 */ + 0xF8, /* 11111 */ + 0xF8, /* 11111 */ + 0xF8, /* 11111 */ + 0xF8, /* 11111 */ + 0xF8, /* 11111 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=224, hex=0xE0, ascii="!`" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x48, /* 01001 */ - // 0xB0, /* 10110 */ - // 0xA0, /* 10100 */ - // 0xA0, /* 10100 */ - // 0xB0, /* 10110 */ - // 0x48, /* 01001 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x48, /* 01001 */ + 0xB0, /* 10110 */ + 0xA0, /* 10100 */ + 0xA0, /* 10100 */ + 0xB0, /* 10110 */ + 0x48, /* 01001 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=225, hex=0xE1, ascii="!a" // */ - // 0x00, /* 00000 */ - // 0x60, /* 01100 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0xA0, /* 10100 */ - // 0xE0, /* 11100 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0xE0, /* 11100 */ - // 0x80, /* 10000 */ - // 0x80, /* 10000 */ + 0x00, /* 00000 */ + 0x60, /* 01100 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0xA0, /* 10100 */ + 0xE0, /* 11100 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0xE0, /* 11100 */ + 0x80, /* 10000 */ + 0x80, /* 10000 */ // /* // * code=226, hex=0xE2, ascii="!b" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x78, /* 01111 */ - // 0x48, /* 01001 */ - // 0x40, /* 01000 */ - // 0x40, /* 01000 */ - // 0x40, /* 01000 */ - // 0x40, /* 01000 */ - // 0x40, /* 01000 */ - // 0x40, /* 01000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x78, /* 01111 */ + 0x48, /* 01001 */ + 0x40, /* 01000 */ + 0x40, /* 01000 */ + 0x40, /* 01000 */ + 0x40, /* 01000 */ + 0x40, /* 01000 */ + 0x40, /* 01000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=227, hex=0xE3, ascii="!c" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0xF8, /* 11111 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0xF8, /* 11111 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=228, hex=0xE4, ascii="!d" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0xF8, /* 11111 */ - // 0x48, /* 01001 */ - // 0x20, /* 00100 */ - // 0x10, /* 00010 */ - // 0x20, /* 00100 */ - // 0x48, /* 01001 */ - // 0xF8, /* 11111 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0xF8, /* 11111 */ + 0x48, /* 01001 */ + 0x20, /* 00100 */ + 0x10, /* 00010 */ + 0x20, /* 00100 */ + 0x48, /* 01001 */ + 0xF8, /* 11111 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=229, hex=0xE5, ascii="!e" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0xF8, /* 11111 */ - // 0xA0, /* 10100 */ - // 0xA0, /* 10100 */ - // 0xA0, /* 10100 */ - // 0x40, /* 01000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0xF8, /* 11111 */ + 0xA0, /* 10100 */ + 0xA0, /* 10100 */ + 0xA0, /* 10100 */ + 0x40, /* 01000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=230, hex=0xE6, ascii="!f" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0xE0, /* 11100 */ - // 0x80, /* 10000 */ - // 0x80, /* 10000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0xE0, /* 11100 */ + 0x80, /* 10000 */ + 0x80, /* 10000 */ // /* // * code=231, hex=0xE7, ascii="!g" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x50, /* 01010 */ - // 0xA0, /* 10100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x50, /* 01010 */ + 0xA0, /* 10100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=232, hex=0xE8, ascii="!h" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x70, /* 01110 */ - // 0x20, /* 00100 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x20, /* 00100 */ - // 0x70, /* 01110 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x70, /* 01110 */ + 0x20, /* 00100 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x20, /* 00100 */ + 0x70, /* 01110 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=233, hex=0xE9, ascii="!i" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x20, /* 00100 */ - // 0x50, /* 01010 */ - // 0x88, /* 10001 */ - // 0xF8, /* 11111 */ - // 0x88, /* 10001 */ - // 0x50, /* 01010 */ - // 0x20, /* 00100 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x20, /* 00100 */ + 0x50, /* 01010 */ + 0x88, /* 10001 */ + 0xF8, /* 11111 */ + 0x88, /* 10001 */ + 0x50, /* 01010 */ + 0x20, /* 00100 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=234, hex=0xEA, ascii="!j" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x20, /* 00100 */ - // 0x50, /* 01010 */ - // 0x88, /* 10001 */ - // 0x88, /* 10001 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0xD8, /* 11011 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x20, /* 00100 */ + 0x50, /* 01010 */ + 0x88, /* 10001 */ + 0x88, /* 10001 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0xD8, /* 11011 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=235, hex=0xEB, ascii="!k" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x30, /* 00110 */ - // 0x40, /* 01000 */ - // 0x40, /* 01000 */ - // 0x20, /* 00100 */ - // 0x70, /* 01110 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x60, /* 01100 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x30, /* 00110 */ + 0x40, /* 01000 */ + 0x40, /* 01000 */ + 0x20, /* 00100 */ + 0x70, /* 01110 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x60, /* 01100 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=236, hex=0xEC, ascii="!l" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x50, /* 01010 */ - // 0xA8, /* 10101 */ - // 0xA8, /* 10101 */ - // 0x50, /* 01010 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x50, /* 01010 */ + 0xA8, /* 10101 */ + 0xA8, /* 10101 */ + 0x50, /* 01010 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=237, hex=0xED, ascii="!m" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x70, /* 01110 */ - // 0xA8, /* 10101 */ - // 0xA8, /* 10101 */ - // 0x70, /* 01110 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x70, /* 01110 */ + 0xA8, /* 10101 */ + 0xA8, /* 10101 */ + 0x70, /* 01110 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=238, hex=0xEE, ascii="!n" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x70, /* 01110 */ - // 0x80, /* 10000 */ - // 0x80, /* 10000 */ - // 0xE0, /* 11100 */ - // 0x80, /* 10000 */ - // 0x80, /* 10000 */ - // 0x70, /* 01110 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x70, /* 01110 */ + 0x80, /* 10000 */ + 0x80, /* 10000 */ + 0xE0, /* 11100 */ + 0x80, /* 10000 */ + 0x80, /* 10000 */ + 0x70, /* 01110 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=239, hex=0xEF, ascii="!o" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x60, /* 01100 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x60, /* 01100 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=240, hex=0xF0, ascii="!p" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0xF0, /* 11110 */ - // 0x00, /* 00000 */ - // 0xF0, /* 11110 */ - // 0x00, /* 00000 */ - // 0xF0, /* 11110 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0xF0, /* 11110 */ + 0x00, /* 00000 */ + 0xF0, /* 11110 */ + 0x00, /* 00000 */ + 0xF0, /* 11110 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=241, hex=0xF1, ascii="!q" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0xF8, /* 11111 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x00, /* 00000 */ - // 0xF8, /* 11111 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0xF8, /* 11111 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x00, /* 00000 */ + 0xF8, /* 11111 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=242, hex=0xF2, ascii="!r" // */ - // 0x00, /* 00000 */ - // 0x80, /* 10000 */ - // 0x40, /* 01000 */ - // 0x20, /* 00100 */ - // 0x10, /* 00010 */ - // 0x20, /* 00100 */ - // 0x40, /* 01000 */ - // 0x80, /* 10000 */ - // 0x00, /* 00000 */ - // 0xF0, /* 11110 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x80, /* 10000 */ + 0x40, /* 01000 */ + 0x20, /* 00100 */ + 0x10, /* 00010 */ + 0x20, /* 00100 */ + 0x40, /* 01000 */ + 0x80, /* 10000 */ + 0x00, /* 00000 */ + 0xF0, /* 11110 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=243, hex=0xF3, ascii="!s" // */ - // 0x00, /* 00000 */ - // 0x10, /* 00010 */ - // 0x20, /* 00100 */ - // 0x40, /* 01000 */ - // 0x80, /* 10000 */ - // 0x40, /* 01000 */ - // 0x20, /* 00100 */ - // 0x10, /* 00010 */ - // 0x00, /* 00000 */ - // 0xF0, /* 11110 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x10, /* 00010 */ + 0x20, /* 00100 */ + 0x40, /* 01000 */ + 0x80, /* 10000 */ + 0x40, /* 01000 */ + 0x20, /* 00100 */ + 0x10, /* 00010 */ + 0x00, /* 00000 */ + 0xF0, /* 11110 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=244, hex=0xF4, ascii="!t" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x10, /* 00010 */ - // 0x28, /* 00101 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x10, /* 00010 */ + 0x28, /* 00101 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ // /* // * code=245, hex=0xF5, ascii="!u" // */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0xA0, /* 10100 */ - // 0x40, /* 01000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0xA0, /* 10100 */ + 0x40, /* 01000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=246, hex=0xF6, ascii="!v" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x00, /* 00000 */ - // 0xF8, /* 11111 */ - // 0x00, /* 00000 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x00, /* 00000 */ + 0xF8, /* 11111 */ + 0x00, /* 00000 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=247, hex=0xF7, ascii="!w" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x50, /* 01010 */ - // 0xA0, /* 10100 */ - // 0x00, /* 00000 */ - // 0x50, /* 01010 */ - // 0xA0, /* 10100 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x50, /* 01010 */ + 0xA0, /* 10100 */ + 0x00, /* 00000 */ + 0x50, /* 01010 */ + 0xA0, /* 10100 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=248, hex=0xF8, ascii="!x" // */ - // 0x60, /* 01100 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x60, /* 01100 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x60, /* 01100 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x60, /* 01100 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=249, hex=0xF9, ascii="!y" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x20, /* 00100 */ - // 0x70, /* 01110 */ - // 0x20, /* 00100 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x20, /* 00100 */ + 0x70, /* 01110 */ + 0x20, /* 00100 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=250, hex=0xFA, ascii="!z" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=251, hex=0xFB, ascii="!{" // */ - // 0x00, /* 00000 */ - // 0x38, /* 00111 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0xA0, /* 10100 */ - // 0xA0, /* 10100 */ - // 0x60, /* 01100 */ - // 0x20, /* 00100 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x38, /* 00111 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0xA0, /* 10100 */ + 0xA0, /* 10100 */ + 0x60, /* 01100 */ + 0x20, /* 00100 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=252, hex=0xFC, ascii="!|" // */ - // 0xA0, /* 10100 */ - // 0xD0, /* 11010 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0xA0, /* 10100 */ + 0xD0, /* 11010 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=253, hex=0xFD, ascii="!}" // */ - // 0x60, /* 01100 */ - // 0x90, /* 10010 */ - // 0x10, /* 00010 */ - // 0x60, /* 01100 */ - // 0x80, /* 10000 */ - // 0xF0, /* 11110 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x60, /* 01100 */ + 0x90, /* 10010 */ + 0x10, /* 00010 */ + 0x60, /* 01100 */ + 0x80, /* 10000 */ + 0xF0, /* 11110 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=254, hex=0xFE, ascii="!~" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x70, /* 01110 */ - // 0x70, /* 01110 */ - // 0x70, /* 01110 */ - // 0x70, /* 01110 */ - // 0x70, /* 01110 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x70, /* 01110 */ + 0x70, /* 01110 */ + 0x70, /* 01110 */ + 0x70, /* 01110 */ + 0x70, /* 01110 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ +#endif + +#if 0 // skip 255 = NBSP // /* // * code=255, hex=0xFF, ascii="!^Ÿ" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ +#endif }; diff --git a/wled00/src/font/console_font_5x8.h b/wled00/src/font/console_font_5x8.h index c56f2ce0..feb649e8 100644 --- a/wled00/src/font/console_font_5x8.h +++ b/wled00/src/font/console_font_5x8.h @@ -1,393 +1,404 @@ +#if !defined(WLED_ENABLE_FULL_FONTS) +constexpr uint16_t console_font_5x8_first = 32; // index 0 = code 32 "" +constexpr uint16_t console_font_5x8_last = 126; // last index = code 126 "~" +#else +constexpr uint16_t console_font_5x8_first = 1; // index 0 = code 1 "☺︎" +constexpr uint16_t console_font_5x8_last = 254; // last index = code 254 "■" +#endif + // font courtesy of https://github.com/idispatch/raster-fonts static const unsigned char console_font_5x8[] PROGMEM = { // code points 0-31 and 127-255 are commented out to save memory, they contain extra characters (CP437), // which could be used with an UTF-8 to CP437 conversion +#if 0 // skip 0 // /* // * code=0, hex=0x00, ascii="^@" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ +#endif +#if defined(WLED_ENABLE_FULL_FONTS) // /* // * code=1, hex=0x01, ascii="^A" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x70, /* 01110 */ - // 0xA8, /* 10101 */ - // 0xF8, /* 11111 */ - // 0xD8, /* 11011 */ - // 0x70, /* 01110 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x70, /* 01110 */ + 0xA8, /* 10101 */ + 0xF8, /* 11111 */ + 0xD8, /* 11011 */ + 0x70, /* 01110 */ + 0x00, /* 00000 */ // /* // * code=2, hex=0x02, ascii="^B" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x70, /* 01110 */ - // 0xA8, /* 10101 */ - // 0xF8, /* 11111 */ - // 0xF8, /* 11111 */ - // 0x70, /* 01110 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x70, /* 01110 */ + 0xA8, /* 10101 */ + 0xF8, /* 11111 */ + 0xF8, /* 11111 */ + 0x70, /* 01110 */ + 0x00, /* 00000 */ // /* // * code=3, hex=0x03, ascii="^C" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x50, /* 01010 */ - // 0xF8, /* 11111 */ - // 0xF8, /* 11111 */ - // 0x70, /* 01110 */ - // 0x20, /* 00100 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x50, /* 01010 */ + 0xF8, /* 11111 */ + 0xF8, /* 11111 */ + 0x70, /* 01110 */ + 0x20, /* 00100 */ + 0x00, /* 00000 */ // /* // * code=4, hex=0x04, ascii="^D" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x20, /* 00100 */ - // 0x70, /* 01110 */ - // 0xF8, /* 11111 */ - // 0x70, /* 01110 */ - // 0x20, /* 00100 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x20, /* 00100 */ + 0x70, /* 01110 */ + 0xF8, /* 11111 */ + 0x70, /* 01110 */ + 0x20, /* 00100 */ + 0x00, /* 00000 */ // /* // * code=5, hex=0x05, ascii="^E" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x70, /* 01110 */ - // 0xA8, /* 10101 */ - // 0xF8, /* 11111 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x70, /* 01110 */ + 0xA8, /* 10101 */ + 0xF8, /* 11111 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x00, /* 00000 */ // /* // * code=6, hex=0x06, ascii="^F" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x20, /* 00100 */ - // 0x70, /* 01110 */ - // 0xF8, /* 11111 */ - // 0xA8, /* 10101 */ - // 0x20, /* 00100 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x20, /* 00100 */ + 0x70, /* 01110 */ + 0xF8, /* 11111 */ + 0xA8, /* 10101 */ + 0x20, /* 00100 */ + 0x00, /* 00000 */ // /* // * code=7, hex=0x07, ascii="^G" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x20, /* 00100 */ - // 0x70, /* 01110 */ - // 0x20, /* 00100 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x20, /* 00100 */ + 0x70, /* 01110 */ + 0x20, /* 00100 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=8, hex=0x08, ascii="^H" // */ - // 0x00, /* 00000 */ - // 0xF8, /* 11111 */ - // 0xF8, /* 11111 */ - // 0xD8, /* 11011 */ - // 0x88, /* 10001 */ - // 0xD8, /* 11011 */ - // 0xF8, /* 11111 */ - // 0xF8, /* 11111 */ + 0x00, /* 00000 */ + 0xF8, /* 11111 */ + 0xF8, /* 11111 */ + 0xD8, /* 11011 */ + 0x88, /* 10001 */ + 0xD8, /* 11011 */ + 0xF8, /* 11111 */ + 0xF8, /* 11111 */ // /* // * code=9, hex=0x09, ascii="^I" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x20, /* 00100 */ - // 0x50, /* 01010 */ - // 0x20, /* 00100 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x20, /* 00100 */ + 0x50, /* 01010 */ + 0x20, /* 00100 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=10, hex=0x0A, ascii="^J" // */ - // 0x00, /* 00000 */ - // 0xF8, /* 11111 */ - // 0xF8, /* 11111 */ - // 0xD8, /* 11011 */ - // 0x88, /* 10001 */ - // 0xD8, /* 11011 */ - // 0xF8, /* 11111 */ - // 0xF8, /* 11111 */ + 0x00, /* 00000 */ + 0xF8, /* 11111 */ + 0xF8, /* 11111 */ + 0xD8, /* 11011 */ + 0x88, /* 10001 */ + 0xD8, /* 11011 */ + 0xF8, /* 11111 */ + 0xF8, /* 11111 */ // /* // * code=11, hex=0x0B, ascii="^K" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x38, /* 00111 */ - // 0x18, /* 00011 */ - // 0x68, /* 01101 */ - // 0xA0, /* 10100 */ - // 0x40, /* 01000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x38, /* 00111 */ + 0x18, /* 00011 */ + 0x68, /* 01101 */ + 0xA0, /* 10100 */ + 0x40, /* 01000 */ + 0x00, /* 00000 */ // /* // * code=12, hex=0x0C, ascii="^L" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x20, /* 00100 */ - // 0x50, /* 01010 */ - // 0x20, /* 00100 */ - // 0x70, /* 01110 */ - // 0x20, /* 00100 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x20, /* 00100 */ + 0x50, /* 01010 */ + 0x20, /* 00100 */ + 0x70, /* 01110 */ + 0x20, /* 00100 */ + 0x00, /* 00000 */ // /* // * code=13, hex=0x0D, ascii="^M" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x20, /* 00100 */ - // 0x50, /* 01010 */ - // 0x40, /* 01000 */ - // 0xC0, /* 11000 */ - // 0x80, /* 10000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x20, /* 00100 */ + 0x50, /* 01010 */ + 0x40, /* 01000 */ + 0xC0, /* 11000 */ + 0x80, /* 10000 */ + 0x00, /* 00000 */ // /* // * code=14, hex=0x0E, ascii="^N" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x38, /* 00111 */ - // 0x48, /* 01001 */ - // 0x58, /* 01011 */ - // 0xD0, /* 11010 */ - // 0x80, /* 10000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x38, /* 00111 */ + 0x48, /* 01001 */ + 0x58, /* 01011 */ + 0xD0, /* 11010 */ + 0x80, /* 10000 */ + 0x00, /* 00000 */ // /* // * code=15, hex=0x0F, ascii="^O" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x20, /* 00100 */ - // 0x50, /* 01010 */ - // 0x20, /* 00100 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x20, /* 00100 */ + 0x50, /* 01010 */ + 0x20, /* 00100 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=16, hex=0x10, ascii="^P" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x40, /* 01000 */ - // 0x60, /* 01100 */ - // 0x70, /* 01110 */ - // 0x60, /* 01100 */ - // 0x40, /* 01000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x40, /* 01000 */ + 0x60, /* 01100 */ + 0x70, /* 01110 */ + 0x60, /* 01100 */ + 0x40, /* 01000 */ + 0x00, /* 00000 */ // /* // * code=17, hex=0x11, ascii="^Q" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x10, /* 00010 */ - // 0x30, /* 00110 */ - // 0x70, /* 01110 */ - // 0x30, /* 00110 */ - // 0x10, /* 00010 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x10, /* 00010 */ + 0x30, /* 00110 */ + 0x70, /* 01110 */ + 0x30, /* 00110 */ + 0x10, /* 00010 */ + 0x00, /* 00000 */ // /* // * code=18, hex=0x12, ascii="^R" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x20, /* 00100 */ - // 0x70, /* 01110 */ - // 0x20, /* 00100 */ - // 0x70, /* 01110 */ - // 0x20, /* 00100 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x20, /* 00100 */ + 0x70, /* 01110 */ + 0x20, /* 00100 */ + 0x70, /* 01110 */ + 0x20, /* 00100 */ + 0x00, /* 00000 */ // /* // * code=19, hex=0x13, ascii="^S" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x00, /* 00000 */ - // 0x50, /* 01010 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x00, /* 00000 */ + 0x50, /* 01010 */ + 0x00, /* 00000 */ // /* // * code=20, hex=0x14, ascii="^T" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x78, /* 01111 */ - // 0xD0, /* 11010 */ - // 0xD0, /* 11010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x78, /* 01111 */ + 0xD0, /* 11010 */ + 0xD0, /* 11010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ // /* // * code=21, hex=0x15, ascii="^U" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x18, /* 00011 */ - // 0x60, /* 01100 */ - // 0x90, /* 10010 */ - // 0x48, /* 01001 */ - // 0x30, /* 00110 */ - // 0xC0, /* 11000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x18, /* 00011 */ + 0x60, /* 01100 */ + 0x90, /* 10010 */ + 0x48, /* 01001 */ + 0x30, /* 00110 */ + 0xC0, /* 11000 */ // /* // * code=22, hex=0x16, ascii="^V" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0xF8, /* 11111 */ - // 0xF8, /* 11111 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0xF8, /* 11111 */ + 0xF8, /* 11111 */ + 0x00, /* 00000 */ // /* // * code=23, hex=0x17, ascii="^W" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x20, /* 00100 */ - // 0x70, /* 01110 */ - // 0x20, /* 00100 */ - // 0x70, /* 01110 */ - // 0x20, /* 00100 */ - // 0x70, /* 01110 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x20, /* 00100 */ + 0x70, /* 01110 */ + 0x20, /* 00100 */ + 0x70, /* 01110 */ + 0x20, /* 00100 */ + 0x70, /* 01110 */ // /* // * code=24, hex=0x18, ascii="^X" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x20, /* 00100 */ - // 0x70, /* 01110 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x20, /* 00100 */ + 0x70, /* 01110 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x00, /* 00000 */ // /* // * code=25, hex=0x19, ascii="^Y" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x70, /* 01110 */ - // 0x20, /* 00100 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x70, /* 01110 */ + 0x20, /* 00100 */ + 0x00, /* 00000 */ // /* // * code=26, hex=0x1A, ascii="^Z" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x10, /* 00010 */ - // 0xF8, /* 11111 */ - // 0x10, /* 00010 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x10, /* 00010 */ + 0xF8, /* 11111 */ + 0x10, /* 00010 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=27, hex=0x1B, ascii="^[" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x40, /* 01000 */ - // 0xF8, /* 11111 */ - // 0x40, /* 01000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x40, /* 01000 */ + 0xF8, /* 11111 */ + 0x40, /* 01000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=28, hex=0x1C, ascii="^\" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x80, /* 10000 */ - // 0xF8, /* 11111 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x80, /* 10000 */ + 0xF8, /* 11111 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=29, hex=0x1D, ascii="^]" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x50, /* 01010 */ - // 0xF8, /* 11111 */ - // 0x50, /* 01010 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x50, /* 01010 */ + 0xF8, /* 11111 */ + 0x50, /* 01010 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=30, hex=0x1E, ascii="^^" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x20, /* 00100 */ - // 0x70, /* 01110 */ - // 0xF8, /* 11111 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x20, /* 00100 */ + 0x70, /* 01110 */ + 0xF8, /* 11111 */ + 0x00, /* 00000 */ // /* // * code=31, hex=0x1F, ascii="^_" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0xF8, /* 11111 */ - // 0x70, /* 01110 */ - // 0x20, /* 00100 */ - // 0x00, /* 00000 */ - + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0xF8, /* 11111 */ + 0x70, /* 01110 */ + 0x20, /* 00100 */ + 0x00, /* 00000 */ +#endif /* * code=32, hex=0x20, ascii=" " */ @@ -1528,1551 +1539,1557 @@ static const unsigned char console_font_5x8[] PROGMEM = { 0x00, /* 00000 */ 0x00, /* 00000 */ +#if defined(WLED_ENABLE_FULL_FONTS) + // /* // * code=127, hex=0x7F, ascii="^?" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x20, /* 00100 */ - // 0x50, /* 01010 */ - // 0x88, /* 10001 */ - // 0xF8, /* 11111 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x20, /* 00100 */ + 0x50, /* 01010 */ + 0x88, /* 10001 */ + 0xF8, /* 11111 */ + 0x00, /* 00000 */ // /* // * code=128, hex=0x80, ascii="!^@" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x70, /* 01110 */ - // 0x80, /* 10000 */ - // 0x80, /* 10000 */ - // 0x80, /* 10000 */ - // 0x70, /* 01110 */ - // 0x20, /* 00100 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x70, /* 01110 */ + 0x80, /* 10000 */ + 0x80, /* 10000 */ + 0x80, /* 10000 */ + 0x70, /* 01110 */ + 0x20, /* 00100 */ // /* // * code=129, hex=0x81, ascii="!^A" // */ - // 0x00, /* 00000 */ - // 0x50, /* 01010 */ - // 0x00, /* 00000 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x70, /* 01110 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x50, /* 01010 */ + 0x00, /* 00000 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x70, /* 01110 */ + 0x00, /* 00000 */ // /* // * code=130, hex=0x82, ascii="!^B" // */ - // 0x10, /* 00010 */ - // 0x20, /* 00100 */ - // 0x00, /* 00000 */ - // 0x60, /* 01100 */ - // 0xF0, /* 11110 */ - // 0x80, /* 10000 */ - // 0x70, /* 01110 */ - // 0x00, /* 00000 */ + 0x10, /* 00010 */ + 0x20, /* 00100 */ + 0x00, /* 00000 */ + 0x60, /* 01100 */ + 0xF0, /* 11110 */ + 0x80, /* 10000 */ + 0x70, /* 01110 */ + 0x00, /* 00000 */ // /* // * code=131, hex=0x83, ascii="!^C" // */ - // 0x20, /* 00100 */ - // 0x50, /* 01010 */ - // 0x00, /* 00000 */ - // 0xC0, /* 11000 */ - // 0x20, /* 00100 */ - // 0xA0, /* 10100 */ - // 0x50, /* 01010 */ - // 0x00, /* 00000 */ + 0x20, /* 00100 */ + 0x50, /* 01010 */ + 0x00, /* 00000 */ + 0xC0, /* 11000 */ + 0x20, /* 00100 */ + 0xA0, /* 10100 */ + 0x50, /* 01010 */ + 0x00, /* 00000 */ // /* // * code=132, hex=0x84, ascii="!^D" // */ - // 0x00, /* 00000 */ - // 0x50, /* 01010 */ - // 0x00, /* 00000 */ - // 0xC0, /* 11000 */ - // 0x20, /* 00100 */ - // 0x60, /* 01100 */ - // 0xB0, /* 10110 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x50, /* 01010 */ + 0x00, /* 00000 */ + 0xC0, /* 11000 */ + 0x20, /* 00100 */ + 0x60, /* 01100 */ + 0xB0, /* 10110 */ + 0x00, /* 00000 */ // /* // * code=133, hex=0x85, ascii="!^E" // */ - // 0x40, /* 01000 */ - // 0x20, /* 00100 */ - // 0x00, /* 00000 */ - // 0xC0, /* 11000 */ - // 0x20, /* 00100 */ - // 0x60, /* 01100 */ - // 0xB0, /* 10110 */ - // 0x00, /* 00000 */ + 0x40, /* 01000 */ + 0x20, /* 00100 */ + 0x00, /* 00000 */ + 0xC0, /* 11000 */ + 0x20, /* 00100 */ + 0x60, /* 01100 */ + 0xB0, /* 10110 */ + 0x00, /* 00000 */ // /* // * code=134, hex=0x86, ascii="!^F" // */ - // 0x00, /* 00000 */ - // 0x20, /* 00100 */ - // 0x00, /* 00000 */ - // 0xC0, /* 11000 */ - // 0x20, /* 00100 */ - // 0x60, /* 01100 */ - // 0xB0, /* 10110 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x20, /* 00100 */ + 0x00, /* 00000 */ + 0xC0, /* 11000 */ + 0x20, /* 00100 */ + 0x60, /* 01100 */ + 0xB0, /* 10110 */ + 0x00, /* 00000 */ // /* // * code=135, hex=0x87, ascii="!^G" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x30, /* 00110 */ - // 0x40, /* 01000 */ - // 0x40, /* 01000 */ - // 0x30, /* 00110 */ - // 0x20, /* 00100 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x30, /* 00110 */ + 0x40, /* 01000 */ + 0x40, /* 01000 */ + 0x30, /* 00110 */ + 0x20, /* 00100 */ // /* // * code=136, hex=0x88, ascii="!^H" // */ - // 0x20, /* 00100 */ - // 0x50, /* 01010 */ - // 0x00, /* 00000 */ - // 0x60, /* 01100 */ - // 0xF0, /* 11110 */ - // 0x80, /* 10000 */ - // 0x70, /* 01110 */ - // 0x00, /* 00000 */ + 0x20, /* 00100 */ + 0x50, /* 01010 */ + 0x00, /* 00000 */ + 0x60, /* 01100 */ + 0xF0, /* 11110 */ + 0x80, /* 10000 */ + 0x70, /* 01110 */ + 0x00, /* 00000 */ // /* // * code=137, hex=0x89, ascii="!^I" // */ - // 0x00, /* 00000 */ - // 0x50, /* 01010 */ - // 0x00, /* 00000 */ - // 0x60, /* 01100 */ - // 0xF0, /* 11110 */ - // 0x80, /* 10000 */ - // 0x70, /* 01110 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x50, /* 01010 */ + 0x00, /* 00000 */ + 0x60, /* 01100 */ + 0xF0, /* 11110 */ + 0x80, /* 10000 */ + 0x70, /* 01110 */ + 0x00, /* 00000 */ // /* // * code=138, hex=0x8A, ascii="!^J" // */ - // 0x40, /* 01000 */ - // 0x20, /* 00100 */ - // 0x00, /* 00000 */ - // 0x60, /* 01100 */ - // 0xF0, /* 11110 */ - // 0x80, /* 10000 */ - // 0x70, /* 01110 */ - // 0x00, /* 00000 */ + 0x40, /* 01000 */ + 0x20, /* 00100 */ + 0x00, /* 00000 */ + 0x60, /* 01100 */ + 0xF0, /* 11110 */ + 0x80, /* 10000 */ + 0x70, /* 01110 */ + 0x00, /* 00000 */ // /* // * code=139, hex=0x8B, ascii="!^K" // */ - // 0x00, /* 00000 */ - // 0x50, /* 01010 */ - // 0x00, /* 00000 */ - // 0x60, /* 01100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x70, /* 01110 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x50, /* 01010 */ + 0x00, /* 00000 */ + 0x60, /* 01100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x70, /* 01110 */ + 0x00, /* 00000 */ // /* // * code=140, hex=0x8C, ascii="!^L" // */ - // 0x20, /* 00100 */ - // 0x50, /* 01010 */ - // 0x00, /* 00000 */ - // 0x60, /* 01100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x70, /* 01110 */ - // 0x00, /* 00000 */ + 0x20, /* 00100 */ + 0x50, /* 01010 */ + 0x00, /* 00000 */ + 0x60, /* 01100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x70, /* 01110 */ + 0x00, /* 00000 */ // /* // * code=141, hex=0x8D, ascii="!^M" // */ - // 0x40, /* 01000 */ - // 0x20, /* 00100 */ - // 0x00, /* 00000 */ - // 0x60, /* 01100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x70, /* 01110 */ - // 0x00, /* 00000 */ + 0x40, /* 01000 */ + 0x20, /* 00100 */ + 0x00, /* 00000 */ + 0x60, /* 01100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x70, /* 01110 */ + 0x00, /* 00000 */ // /* // * code=142, hex=0x8E, ascii="!^N" // */ - // 0xA0, /* 10100 */ - // 0x00, /* 00000 */ - // 0x60, /* 01100 */ - // 0x90, /* 10010 */ - // 0xF0, /* 11110 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x00, /* 00000 */ + 0xA0, /* 10100 */ + 0x00, /* 00000 */ + 0x60, /* 01100 */ + 0x90, /* 10010 */ + 0xF0, /* 11110 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x00, /* 00000 */ // /* // * code=143, hex=0x8F, ascii="!^O" // */ - // 0x20, /* 00100 */ - // 0x00, /* 00000 */ - // 0x60, /* 01100 */ - // 0x90, /* 10010 */ - // 0xF0, /* 11110 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x00, /* 00000 */ + 0x20, /* 00100 */ + 0x00, /* 00000 */ + 0x60, /* 01100 */ + 0x90, /* 10010 */ + 0xF0, /* 11110 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x00, /* 00000 */ // /* // * code=144, hex=0x90, ascii="!^P" // */ - // 0x10, /* 00010 */ - // 0x20, /* 00100 */ - // 0xF0, /* 11110 */ - // 0x80, /* 10000 */ - // 0xE0, /* 11100 */ - // 0x80, /* 10000 */ - // 0xF0, /* 11110 */ - // 0x00, /* 00000 */ + 0x10, /* 00010 */ + 0x20, /* 00100 */ + 0xF0, /* 11110 */ + 0x80, /* 10000 */ + 0xE0, /* 11100 */ + 0x80, /* 10000 */ + 0xF0, /* 11110 */ + 0x00, /* 00000 */ // /* // * code=145, hex=0x91, ascii="!^Q" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0xD8, /* 11011 */ - // 0x78, /* 01111 */ - // 0xE0, /* 11100 */ - // 0xB8, /* 10111 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0xD8, /* 11011 */ + 0x78, /* 01111 */ + 0xE0, /* 11100 */ + 0xB8, /* 10111 */ + 0x00, /* 00000 */ // /* // * code=146, hex=0x92, ascii="!^R" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x70, /* 01110 */ - // 0xA0, /* 10100 */ - // 0xF0, /* 11110 */ - // 0xA0, /* 10100 */ - // 0xB0, /* 10110 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x70, /* 01110 */ + 0xA0, /* 10100 */ + 0xF0, /* 11110 */ + 0xA0, /* 10100 */ + 0xB0, /* 10110 */ + 0x00, /* 00000 */ // /* // * code=147, hex=0x93, ascii="!^S" // */ - // 0x20, /* 00100 */ - // 0x50, /* 01010 */ - // 0x00, /* 00000 */ - // 0x60, /* 01100 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x60, /* 01100 */ - // 0x00, /* 00000 */ + 0x20, /* 00100 */ + 0x50, /* 01010 */ + 0x00, /* 00000 */ + 0x60, /* 01100 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x60, /* 01100 */ + 0x00, /* 00000 */ // /* // * code=148, hex=0x94, ascii="!^T" // */ - // 0x00, /* 00000 */ - // 0x50, /* 01010 */ - // 0x00, /* 00000 */ - // 0x60, /* 01100 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x60, /* 01100 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x50, /* 01010 */ + 0x00, /* 00000 */ + 0x60, /* 01100 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x60, /* 01100 */ + 0x00, /* 00000 */ // /* // * code=149, hex=0x95, ascii="!^U" // */ - // 0x40, /* 01000 */ - // 0x20, /* 00100 */ - // 0x00, /* 00000 */ - // 0x60, /* 01100 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x60, /* 01100 */ - // 0x00, /* 00000 */ + 0x40, /* 01000 */ + 0x20, /* 00100 */ + 0x00, /* 00000 */ + 0x60, /* 01100 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x60, /* 01100 */ + 0x00, /* 00000 */ // /* // * code=150, hex=0x96, ascii="!^V" // */ - // 0x20, /* 00100 */ - // 0x50, /* 01010 */ - // 0x00, /* 00000 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x70, /* 01110 */ - // 0x00, /* 00000 */ + 0x20, /* 00100 */ + 0x50, /* 01010 */ + 0x00, /* 00000 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x70, /* 01110 */ + 0x00, /* 00000 */ // /* // * code=151, hex=0x97, ascii="!^W" // */ - // 0x40, /* 01000 */ - // 0x20, /* 00100 */ - // 0x00, /* 00000 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x70, /* 01110 */ - // 0x00, /* 00000 */ + 0x40, /* 01000 */ + 0x20, /* 00100 */ + 0x00, /* 00000 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x70, /* 01110 */ + 0x00, /* 00000 */ // /* // * code=152, hex=0x98, ascii="!^X" // */ - // 0x00, /* 00000 */ - // 0x50, /* 01010 */ - // 0x00, /* 00000 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x70, /* 01110 */ - // 0x10, /* 00010 */ - // 0x60, /* 01100 */ + 0x00, /* 00000 */ + 0x50, /* 01010 */ + 0x00, /* 00000 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x70, /* 01110 */ + 0x10, /* 00010 */ + 0x60, /* 01100 */ // /* // * code=153, hex=0x99, ascii="!^Y" // */ - // 0x00, /* 00000 */ - // 0x50, /* 01010 */ - // 0x00, /* 00000 */ - // 0x60, /* 01100 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x60, /* 01100 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x50, /* 01010 */ + 0x00, /* 00000 */ + 0x60, /* 01100 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x60, /* 01100 */ + 0x00, /* 00000 */ // /* // * code=154, hex=0x9A, ascii="!^Z" // */ - // 0x50, /* 01010 */ - // 0x00, /* 00000 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x60, /* 01100 */ - // 0x00, /* 00000 */ + 0x50, /* 01010 */ + 0x00, /* 00000 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x60, /* 01100 */ + 0x00, /* 00000 */ // /* // * code=155, hex=0x9B, ascii="!^[" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x20, /* 00100 */ - // 0x70, /* 01110 */ - // 0x80, /* 10000 */ - // 0x80, /* 10000 */ - // 0x70, /* 01110 */ - // 0x20, /* 00100 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x20, /* 00100 */ + 0x70, /* 01110 */ + 0x80, /* 10000 */ + 0x80, /* 10000 */ + 0x70, /* 01110 */ + 0x20, /* 00100 */ // /* // * code=156, hex=0x9C, ascii="!^\" // */ - // 0x00, /* 00000 */ - // 0x30, /* 00110 */ - // 0x50, /* 01010 */ - // 0x40, /* 01000 */ - // 0xE0, /* 11100 */ - // 0x40, /* 01000 */ - // 0xF0, /* 11110 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x30, /* 00110 */ + 0x50, /* 01010 */ + 0x40, /* 01000 */ + 0xE0, /* 11100 */ + 0x40, /* 01000 */ + 0xF0, /* 11110 */ + 0x00, /* 00000 */ // /* // * code=157, hex=0x9D, ascii="!^]" // */ - // 0x00, /* 00000 */ - // 0xD8, /* 11011 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x20, /* 00100 */ - // 0x70, /* 01110 */ - // 0x20, /* 00100 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0xD8, /* 11011 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x20, /* 00100 */ + 0x70, /* 01110 */ + 0x20, /* 00100 */ + 0x00, /* 00000 */ // /* // * code=158, hex=0x9E, ascii="!^^" // */ - // 0x00, /* 00000 */ - // 0xC0, /* 11000 */ - // 0xA0, /* 10100 */ - // 0xB0, /* 10110 */ - // 0xF8, /* 11111 */ - // 0x90, /* 10010 */ - // 0x88, /* 10001 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0xC0, /* 11000 */ + 0xA0, /* 10100 */ + 0xB0, /* 10110 */ + 0xF8, /* 11111 */ + 0x90, /* 10010 */ + 0x88, /* 10001 */ + 0x00, /* 00000 */ // /* // * code=159, hex=0x9F, ascii="!^_" // */ - // 0x00, /* 00000 */ - // 0x30, /* 00110 */ - // 0x40, /* 01000 */ - // 0x40, /* 01000 */ - // 0xF0, /* 11110 */ - // 0x40, /* 01000 */ - // 0x40, /* 01000 */ - // 0x80, /* 10000 */ + 0x00, /* 00000 */ + 0x30, /* 00110 */ + 0x40, /* 01000 */ + 0x40, /* 01000 */ + 0xF0, /* 11110 */ + 0x40, /* 01000 */ + 0x40, /* 01000 */ + 0x80, /* 10000 */ // /* // * code=160, hex=0xA0, ascii="! " // */ - // 0x20, /* 00100 */ - // 0x40, /* 01000 */ - // 0x00, /* 00000 */ - // 0xC0, /* 11000 */ - // 0x20, /* 00100 */ - // 0x60, /* 01100 */ - // 0xB0, /* 10110 */ - // 0x00, /* 00000 */ + 0x20, /* 00100 */ + 0x40, /* 01000 */ + 0x00, /* 00000 */ + 0xC0, /* 11000 */ + 0x20, /* 00100 */ + 0x60, /* 01100 */ + 0xB0, /* 10110 */ + 0x00, /* 00000 */ // /* // * code=161, hex=0xA1, ascii="!!" // */ - // 0x10, /* 00010 */ - // 0x20, /* 00100 */ - // 0x00, /* 00000 */ - // 0x60, /* 01100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x70, /* 01110 */ - // 0x00, /* 00000 */ + 0x10, /* 00010 */ + 0x20, /* 00100 */ + 0x00, /* 00000 */ + 0x60, /* 01100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x70, /* 01110 */ + 0x00, /* 00000 */ // /* // * code=162, hex=0xA2, ascii="!"" // */ - // 0x10, /* 00010 */ - // 0x20, /* 00100 */ - // 0x00, /* 00000 */ - // 0x60, /* 01100 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x60, /* 01100 */ - // 0x00, /* 00000 */ + 0x10, /* 00010 */ + 0x20, /* 00100 */ + 0x00, /* 00000 */ + 0x60, /* 01100 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x60, /* 01100 */ + 0x00, /* 00000 */ // /* // * code=163, hex=0xA3, ascii="!#" // */ - // 0x10, /* 00010 */ - // 0x20, /* 00100 */ - // 0x00, /* 00000 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x70, /* 01110 */ - // 0x00, /* 00000 */ + 0x10, /* 00010 */ + 0x20, /* 00100 */ + 0x00, /* 00000 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x70, /* 01110 */ + 0x00, /* 00000 */ // /* // * code=164, hex=0xA4, ascii="!$" // */ - // 0x50, /* 01010 */ - // 0xA0, /* 10100 */ - // 0x00, /* 00000 */ - // 0xE0, /* 11100 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x00, /* 00000 */ + 0x50, /* 01010 */ + 0xA0, /* 10100 */ + 0x00, /* 00000 */ + 0xE0, /* 11100 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x00, /* 00000 */ // /* // * code=165, hex=0xA5, ascii="!%" // */ - // 0x50, /* 01010 */ - // 0xA0, /* 10100 */ - // 0x90, /* 10010 */ - // 0xD0, /* 11010 */ - // 0xD0, /* 11010 */ - // 0xB0, /* 10110 */ - // 0x90, /* 10010 */ - // 0x00, /* 00000 */ + 0x50, /* 01010 */ + 0xA0, /* 10100 */ + 0x90, /* 10010 */ + 0xD0, /* 11010 */ + 0xD0, /* 11010 */ + 0xB0, /* 10110 */ + 0x90, /* 10010 */ + 0x00, /* 00000 */ // /* // * code=166, hex=0xA6, ascii="!&" // */ - // 0x00, /* 00000 */ - // 0x20, /* 00100 */ - // 0x50, /* 01010 */ - // 0x30, /* 00110 */ - // 0x00, /* 00000 */ - // 0x70, /* 01110 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x20, /* 00100 */ + 0x50, /* 01010 */ + 0x30, /* 00110 */ + 0x00, /* 00000 */ + 0x70, /* 01110 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=167, hex=0xA7, ascii="!'" // */ - // 0x00, /* 00000 */ - // 0x20, /* 00100 */ - // 0x50, /* 01010 */ - // 0x20, /* 00100 */ - // 0x00, /* 00000 */ - // 0x70, /* 01110 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x20, /* 00100 */ + 0x50, /* 01010 */ + 0x20, /* 00100 */ + 0x00, /* 00000 */ + 0x70, /* 01110 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=168, hex=0xA8, ascii="!(" // */ - // 0x00, /* 00000 */ - // 0x20, /* 00100 */ - // 0x00, /* 00000 */ - // 0x20, /* 00100 */ - // 0x40, /* 01000 */ - // 0x90, /* 10010 */ - // 0x60, /* 01100 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x20, /* 00100 */ + 0x00, /* 00000 */ + 0x20, /* 00100 */ + 0x40, /* 01000 */ + 0x90, /* 10010 */ + 0x60, /* 01100 */ + 0x00, /* 00000 */ // /* // * code=169, hex=0xA9, ascii="!)" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0xF8, /* 11111 */ - // 0x80, /* 10000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0xF8, /* 11111 */ + 0x80, /* 10000 */ + 0x00, /* 00000 */ // /* // * code=170, hex=0xAA, ascii="!*" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0xF8, /* 11111 */ - // 0x08, /* 00001 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0xF8, /* 11111 */ + 0x08, /* 00001 */ + 0x00, /* 00000 */ // /* // * code=171, hex=0xAB, ascii="!+" // */ - // 0x00, /* 00000 */ - // 0x80, /* 10000 */ - // 0x90, /* 10010 */ - // 0xA0, /* 10100 */ - // 0x58, /* 01011 */ - // 0x88, /* 10001 */ - // 0x38, /* 00111 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x80, /* 10000 */ + 0x90, /* 10010 */ + 0xA0, /* 10100 */ + 0x58, /* 01011 */ + 0x88, /* 10001 */ + 0x38, /* 00111 */ + 0x00, /* 00000 */ // /* // * code=172, hex=0xAC, ascii="!," // */ - // 0x00, /* 00000 */ - // 0x88, /* 10001 */ - // 0x90, /* 10010 */ - // 0xA0, /* 10100 */ - // 0x48, /* 01001 */ - // 0x98, /* 10011 */ - // 0x38, /* 00111 */ - // 0x08, /* 00001 */ + 0x00, /* 00000 */ + 0x88, /* 10001 */ + 0x90, /* 10010 */ + 0xA0, /* 10100 */ + 0x48, /* 01001 */ + 0x98, /* 10011 */ + 0x38, /* 00111 */ + 0x08, /* 00001 */ // /* // * code=173, hex=0xAD, ascii="!-" // */ - // 0x00, /* 00000 */ - // 0x20, /* 00100 */ - // 0x00, /* 00000 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x70, /* 01110 */ - // 0x20, /* 00100 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x20, /* 00100 */ + 0x00, /* 00000 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x70, /* 01110 */ + 0x20, /* 00100 */ + 0x00, /* 00000 */ // /* // * code=174, hex=0xAE, ascii="!." // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x50, /* 01010 */ - // 0xA0, /* 10100 */ - // 0x50, /* 01010 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x50, /* 01010 */ + 0xA0, /* 10100 */ + 0x50, /* 01010 */ + 0x00, /* 00000 */ // /* // * code=175, hex=0xAF, ascii="!/" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0xA0, /* 10100 */ - // 0x50, /* 01010 */ - // 0xA0, /* 10100 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0xA0, /* 10100 */ + 0x50, /* 01010 */ + 0xA0, /* 10100 */ + 0x00, /* 00000 */ // /* // * code=176, hex=0xB0, ascii="!0" // */ - // 0xA8, /* 10101 */ - // 0x50, /* 01010 */ - // 0xA8, /* 10101 */ - // 0x50, /* 01010 */ - // 0xA8, /* 10101 */ - // 0x50, /* 01010 */ - // 0xA8, /* 10101 */ - // 0x50, /* 01010 */ + 0xA8, /* 10101 */ + 0x50, /* 01010 */ + 0xA8, /* 10101 */ + 0x50, /* 01010 */ + 0xA8, /* 10101 */ + 0x50, /* 01010 */ + 0xA8, /* 10101 */ + 0x50, /* 01010 */ // /* // * code=177, hex=0xB1, ascii="!1" // */ - // 0xE8, /* 11101 */ - // 0x50, /* 01010 */ - // 0xB8, /* 10111 */ - // 0x50, /* 01010 */ - // 0xE8, /* 11101 */ - // 0x50, /* 01010 */ - // 0xB8, /* 10111 */ - // 0x50, /* 01010 */ + 0xE8, /* 11101 */ + 0x50, /* 01010 */ + 0xB8, /* 10111 */ + 0x50, /* 01010 */ + 0xE8, /* 11101 */ + 0x50, /* 01010 */ + 0xB8, /* 10111 */ + 0x50, /* 01010 */ // /* // * code=178, hex=0xB2, ascii="!2" // */ - // 0xD8, /* 11011 */ - // 0x70, /* 01110 */ - // 0xD8, /* 11011 */ - // 0x70, /* 01110 */ - // 0xD8, /* 11011 */ - // 0x70, /* 01110 */ - // 0xD8, /* 11011 */ - // 0x70, /* 01110 */ + 0xD8, /* 11011 */ + 0x70, /* 01110 */ + 0xD8, /* 11011 */ + 0x70, /* 01110 */ + 0xD8, /* 11011 */ + 0x70, /* 01110 */ + 0xD8, /* 11011 */ + 0x70, /* 01110 */ // /* // * code=179, hex=0xB3, ascii="!3" // */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ // /* // * code=180, hex=0xB4, ascii="!4" // */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0xE0, /* 11100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0xE0, /* 11100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ // /* // * code=181, hex=0xB5, ascii="!5" // */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0xE0, /* 11100 */ - // 0x20, /* 00100 */ - // 0xE0, /* 11100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0xE0, /* 11100 */ + 0x20, /* 00100 */ + 0xE0, /* 11100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ // /* // * code=182, hex=0xB6, ascii="!6" // */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0xD0, /* 11010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0xD0, /* 11010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ // /* // * code=183, hex=0xB7, ascii="!7" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0xF0, /* 11110 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0xF0, /* 11110 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ // /* // * code=184, hex=0xB8, ascii="!8" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0xE0, /* 11100 */ - // 0x20, /* 00100 */ - // 0xE0, /* 11100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0xE0, /* 11100 */ + 0x20, /* 00100 */ + 0xE0, /* 11100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ // /* // * code=185, hex=0xB9, ascii="!9" // */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0xD0, /* 11010 */ - // 0x10, /* 00010 */ - // 0xD0, /* 11010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0xD0, /* 11010 */ + 0x10, /* 00010 */ + 0xD0, /* 11010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ // /* // * code=186, hex=0xBA, ascii="!:" // */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ // /* // * code=187, hex=0xBB, ascii="!;" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0xF0, /* 11110 */ - // 0x10, /* 00010 */ - // 0xD0, /* 11010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0xF0, /* 11110 */ + 0x10, /* 00010 */ + 0xD0, /* 11010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ // /* // * code=188, hex=0xBC, ascii="!<" // */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0xD0, /* 11010 */ - // 0x10, /* 00010 */ - // 0xF0, /* 11110 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0xD0, /* 11010 */ + 0x10, /* 00010 */ + 0xF0, /* 11110 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=189, hex=0xBD, ascii="!=" // */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0xF0, /* 11110 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0xF0, /* 11110 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=190, hex=0xBE, ascii="!>" // */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0xE0, /* 11100 */ - // 0x20, /* 00100 */ - // 0xE0, /* 11100 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0xE0, /* 11100 */ + 0x20, /* 00100 */ + 0xE0, /* 11100 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=191, hex=0xBF, ascii="!?" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0xE0, /* 11100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0xE0, /* 11100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ // /* // * code=192, hex=0xC0, ascii="!@" // */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x38, /* 00111 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x38, /* 00111 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=193, hex=0xC1, ascii="!A" // */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0xF8, /* 11111 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0xF8, /* 11111 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=194, hex=0xC2, ascii="!B" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0xF8, /* 11111 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0xF8, /* 11111 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ // /* // * code=195, hex=0xC3, ascii="!C" // */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x38, /* 00111 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x38, /* 00111 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ // /* // * code=196, hex=0xC4, ascii="!D" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0xF8, /* 11111 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0xF8, /* 11111 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=197, hex=0xC5, ascii="!E" // */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0xF8, /* 11111 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0xF8, /* 11111 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ // /* // * code=198, hex=0xC6, ascii="!F" // */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x38, /* 00111 */ - // 0x20, /* 00100 */ - // 0x38, /* 00111 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x38, /* 00111 */ + 0x20, /* 00100 */ + 0x38, /* 00111 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ // /* // * code=199, hex=0xC7, ascii="!G" // */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x58, /* 01011 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x58, /* 01011 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ // /* // * code=200, hex=0xC8, ascii="!H" // */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x58, /* 01011 */ - // 0x40, /* 01000 */ - // 0x78, /* 01111 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x58, /* 01011 */ + 0x40, /* 01000 */ + 0x78, /* 01111 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=201, hex=0xC9, ascii="!I" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x78, /* 01111 */ - // 0x40, /* 01000 */ - // 0x58, /* 01011 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x78, /* 01111 */ + 0x40, /* 01000 */ + 0x58, /* 01011 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ // /* // * code=202, hex=0xCA, ascii="!J" // */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0xD8, /* 11011 */ - // 0x00, /* 00000 */ - // 0xF8, /* 11111 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0xD8, /* 11011 */ + 0x00, /* 00000 */ + 0xF8, /* 11111 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=203, hex=0xCB, ascii="!K" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0xF8, /* 11111 */ - // 0x00, /* 00000 */ - // 0xD8, /* 11011 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0xF8, /* 11111 */ + 0x00, /* 00000 */ + 0xD8, /* 11011 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ // /* // * code=204, hex=0xCC, ascii="!L" // */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x58, /* 01011 */ - // 0x40, /* 01000 */ - // 0x58, /* 01011 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x58, /* 01011 */ + 0x40, /* 01000 */ + 0x58, /* 01011 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ // /* // * code=205, hex=0xCD, ascii="!M" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0xF8, /* 11111 */ - // 0x00, /* 00000 */ - // 0xF8, /* 11111 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0xF8, /* 11111 */ + 0x00, /* 00000 */ + 0xF8, /* 11111 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=206, hex=0xCE, ascii="!N" // */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0xD8, /* 11011 */ - // 0x00, /* 00000 */ - // 0xD8, /* 11011 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0xD8, /* 11011 */ + 0x00, /* 00000 */ + 0xD8, /* 11011 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ // /* // * code=207, hex=0xCF, ascii="!O" // */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0xF8, /* 11111 */ - // 0x00, /* 00000 */ - // 0xF8, /* 11111 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0xF8, /* 11111 */ + 0x00, /* 00000 */ + 0xF8, /* 11111 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=208, hex=0xD0, ascii="!P" // */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0xF8, /* 11111 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0xF8, /* 11111 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=209, hex=0xD1, ascii="!Q" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0xF8, /* 11111 */ - // 0x00, /* 00000 */ - // 0xF8, /* 11111 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0xF8, /* 11111 */ + 0x00, /* 00000 */ + 0xF8, /* 11111 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ // /* // * code=210, hex=0xD2, ascii="!R" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0xF8, /* 11111 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0xF8, /* 11111 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ // /* // * code=211, hex=0xD3, ascii="!S" // */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x78, /* 01111 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x78, /* 01111 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=212, hex=0xD4, ascii="!T" // */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x38, /* 00111 */ - // 0x20, /* 00100 */ - // 0x38, /* 00111 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x38, /* 00111 */ + 0x20, /* 00100 */ + 0x38, /* 00111 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=213, hex=0xD5, ascii="!U" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x38, /* 00111 */ - // 0x20, /* 00100 */ - // 0x38, /* 00111 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x38, /* 00111 */ + 0x20, /* 00100 */ + 0x38, /* 00111 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ // /* // * code=214, hex=0xD6, ascii="!V" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x78, /* 01111 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x78, /* 01111 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ // /* // * code=215, hex=0xD7, ascii="!W" // */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0xF8, /* 11111 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0xF8, /* 11111 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ // /* // * code=216, hex=0xD8, ascii="!X" // */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0xF8, /* 11111 */ - // 0x20, /* 00100 */ - // 0xF8, /* 11111 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0xF8, /* 11111 */ + 0x20, /* 00100 */ + 0xF8, /* 11111 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ // /* // * code=217, hex=0xD9, ascii="!Y" // */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0xE0, /* 11100 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0xE0, /* 11100 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=218, hex=0xDA, ascii="!Z" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x38, /* 00111 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x38, /* 00111 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ // /* // * code=219, hex=0xDB, ascii="![" // */ - // 0xF8, /* 11111 */ - // 0xF8, /* 11111 */ - // 0xF8, /* 11111 */ - // 0xF8, /* 11111 */ - // 0xF8, /* 11111 */ - // 0xF8, /* 11111 */ - // 0xF8, /* 11111 */ - // 0xF8, /* 11111 */ + 0xF8, /* 11111 */ + 0xF8, /* 11111 */ + 0xF8, /* 11111 */ + 0xF8, /* 11111 */ + 0xF8, /* 11111 */ + 0xF8, /* 11111 */ + 0xF8, /* 11111 */ + 0xF8, /* 11111 */ // /* // * code=220, hex=0xDC, ascii="!\" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0xF8, /* 11111 */ - // 0xF8, /* 11111 */ - // 0xF8, /* 11111 */ - // 0xF8, /* 11111 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0xF8, /* 11111 */ + 0xF8, /* 11111 */ + 0xF8, /* 11111 */ + 0xF8, /* 11111 */ // /* // * code=221, hex=0xDD, ascii="!]" // */ - // 0xE0, /* 11100 */ - // 0xE0, /* 11100 */ - // 0xE0, /* 11100 */ - // 0xE0, /* 11100 */ - // 0xE0, /* 11100 */ - // 0xE0, /* 11100 */ - // 0xE0, /* 11100 */ - // 0xE0, /* 11100 */ + 0xE0, /* 11100 */ + 0xE0, /* 11100 */ + 0xE0, /* 11100 */ + 0xE0, /* 11100 */ + 0xE0, /* 11100 */ + 0xE0, /* 11100 */ + 0xE0, /* 11100 */ + 0xE0, /* 11100 */ // /* // * code=222, hex=0xDE, ascii="!^" // */ - // 0x18, /* 00011 */ - // 0x18, /* 00011 */ - // 0x18, /* 00011 */ - // 0x18, /* 00011 */ - // 0x18, /* 00011 */ - // 0x18, /* 00011 */ - // 0x18, /* 00011 */ - // 0x18, /* 00011 */ + 0x18, /* 00011 */ + 0x18, /* 00011 */ + 0x18, /* 00011 */ + 0x18, /* 00011 */ + 0x18, /* 00011 */ + 0x18, /* 00011 */ + 0x18, /* 00011 */ + 0x18, /* 00011 */ // /* // * code=223, hex=0xDF, ascii="!_" // */ - // 0xF8, /* 11111 */ - // 0xF8, /* 11111 */ - // 0xF8, /* 11111 */ - // 0xF8, /* 11111 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0xF8, /* 11111 */ + 0xF8, /* 11111 */ + 0xF8, /* 11111 */ + 0xF8, /* 11111 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=224, hex=0xE0, ascii="!`" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x68, /* 01101 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x68, /* 01101 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x68, /* 01101 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x68, /* 01101 */ + 0x00, /* 00000 */ // /* // * code=225, hex=0xE1, ascii="!a" // */ - // 0x00, /* 00000 */ - // 0x60, /* 01100 */ - // 0x90, /* 10010 */ - // 0xF0, /* 11110 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0xE0, /* 11100 */ - // 0x80, /* 10000 */ + 0x00, /* 00000 */ + 0x60, /* 01100 */ + 0x90, /* 10010 */ + 0xF0, /* 11110 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0xE0, /* 11100 */ + 0x80, /* 10000 */ // /* // * code=226, hex=0xE2, ascii="!b" // */ - // 0x00, /* 00000 */ - // 0x70, /* 01110 */ - // 0x40, /* 01000 */ - // 0x40, /* 01000 */ - // 0x40, /* 01000 */ - // 0x40, /* 01000 */ - // 0x40, /* 01000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x70, /* 01110 */ + 0x40, /* 01000 */ + 0x40, /* 01000 */ + 0x40, /* 01000 */ + 0x40, /* 01000 */ + 0x40, /* 01000 */ + 0x00, /* 00000 */ // /* // * code=227, hex=0xE3, ascii="!c" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x70, /* 01110 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x70, /* 01110 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x00, /* 00000 */ // /* // * code=228, hex=0xE4, ascii="!d" // */ - // 0x00, /* 00000 */ - // 0xF8, /* 11111 */ - // 0x48, /* 01001 */ - // 0x20, /* 00100 */ - // 0x40, /* 01000 */ - // 0x88, /* 10001 */ - // 0xF8, /* 11111 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0xF8, /* 11111 */ + 0x48, /* 01001 */ + 0x20, /* 00100 */ + 0x40, /* 01000 */ + 0x88, /* 10001 */ + 0xF8, /* 11111 */ + 0x00, /* 00000 */ // /* // * code=229, hex=0xE5, ascii="!e" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x78, /* 01111 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x60, /* 01100 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x78, /* 01111 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x60, /* 01100 */ + 0x00, /* 00000 */ // /* // * code=230, hex=0xE6, ascii="!f" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0xE8, /* 11101 */ - // 0x80, /* 10000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0xE8, /* 11101 */ + 0x80, /* 10000 */ // /* // * code=231, hex=0xE7, ascii="!g" // */ - // 0x00, /* 00000 */ - // 0x98, /* 10011 */ - // 0x50, /* 01010 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x98, /* 10011 */ + 0x50, /* 01010 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x00, /* 00000 */ // /* // * code=232, hex=0xE8, ascii="!h" // */ - // 0x00, /* 00000 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x70, /* 01110 */ - // 0x88, /* 10001 */ - // 0x70, /* 01110 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ + 0x00, /* 00000 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x70, /* 01110 */ + 0x88, /* 10001 */ + 0x70, /* 01110 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ // /* // * code=233, hex=0xE9, ascii="!i" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x70, /* 01110 */ - // 0x88, /* 10001 */ - // 0xF8, /* 11111 */ - // 0x88, /* 10001 */ - // 0x70, /* 01110 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x70, /* 01110 */ + 0x88, /* 10001 */ + 0xF8, /* 11111 */ + 0x88, /* 10001 */ + 0x70, /* 01110 */ + 0x00, /* 00000 */ // /* // * code=234, hex=0xEA, ascii="!j" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x70, /* 01110 */ - // 0x88, /* 10001 */ - // 0x88, /* 10001 */ - // 0x50, /* 01010 */ - // 0xD8, /* 11011 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x70, /* 01110 */ + 0x88, /* 10001 */ + 0x88, /* 10001 */ + 0x50, /* 01010 */ + 0xD8, /* 11011 */ + 0x00, /* 00000 */ // /* // * code=235, hex=0xEB, ascii="!k" // */ - // 0x60, /* 01100 */ - // 0x80, /* 10000 */ - // 0x40, /* 01000 */ - // 0x60, /* 01100 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x60, /* 01100 */ - // 0x00, /* 00000 */ + 0x60, /* 01100 */ + 0x80, /* 10000 */ + 0x40, /* 01000 */ + 0x60, /* 01100 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x60, /* 01100 */ + 0x00, /* 00000 */ // /* // * code=236, hex=0xEC, ascii="!l" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x70, /* 01110 */ - // 0xA8, /* 10101 */ - // 0xA8, /* 10101 */ - // 0x70, /* 01110 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x70, /* 01110 */ + 0xA8, /* 10101 */ + 0xA8, /* 10101 */ + 0x70, /* 01110 */ + 0x00, /* 00000 */ // /* // * code=237, hex=0xED, ascii="!m" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x08, /* 00001 */ - // 0x70, /* 01110 */ - // 0xA8, /* 10101 */ - // 0x48, /* 01001 */ - // 0xB0, /* 10110 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x08, /* 00001 */ + 0x70, /* 01110 */ + 0xA8, /* 10101 */ + 0x48, /* 01001 */ + 0xB0, /* 10110 */ + 0x00, /* 00000 */ // /* // * code=238, hex=0xEE, ascii="!n" // */ - // 0x00, /* 00000 */ - // 0x30, /* 00110 */ - // 0x40, /* 01000 */ - // 0x70, /* 01110 */ - // 0x40, /* 01000 */ - // 0x40, /* 01000 */ - // 0x30, /* 00110 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x30, /* 00110 */ + 0x40, /* 01000 */ + 0x70, /* 01110 */ + 0x40, /* 01000 */ + 0x40, /* 01000 */ + 0x30, /* 00110 */ + 0x00, /* 00000 */ // /* // * code=239, hex=0xEF, ascii="!o" // */ - // 0x00, /* 00000 */ - // 0x60, /* 01100 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x90, /* 10010 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x60, /* 01100 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x90, /* 10010 */ + 0x00, /* 00000 */ // /* // * code=240, hex=0xF0, ascii="!p" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0xF0, /* 11110 */ - // 0x00, /* 00000 */ - // 0xF0, /* 11110 */ - // 0x00, /* 00000 */ - // 0xF0, /* 11110 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0xF0, /* 11110 */ + 0x00, /* 00000 */ + 0xF0, /* 11110 */ + 0x00, /* 00000 */ + 0xF0, /* 11110 */ + 0x00, /* 00000 */ // /* // * code=241, hex=0xF1, ascii="!q" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x20, /* 00100 */ - // 0xF8, /* 11111 */ - // 0x20, /* 00100 */ - // 0x00, /* 00000 */ - // 0xF8, /* 11111 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x20, /* 00100 */ + 0xF8, /* 11111 */ + 0x20, /* 00100 */ + 0x00, /* 00000 */ + 0xF8, /* 11111 */ + 0x00, /* 00000 */ // /* // * code=242, hex=0xF2, ascii="!r" // */ - // 0x00, /* 00000 */ - // 0x40, /* 01000 */ - // 0x20, /* 00100 */ - // 0x10, /* 00010 */ - // 0x20, /* 00100 */ - // 0x40, /* 01000 */ - // 0xF0, /* 11110 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x40, /* 01000 */ + 0x20, /* 00100 */ + 0x10, /* 00010 */ + 0x20, /* 00100 */ + 0x40, /* 01000 */ + 0xF0, /* 11110 */ + 0x00, /* 00000 */ // /* // * code=243, hex=0xF3, ascii="!s" // */ - // 0x00, /* 00000 */ - // 0x10, /* 00010 */ - // 0x20, /* 00100 */ - // 0x40, /* 01000 */ - // 0x20, /* 00100 */ - // 0x10, /* 00010 */ - // 0x70, /* 01110 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x10, /* 00010 */ + 0x20, /* 00100 */ + 0x40, /* 01000 */ + 0x20, /* 00100 */ + 0x10, /* 00010 */ + 0x70, /* 01110 */ + 0x00, /* 00000 */ // /* // * code=244, hex=0xF4, ascii="!t" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x18, /* 00011 */ - // 0x28, /* 00101 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x18, /* 00011 */ + 0x28, /* 00101 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ // /* // * code=245, hex=0xF5, ascii="!u" // */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0x20, /* 00100 */ - // 0xA0, /* 10100 */ - // 0xC0, /* 11000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0x20, /* 00100 */ + 0xA0, /* 10100 */ + 0xC0, /* 11000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=246, hex=0xF6, ascii="!v" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x60, /* 01100 */ - // 0x00, /* 00000 */ - // 0xF0, /* 11110 */ - // 0x00, /* 00000 */ - // 0x60, /* 01100 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x60, /* 01100 */ + 0x00, /* 00000 */ + 0xF0, /* 11110 */ + 0x00, /* 00000 */ + 0x60, /* 01100 */ + 0x00, /* 00000 */ // /* // * code=247, hex=0xF7, ascii="!w" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x50, /* 01010 */ - // 0xA0, /* 10100 */ - // 0x00, /* 00000 */ - // 0x50, /* 01010 */ - // 0xA0, /* 10100 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x50, /* 01010 */ + 0xA0, /* 10100 */ + 0x00, /* 00000 */ + 0x50, /* 01010 */ + 0xA0, /* 10100 */ + 0x00, /* 00000 */ // /* // * code=248, hex=0xF8, ascii="!x" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x20, /* 00100 */ - // 0x50, /* 01010 */ - // 0x20, /* 00100 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x20, /* 00100 */ + 0x50, /* 01010 */ + 0x20, /* 00100 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=249, hex=0xF9, ascii="!y" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x60, /* 01100 */ - // 0x60, /* 01100 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x60, /* 01100 */ + 0x60, /* 01100 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=250, hex=0xFA, ascii="!z" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x20, /* 00100 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x20, /* 00100 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=251, hex=0xFB, ascii="!{" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x18, /* 00011 */ - // 0x10, /* 00010 */ - // 0x20, /* 00100 */ - // 0xA0, /* 10100 */ - // 0x40, /* 01000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x18, /* 00011 */ + 0x10, /* 00010 */ + 0x20, /* 00100 */ + 0xA0, /* 10100 */ + 0x40, /* 01000 */ + 0x00, /* 00000 */ // /* // * code=252, hex=0xFC, ascii="!|" // */ - // 0x00, /* 00000 */ - // 0x60, /* 01100 */ - // 0x50, /* 01010 */ - // 0x50, /* 01010 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x60, /* 01100 */ + 0x50, /* 01010 */ + 0x50, /* 01010 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=253, hex=0xFD, ascii="!}" // */ - // 0x00, /* 00000 */ - // 0x60, /* 01100 */ - // 0x10, /* 00010 */ - // 0x20, /* 00100 */ - // 0x70, /* 01110 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x60, /* 01100 */ + 0x10, /* 00010 */ + 0x20, /* 00100 */ + 0x70, /* 01110 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ // /* // * code=254, hex=0xFE, ascii="!~" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x70, /* 01110 */ - // 0x70, /* 01110 */ - // 0x70, /* 01110 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x70, /* 01110 */ + 0x70, /* 01110 */ + 0x70, /* 01110 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ +#endif + +#if 0 // skip 255 = NBSP // /* // * code=255, hex=0xFF, ascii="!^Ÿ" // */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ - // 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ + 0x00, /* 00000 */ +#endif }; diff --git a/wled00/src/font/console_font_6x8.h b/wled00/src/font/console_font_6x8.h index 137c9cf1..8697ca19 100644 --- a/wled00/src/font/console_font_6x8.h +++ b/wled00/src/font/console_font_6x8.h @@ -1,392 +1,405 @@ +#if !defined(WLED_ENABLE_FULL_FONTS) +constexpr uint16_t console_font_6x8_first = 32; // index 0 = code 32 "" +constexpr uint16_t console_font_6x8_last = 126; // last index = code 126 "~" +#else +constexpr uint16_t console_font_6x8_first = 1; // index 0 = code 1 "☺︎" +constexpr uint16_t console_font_6x8_last = 254; // last index = code 254 "■" +#endif + // font courtesy of https://github.com/idispatch/raster-fonts static const unsigned char console_font_6x8[] PROGMEM = { // code points 0-31 and 127-255 are commented out to save memory, they contain extra characters (CP437), // which could be used with an UTF-8 to CP437 conversion - +#if 0 // skip 0 // /* // * code=0, hex=0x00, ascii="^@" // */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ +#endif + +#if defined(WLED_ENABLE_FULL_FONTS) // /* // * code=1, hex=0x01, ascii="^A" // */ - // 0x38, /* 001110 */ - // 0x44, /* 010001 */ - // 0x6C, /* 011011 */ - // 0x44, /* 010001 */ - // 0x54, /* 010101 */ - // 0x44, /* 010001 */ - // 0x38, /* 001110 */ - // 0x00, /* 000000 */ + 0x38, /* 001110 */ + 0x44, /* 010001 */ + 0x6C, /* 011011 */ + 0x44, /* 010001 */ + 0x54, /* 010101 */ + 0x44, /* 010001 */ + 0x38, /* 001110 */ + 0x00, /* 000000 */ // /* // * code=2, hex=0x02, ascii="^B" // */ - // 0x38, /* 001110 */ - // 0x7C, /* 011111 */ - // 0x54, /* 010101 */ - // 0x7C, /* 011111 */ - // 0x44, /* 010001 */ - // 0x7C, /* 011111 */ - // 0x38, /* 001110 */ - // 0x00, /* 000000 */ + 0x38, /* 001110 */ + 0x7C, /* 011111 */ + 0x54, /* 010101 */ + 0x7C, /* 011111 */ + 0x44, /* 010001 */ + 0x7C, /* 011111 */ + 0x38, /* 001110 */ + 0x00, /* 000000 */ // /* // * code=3, hex=0x03, ascii="^C" // */ - // 0x00, /* 000000 */ - // 0x28, /* 001010 */ - // 0x7C, /* 011111 */ - // 0x7C, /* 011111 */ - // 0x7C, /* 011111 */ - // 0x38, /* 001110 */ - // 0x10, /* 000100 */ - // 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x28, /* 001010 */ + 0x7C, /* 011111 */ + 0x7C, /* 011111 */ + 0x7C, /* 011111 */ + 0x38, /* 001110 */ + 0x10, /* 000100 */ + 0x00, /* 000000 */ // /* // * code=4, hex=0x04, ascii="^D" // */ - // 0x00, /* 000000 */ - // 0x10, /* 000100 */ - // 0x38, /* 001110 */ - // 0x7C, /* 011111 */ - // 0x7C, /* 011111 */ - // 0x38, /* 001110 */ - // 0x10, /* 000100 */ - // 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x10, /* 000100 */ + 0x38, /* 001110 */ + 0x7C, /* 011111 */ + 0x7C, /* 011111 */ + 0x38, /* 001110 */ + 0x10, /* 000100 */ + 0x00, /* 000000 */ // /* // * code=5, hex=0x05, ascii="^E" // */ - // 0x10, /* 000100 */ - // 0x38, /* 001110 */ - // 0x38, /* 001110 */ - // 0x10, /* 000100 */ - // 0x7C, /* 011111 */ - // 0x7C, /* 011111 */ - // 0x10, /* 000100 */ - // 0x00, /* 000000 */ + 0x10, /* 000100 */ + 0x38, /* 001110 */ + 0x38, /* 001110 */ + 0x10, /* 000100 */ + 0x7C, /* 011111 */ + 0x7C, /* 011111 */ + 0x10, /* 000100 */ + 0x00, /* 000000 */ // /* // * code=6, hex=0x06, ascii="^F" // */ - // 0x00, /* 000000 */ - // 0x10, /* 000100 */ - // 0x38, /* 001110 */ - // 0x7C, /* 011111 */ - // 0x7C, /* 011111 */ - // 0x10, /* 000100 */ - // 0x38, /* 001110 */ - // 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x10, /* 000100 */ + 0x38, /* 001110 */ + 0x7C, /* 011111 */ + 0x7C, /* 011111 */ + 0x10, /* 000100 */ + 0x38, /* 001110 */ + 0x00, /* 000000 */ // /* // * code=7, hex=0x07, ascii="^G" // */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0x30, /* 001100 */ - // 0x30, /* 001100 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x30, /* 001100 */ + 0x30, /* 001100 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ // /* // * code=8, hex=0x08, ascii="^H" // */ - // 0xFC, /* 111111 */ - // 0xFC, /* 111111 */ - // 0xFC, /* 111111 */ - // 0xCC, /* 110011 */ - // 0xCC, /* 110011 */ - // 0xFC, /* 111111 */ - // 0xFC, /* 111111 */ - // 0xFC, /* 111111 */ + 0xFC, /* 111111 */ + 0xFC, /* 111111 */ + 0xFC, /* 111111 */ + 0xCC, /* 110011 */ + 0xCC, /* 110011 */ + 0xFC, /* 111111 */ + 0xFC, /* 111111 */ + 0xFC, /* 111111 */ // /* // * code=9, hex=0x09, ascii="^I" // */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0x78, /* 011110 */ - // 0x48, /* 010010 */ - // 0x48, /* 010010 */ - // 0x78, /* 011110 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x78, /* 011110 */ + 0x48, /* 010010 */ + 0x48, /* 010010 */ + 0x78, /* 011110 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ // /* // * code=10, hex=0x0A, ascii="^J" // */ - // 0xFC, /* 111111 */ - // 0xFC, /* 111111 */ - // 0x84, /* 100001 */ - // 0xB4, /* 101101 */ - // 0xB4, /* 101101 */ - // 0x84, /* 100001 */ - // 0xFC, /* 111111 */ - // 0xFC, /* 111111 */ + 0xFC, /* 111111 */ + 0xFC, /* 111111 */ + 0x84, /* 100001 */ + 0xB4, /* 101101 */ + 0xB4, /* 101101 */ + 0x84, /* 100001 */ + 0xFC, /* 111111 */ + 0xFC, /* 111111 */ // /* // * code=11, hex=0x0B, ascii="^K" // */ - // 0x00, /* 000000 */ - // 0x1C, /* 000111 */ - // 0x0C, /* 000011 */ - // 0x34, /* 001101 */ - // 0x48, /* 010010 */ - // 0x48, /* 010010 */ - // 0x30, /* 001100 */ - // 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x1C, /* 000111 */ + 0x0C, /* 000011 */ + 0x34, /* 001101 */ + 0x48, /* 010010 */ + 0x48, /* 010010 */ + 0x30, /* 001100 */ + 0x00, /* 000000 */ // /* // * code=12, hex=0x0C, ascii="^L" // */ - // 0x38, /* 001110 */ - // 0x44, /* 010001 */ - // 0x44, /* 010001 */ - // 0x38, /* 001110 */ - // 0x10, /* 000100 */ - // 0x38, /* 001110 */ - // 0x10, /* 000100 */ - // 0x00, /* 000000 */ + 0x38, /* 001110 */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x38, /* 001110 */ + 0x10, /* 000100 */ + 0x38, /* 001110 */ + 0x10, /* 000100 */ + 0x00, /* 000000 */ // /* // * code=13, hex=0x0D, ascii="^M" // */ - // 0x10, /* 000100 */ - // 0x18, /* 000110 */ - // 0x14, /* 000101 */ - // 0x10, /* 000100 */ - // 0x30, /* 001100 */ - // 0x70, /* 011100 */ - // 0x60, /* 011000 */ - // 0x00, /* 000000 */ + 0x10, /* 000100 */ + 0x18, /* 000110 */ + 0x14, /* 000101 */ + 0x10, /* 000100 */ + 0x30, /* 001100 */ + 0x70, /* 011100 */ + 0x60, /* 011000 */ + 0x00, /* 000000 */ // /* // * code=14, hex=0x0E, ascii="^N" // */ - // 0x0C, /* 000011 */ - // 0x34, /* 001101 */ - // 0x2C, /* 001011 */ - // 0x34, /* 001101 */ - // 0x2C, /* 001011 */ - // 0x6C, /* 011011 */ - // 0x60, /* 011000 */ - // 0x00, /* 000000 */ + 0x0C, /* 000011 */ + 0x34, /* 001101 */ + 0x2C, /* 001011 */ + 0x34, /* 001101 */ + 0x2C, /* 001011 */ + 0x6C, /* 011011 */ + 0x60, /* 011000 */ + 0x00, /* 000000 */ // /* // * code=15, hex=0x0F, ascii="^O" // */ - // 0x00, /* 000000 */ - // 0x54, /* 010101 */ - // 0x38, /* 001110 */ - // 0x6C, /* 011011 */ - // 0x38, /* 001110 */ - // 0x54, /* 010101 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x54, /* 010101 */ + 0x38, /* 001110 */ + 0x6C, /* 011011 */ + 0x38, /* 001110 */ + 0x54, /* 010101 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ // /* // * code=16, hex=0x10, ascii="^P" // */ - // 0x20, /* 001000 */ - // 0x30, /* 001100 */ - // 0x38, /* 001110 */ - // 0x3C, /* 001111 */ - // 0x38, /* 001110 */ - // 0x30, /* 001100 */ - // 0x20, /* 001000 */ - // 0x00, /* 000000 */ + 0x20, /* 001000 */ + 0x30, /* 001100 */ + 0x38, /* 001110 */ + 0x3C, /* 001111 */ + 0x38, /* 001110 */ + 0x30, /* 001100 */ + 0x20, /* 001000 */ + 0x00, /* 000000 */ // /* // * code=17, hex=0x11, ascii="^Q" // */ - // 0x08, /* 000010 */ - // 0x18, /* 000110 */ - // 0x38, /* 001110 */ - // 0x78, /* 011110 */ - // 0x38, /* 001110 */ - // 0x18, /* 000110 */ - // 0x08, /* 000010 */ - // 0x00, /* 000000 */ + 0x08, /* 000010 */ + 0x18, /* 000110 */ + 0x38, /* 001110 */ + 0x78, /* 011110 */ + 0x38, /* 001110 */ + 0x18, /* 000110 */ + 0x08, /* 000010 */ + 0x00, /* 000000 */ // /* // * code=18, hex=0x12, ascii="^R" // */ - // 0x10, /* 000100 */ - // 0x38, /* 001110 */ - // 0x7C, /* 011111 */ - // 0x10, /* 000100 */ - // 0x7C, /* 011111 */ - // 0x38, /* 001110 */ - // 0x10, /* 000100 */ - // 0x00, /* 000000 */ + 0x10, /* 000100 */ + 0x38, /* 001110 */ + 0x7C, /* 011111 */ + 0x10, /* 000100 */ + 0x7C, /* 011111 */ + 0x38, /* 001110 */ + 0x10, /* 000100 */ + 0x00, /* 000000 */ // /* // * code=19, hex=0x13, ascii="^S" // */ - // 0x28, /* 001010 */ - // 0x28, /* 001010 */ - // 0x28, /* 001010 */ - // 0x28, /* 001010 */ - // 0x28, /* 001010 */ - // 0x00, /* 000000 */ - // 0x28, /* 001010 */ - // 0x00, /* 000000 */ + 0x28, /* 001010 */ + 0x28, /* 001010 */ + 0x28, /* 001010 */ + 0x28, /* 001010 */ + 0x28, /* 001010 */ + 0x00, /* 000000 */ + 0x28, /* 001010 */ + 0x00, /* 000000 */ // /* // * code=20, hex=0x14, ascii="^T" // */ - // 0x3C, /* 001111 */ - // 0x54, /* 010101 */ - // 0x54, /* 010101 */ - // 0x34, /* 001101 */ - // 0x14, /* 000101 */ - // 0x14, /* 000101 */ - // 0x14, /* 000101 */ - // 0x00, /* 000000 */ + 0x3C, /* 001111 */ + 0x54, /* 010101 */ + 0x54, /* 010101 */ + 0x34, /* 001101 */ + 0x14, /* 000101 */ + 0x14, /* 000101 */ + 0x14, /* 000101 */ + 0x00, /* 000000 */ // /* // * code=21, hex=0x15, ascii="^U" // */ - // 0x38, /* 001110 */ - // 0x44, /* 010001 */ - // 0x30, /* 001100 */ - // 0x28, /* 001010 */ - // 0x18, /* 000110 */ - // 0x44, /* 010001 */ - // 0x38, /* 001110 */ - // 0x00, /* 000000 */ + 0x38, /* 001110 */ + 0x44, /* 010001 */ + 0x30, /* 001100 */ + 0x28, /* 001010 */ + 0x18, /* 000110 */ + 0x44, /* 010001 */ + 0x38, /* 001110 */ + 0x00, /* 000000 */ // /* // * code=22, hex=0x16, ascii="^V" // */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0x78, /* 011110 */ - // 0x78, /* 011110 */ - // 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x78, /* 011110 */ + 0x78, /* 011110 */ + 0x00, /* 000000 */ // /* // * code=23, hex=0x17, ascii="^W" // */ - // 0x10, /* 000100 */ - // 0x38, /* 001110 */ - // 0x7C, /* 011111 */ - // 0x10, /* 000100 */ - // 0x7C, /* 011111 */ - // 0x38, /* 001110 */ - // 0x10, /* 000100 */ - // 0x38, /* 001110 */ + 0x10, /* 000100 */ + 0x38, /* 001110 */ + 0x7C, /* 011111 */ + 0x10, /* 000100 */ + 0x7C, /* 011111 */ + 0x38, /* 001110 */ + 0x10, /* 000100 */ + 0x38, /* 001110 */ // /* // * code=24, hex=0x18, ascii="^X" // */ - // 0x10, /* 000100 */ - // 0x38, /* 001110 */ - // 0x7C, /* 011111 */ - // 0x10, /* 000100 */ - // 0x10, /* 000100 */ - // 0x10, /* 000100 */ - // 0x10, /* 000100 */ - // 0x00, /* 000000 */ + 0x10, /* 000100 */ + 0x38, /* 001110 */ + 0x7C, /* 011111 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x00, /* 000000 */ // /* // * code=25, hex=0x19, ascii="^Y" // */ - // 0x10, /* 000100 */ - // 0x10, /* 000100 */ - // 0x10, /* 000100 */ - // 0x10, /* 000100 */ - // 0x7C, /* 011111 */ - // 0x38, /* 001110 */ - // 0x10, /* 000100 */ - // 0x00, /* 000000 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x7C, /* 011111 */ + 0x38, /* 001110 */ + 0x10, /* 000100 */ + 0x00, /* 000000 */ // /* // * code=26, hex=0x1A, ascii="^Z" // */ - // 0x00, /* 000000 */ - // 0x10, /* 000100 */ - // 0x18, /* 000110 */ - // 0x7C, /* 011111 */ - // 0x18, /* 000110 */ - // 0x10, /* 000100 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x10, /* 000100 */ + 0x18, /* 000110 */ + 0x7C, /* 011111 */ + 0x18, /* 000110 */ + 0x10, /* 000100 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ // /* // * code=27, hex=0x1B, ascii="^[" // */ - // 0x00, /* 000000 */ - // 0x10, /* 000100 */ - // 0x30, /* 001100 */ - // 0x7C, /* 011111 */ - // 0x30, /* 001100 */ - // 0x10, /* 000100 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x10, /* 000100 */ + 0x30, /* 001100 */ + 0x7C, /* 011111 */ + 0x30, /* 001100 */ + 0x10, /* 000100 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ // /* // * code=28, hex=0x1C, ascii="^\" // */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0x40, /* 010000 */ - // 0x40, /* 010000 */ - // 0x40, /* 010000 */ - // 0x7C, /* 011111 */ - // 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x40, /* 010000 */ + 0x40, /* 010000 */ + 0x40, /* 010000 */ + 0x7C, /* 011111 */ + 0x00, /* 000000 */ // /* // * code=29, hex=0x1D, ascii="^]" // */ - // 0x00, /* 000000 */ - // 0x28, /* 001010 */ - // 0x28, /* 001010 */ - // 0x7C, /* 011111 */ - // 0x28, /* 001010 */ - // 0x28, /* 001010 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x28, /* 001010 */ + 0x28, /* 001010 */ + 0x7C, /* 011111 */ + 0x28, /* 001010 */ + 0x28, /* 001010 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ // /* // * code=30, hex=0x1E, ascii="^^" // */ - // 0x10, /* 000100 */ - // 0x10, /* 000100 */ - // 0x38, /* 001110 */ - // 0x38, /* 001110 */ - // 0x7C, /* 011111 */ - // 0x7C, /* 011111 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x38, /* 001110 */ + 0x38, /* 001110 */ + 0x7C, /* 011111 */ + 0x7C, /* 011111 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ // /* // * code=31, hex=0x1F, ascii="^_" // */ - // 0x7C, /* 011111 */ - // 0x7C, /* 011111 */ - // 0x38, /* 001110 */ - // 0x38, /* 001110 */ - // 0x10, /* 000100 */ - // 0x10, /* 000100 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ + 0x7C, /* 011111 */ + 0x7C, /* 011111 */ + 0x38, /* 001110 */ + 0x38, /* 001110 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + +#endif /* * code=32, hex=0x20, ascii=" " @@ -1528,1551 +1541,1556 @@ static const unsigned char console_font_6x8[] PROGMEM = { 0x00, /* 000000 */ 0x00, /* 000000 */ +#if defined(WLED_ENABLE_FULL_FONTS) + // /* // * code=127, hex=0x7F, ascii="^?" // */ - // 0x10, /* 000100 */ - // 0x38, /* 001110 */ - // 0x6C, /* 011011 */ - // 0x44, /* 010001 */ - // 0x44, /* 010001 */ - // 0x7C, /* 011111 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ + 0x10, /* 000100 */ + 0x38, /* 001110 */ + 0x6C, /* 011011 */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x7C, /* 011111 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ // /* // * code=128, hex=0x80, ascii="!^@" // */ - // 0x38, /* 001110 */ - // 0x44, /* 010001 */ - // 0x40, /* 010000 */ - // 0x40, /* 010000 */ - // 0x44, /* 010001 */ - // 0x38, /* 001110 */ - // 0x10, /* 000100 */ - // 0x30, /* 001100 */ + 0x38, /* 001110 */ + 0x44, /* 010001 */ + 0x40, /* 010000 */ + 0x40, /* 010000 */ + 0x44, /* 010001 */ + 0x38, /* 001110 */ + 0x10, /* 000100 */ + 0x30, /* 001100 */ // /* // * code=129, hex=0x81, ascii="!^A" // */ - // 0x48, /* 010010 */ - // 0x00, /* 000000 */ - // 0x48, /* 010010 */ - // 0x48, /* 010010 */ - // 0x48, /* 010010 */ - // 0x58, /* 010110 */ - // 0x28, /* 001010 */ - // 0x00, /* 000000 */ + 0x48, /* 010010 */ + 0x00, /* 000000 */ + 0x48, /* 010010 */ + 0x48, /* 010010 */ + 0x48, /* 010010 */ + 0x58, /* 010110 */ + 0x28, /* 001010 */ + 0x00, /* 000000 */ // /* // * code=130, hex=0x82, ascii="!^B" // */ - // 0x0C, /* 000011 */ - // 0x00, /* 000000 */ - // 0x38, /* 001110 */ - // 0x44, /* 010001 */ - // 0x78, /* 011110 */ - // 0x40, /* 010000 */ - // 0x38, /* 001110 */ - // 0x00, /* 000000 */ + 0x0C, /* 000011 */ + 0x00, /* 000000 */ + 0x38, /* 001110 */ + 0x44, /* 010001 */ + 0x78, /* 011110 */ + 0x40, /* 010000 */ + 0x38, /* 001110 */ + 0x00, /* 000000 */ // /* // * code=131, hex=0x83, ascii="!^C" // */ - // 0x38, /* 001110 */ - // 0x00, /* 000000 */ - // 0x38, /* 001110 */ - // 0x04, /* 000001 */ - // 0x3C, /* 001111 */ - // 0x44, /* 010001 */ - // 0x3C, /* 001111 */ - // 0x00, /* 000000 */ + 0x38, /* 001110 */ + 0x00, /* 000000 */ + 0x38, /* 001110 */ + 0x04, /* 000001 */ + 0x3C, /* 001111 */ + 0x44, /* 010001 */ + 0x3C, /* 001111 */ + 0x00, /* 000000 */ // /* // * code=132, hex=0x84, ascii="!^D" // */ - // 0x28, /* 001010 */ - // 0x00, /* 000000 */ - // 0x38, /* 001110 */ - // 0x04, /* 000001 */ - // 0x3C, /* 001111 */ - // 0x44, /* 010001 */ - // 0x3C, /* 001111 */ - // 0x00, /* 000000 */ + 0x28, /* 001010 */ + 0x00, /* 000000 */ + 0x38, /* 001110 */ + 0x04, /* 000001 */ + 0x3C, /* 001111 */ + 0x44, /* 010001 */ + 0x3C, /* 001111 */ + 0x00, /* 000000 */ // /* // * code=133, hex=0x85, ascii="!^E" // */ - // 0x30, /* 001100 */ - // 0x00, /* 000000 */ - // 0x38, /* 001110 */ - // 0x04, /* 000001 */ - // 0x3C, /* 001111 */ - // 0x44, /* 010001 */ - // 0x3C, /* 001111 */ - // 0x00, /* 000000 */ + 0x30, /* 001100 */ + 0x00, /* 000000 */ + 0x38, /* 001110 */ + 0x04, /* 000001 */ + 0x3C, /* 001111 */ + 0x44, /* 010001 */ + 0x3C, /* 001111 */ + 0x00, /* 000000 */ // /* // * code=134, hex=0x86, ascii="!^F" // */ - // 0x38, /* 001110 */ - // 0x28, /* 001010 */ - // 0x38, /* 001110 */ - // 0x04, /* 000001 */ - // 0x3C, /* 001111 */ - // 0x44, /* 010001 */ - // 0x3C, /* 001111 */ - // 0x00, /* 000000 */ + 0x38, /* 001110 */ + 0x28, /* 001010 */ + 0x38, /* 001110 */ + 0x04, /* 000001 */ + 0x3C, /* 001111 */ + 0x44, /* 010001 */ + 0x3C, /* 001111 */ + 0x00, /* 000000 */ // /* // * code=135, hex=0x87, ascii="!^G" // */ - // 0x00, /* 000000 */ - // 0x38, /* 001110 */ - // 0x44, /* 010001 */ - // 0x40, /* 010000 */ - // 0x44, /* 010001 */ - // 0x38, /* 001110 */ - // 0x10, /* 000100 */ - // 0x30, /* 001100 */ + 0x00, /* 000000 */ + 0x38, /* 001110 */ + 0x44, /* 010001 */ + 0x40, /* 010000 */ + 0x44, /* 010001 */ + 0x38, /* 001110 */ + 0x10, /* 000100 */ + 0x30, /* 001100 */ // /* // * code=136, hex=0x88, ascii="!^H" // */ - // 0x38, /* 001110 */ - // 0x00, /* 000000 */ - // 0x38, /* 001110 */ - // 0x44, /* 010001 */ - // 0x78, /* 011110 */ - // 0x40, /* 010000 */ - // 0x38, /* 001110 */ - // 0x00, /* 000000 */ + 0x38, /* 001110 */ + 0x00, /* 000000 */ + 0x38, /* 001110 */ + 0x44, /* 010001 */ + 0x78, /* 011110 */ + 0x40, /* 010000 */ + 0x38, /* 001110 */ + 0x00, /* 000000 */ // /* // * code=137, hex=0x89, ascii="!^I" // */ - // 0x28, /* 001010 */ - // 0x00, /* 000000 */ - // 0x38, /* 001110 */ - // 0x44, /* 010001 */ - // 0x78, /* 011110 */ - // 0x40, /* 010000 */ - // 0x38, /* 001110 */ - // 0x00, /* 000000 */ + 0x28, /* 001010 */ + 0x00, /* 000000 */ + 0x38, /* 001110 */ + 0x44, /* 010001 */ + 0x78, /* 011110 */ + 0x40, /* 010000 */ + 0x38, /* 001110 */ + 0x00, /* 000000 */ // /* // * code=138, hex=0x8A, ascii="!^J" // */ - // 0x30, /* 001100 */ - // 0x00, /* 000000 */ - // 0x38, /* 001110 */ - // 0x44, /* 010001 */ - // 0x78, /* 011110 */ - // 0x40, /* 010000 */ - // 0x38, /* 001110 */ - // 0x00, /* 000000 */ + 0x30, /* 001100 */ + 0x00, /* 000000 */ + 0x38, /* 001110 */ + 0x44, /* 010001 */ + 0x78, /* 011110 */ + 0x40, /* 010000 */ + 0x38, /* 001110 */ + 0x00, /* 000000 */ // /* // * code=139, hex=0x8B, ascii="!^K" // */ - // 0x28, /* 001010 */ - // 0x00, /* 000000 */ - // 0x10, /* 000100 */ - // 0x10, /* 000100 */ - // 0x10, /* 000100 */ - // 0x10, /* 000100 */ - // 0x18, /* 000110 */ - // 0x00, /* 000000 */ + 0x28, /* 001010 */ + 0x00, /* 000000 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x18, /* 000110 */ + 0x00, /* 000000 */ // /* // * code=140, hex=0x8C, ascii="!^L" // */ - // 0x10, /* 000100 */ - // 0x28, /* 001010 */ - // 0x00, /* 000000 */ - // 0x10, /* 000100 */ - // 0x10, /* 000100 */ - // 0x10, /* 000100 */ - // 0x18, /* 000110 */ - // 0x00, /* 000000 */ + 0x10, /* 000100 */ + 0x28, /* 001010 */ + 0x00, /* 000000 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x18, /* 000110 */ + 0x00, /* 000000 */ // /* // * code=141, hex=0x8D, ascii="!^M" // */ - // 0x20, /* 001000 */ - // 0x00, /* 000000 */ - // 0x10, /* 000100 */ - // 0x10, /* 000100 */ - // 0x10, /* 000100 */ - // 0x10, /* 000100 */ - // 0x18, /* 000110 */ - // 0x00, /* 000000 */ + 0x20, /* 001000 */ + 0x00, /* 000000 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x18, /* 000110 */ + 0x00, /* 000000 */ // /* // * code=142, hex=0x8E, ascii="!^N" // */ - // 0x28, /* 001010 */ - // 0x00, /* 000000 */ - // 0x10, /* 000100 */ - // 0x28, /* 001010 */ - // 0x44, /* 010001 */ - // 0x7C, /* 011111 */ - // 0x44, /* 010001 */ - // 0x00, /* 000000 */ + 0x28, /* 001010 */ + 0x00, /* 000000 */ + 0x10, /* 000100 */ + 0x28, /* 001010 */ + 0x44, /* 010001 */ + 0x7C, /* 011111 */ + 0x44, /* 010001 */ + 0x00, /* 000000 */ // /* // * code=143, hex=0x8F, ascii="!^O" // */ - // 0x38, /* 001110 */ - // 0x28, /* 001010 */ - // 0x38, /* 001110 */ - // 0x6C, /* 011011 */ - // 0x44, /* 010001 */ - // 0x7C, /* 011111 */ - // 0x44, /* 010001 */ - // 0x00, /* 000000 */ + 0x38, /* 001110 */ + 0x28, /* 001010 */ + 0x38, /* 001110 */ + 0x6C, /* 011011 */ + 0x44, /* 010001 */ + 0x7C, /* 011111 */ + 0x44, /* 010001 */ + 0x00, /* 000000 */ // /* // * code=144, hex=0x90, ascii="!^P" // */ - // 0x0C, /* 000011 */ - // 0x00, /* 000000 */ - // 0x7C, /* 011111 */ - // 0x40, /* 010000 */ - // 0x78, /* 011110 */ - // 0x40, /* 010000 */ - // 0x7C, /* 011111 */ - // 0x00, /* 000000 */ + 0x0C, /* 000011 */ + 0x00, /* 000000 */ + 0x7C, /* 011111 */ + 0x40, /* 010000 */ + 0x78, /* 011110 */ + 0x40, /* 010000 */ + 0x7C, /* 011111 */ + 0x00, /* 000000 */ // /* // * code=145, hex=0x91, ascii="!^Q" // */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0x78, /* 011110 */ - // 0x14, /* 000101 */ - // 0x7C, /* 011111 */ - // 0x50, /* 010100 */ - // 0x3C, /* 001111 */ - // 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x78, /* 011110 */ + 0x14, /* 000101 */ + 0x7C, /* 011111 */ + 0x50, /* 010100 */ + 0x3C, /* 001111 */ + 0x00, /* 000000 */ // /* // * code=146, hex=0x92, ascii="!^R" // */ - // 0x3C, /* 001111 */ - // 0x50, /* 010100 */ - // 0x50, /* 010100 */ - // 0x7C, /* 011111 */ - // 0x50, /* 010100 */ - // 0x50, /* 010100 */ - // 0x5C, /* 010111 */ - // 0x00, /* 000000 */ + 0x3C, /* 001111 */ + 0x50, /* 010100 */ + 0x50, /* 010100 */ + 0x7C, /* 011111 */ + 0x50, /* 010100 */ + 0x50, /* 010100 */ + 0x5C, /* 010111 */ + 0x00, /* 000000 */ // /* // * code=147, hex=0x93, ascii="!^S" // */ - // 0x38, /* 001110 */ - // 0x00, /* 000000 */ - // 0x30, /* 001100 */ - // 0x48, /* 010010 */ - // 0x48, /* 010010 */ - // 0x48, /* 010010 */ - // 0x30, /* 001100 */ - // 0x00, /* 000000 */ + 0x38, /* 001110 */ + 0x00, /* 000000 */ + 0x30, /* 001100 */ + 0x48, /* 010010 */ + 0x48, /* 010010 */ + 0x48, /* 010010 */ + 0x30, /* 001100 */ + 0x00, /* 000000 */ // /* // * code=148, hex=0x94, ascii="!^T" // */ - // 0x28, /* 001010 */ - // 0x00, /* 000000 */ - // 0x30, /* 001100 */ - // 0x48, /* 010010 */ - // 0x48, /* 010010 */ - // 0x48, /* 010010 */ - // 0x30, /* 001100 */ - // 0x00, /* 000000 */ + 0x28, /* 001010 */ + 0x00, /* 000000 */ + 0x30, /* 001100 */ + 0x48, /* 010010 */ + 0x48, /* 010010 */ + 0x48, /* 010010 */ + 0x30, /* 001100 */ + 0x00, /* 000000 */ // /* // * code=149, hex=0x95, ascii="!^U" // */ - // 0x60, /* 011000 */ - // 0x00, /* 000000 */ - // 0x30, /* 001100 */ - // 0x48, /* 010010 */ - // 0x48, /* 010010 */ - // 0x48, /* 010010 */ - // 0x30, /* 001100 */ - // 0x00, /* 000000 */ + 0x60, /* 011000 */ + 0x00, /* 000000 */ + 0x30, /* 001100 */ + 0x48, /* 010010 */ + 0x48, /* 010010 */ + 0x48, /* 010010 */ + 0x30, /* 001100 */ + 0x00, /* 000000 */ // /* // * code=150, hex=0x96, ascii="!^V" // */ - // 0x38, /* 001110 */ - // 0x00, /* 000000 */ - // 0x48, /* 010010 */ - // 0x48, /* 010010 */ - // 0x48, /* 010010 */ - // 0x58, /* 010110 */ - // 0x28, /* 001010 */ - // 0x00, /* 000000 */ + 0x38, /* 001110 */ + 0x00, /* 000000 */ + 0x48, /* 010010 */ + 0x48, /* 010010 */ + 0x48, /* 010010 */ + 0x58, /* 010110 */ + 0x28, /* 001010 */ + 0x00, /* 000000 */ // /* // * code=151, hex=0x97, ascii="!^W" // */ - // 0x60, /* 011000 */ - // 0x00, /* 000000 */ - // 0x48, /* 010010 */ - // 0x48, /* 010010 */ - // 0x48, /* 010010 */ - // 0x58, /* 010110 */ - // 0x28, /* 001010 */ - // 0x00, /* 000000 */ + 0x60, /* 011000 */ + 0x00, /* 000000 */ + 0x48, /* 010010 */ + 0x48, /* 010010 */ + 0x48, /* 010010 */ + 0x58, /* 010110 */ + 0x28, /* 001010 */ + 0x00, /* 000000 */ // /* // * code=152, hex=0x98, ascii="!^X" // */ - // 0x28, /* 001010 */ - // 0x00, /* 000000 */ - // 0x48, /* 010010 */ - // 0x48, /* 010010 */ - // 0x48, /* 010010 */ - // 0x38, /* 001110 */ - // 0x10, /* 000100 */ - // 0x60, /* 011000 */ + 0x28, /* 001010 */ + 0x00, /* 000000 */ + 0x48, /* 010010 */ + 0x48, /* 010010 */ + 0x48, /* 010010 */ + 0x38, /* 001110 */ + 0x10, /* 000100 */ + 0x60, /* 011000 */ // /* // * code=153, hex=0x99, ascii="!^Y" // */ - // 0x48, /* 010010 */ - // 0x30, /* 001100 */ - // 0x48, /* 010010 */ - // 0x48, /* 010010 */ - // 0x48, /* 010010 */ - // 0x48, /* 010010 */ - // 0x30, /* 001100 */ - // 0x00, /* 000000 */ + 0x48, /* 010010 */ + 0x30, /* 001100 */ + 0x48, /* 010010 */ + 0x48, /* 010010 */ + 0x48, /* 010010 */ + 0x48, /* 010010 */ + 0x30, /* 001100 */ + 0x00, /* 000000 */ // /* // * code=154, hex=0x9A, ascii="!^Z" // */ - // 0x28, /* 001010 */ - // 0x00, /* 000000 */ - // 0x48, /* 010010 */ - // 0x48, /* 010010 */ - // 0x48, /* 010010 */ - // 0x48, /* 010010 */ - // 0x30, /* 001100 */ - // 0x00, /* 000000 */ + 0x28, /* 001010 */ + 0x00, /* 000000 */ + 0x48, /* 010010 */ + 0x48, /* 010010 */ + 0x48, /* 010010 */ + 0x48, /* 010010 */ + 0x30, /* 001100 */ + 0x00, /* 000000 */ // /* // * code=155, hex=0x9B, ascii="!^[" // */ - // 0x00, /* 000000 */ - // 0x10, /* 000100 */ - // 0x38, /* 001110 */ - // 0x40, /* 010000 */ - // 0x40, /* 010000 */ - // 0x38, /* 001110 */ - // 0x10, /* 000100 */ - // 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x10, /* 000100 */ + 0x38, /* 001110 */ + 0x40, /* 010000 */ + 0x40, /* 010000 */ + 0x38, /* 001110 */ + 0x10, /* 000100 */ + 0x00, /* 000000 */ // /* // * code=156, hex=0x9C, ascii="!^\" // */ - // 0x18, /* 000110 */ - // 0x24, /* 001001 */ - // 0x20, /* 001000 */ - // 0x78, /* 011110 */ - // 0x20, /* 001000 */ - // 0x24, /* 001001 */ - // 0x5C, /* 010111 */ - // 0x00, /* 000000 */ + 0x18, /* 000110 */ + 0x24, /* 001001 */ + 0x20, /* 001000 */ + 0x78, /* 011110 */ + 0x20, /* 001000 */ + 0x24, /* 001001 */ + 0x5C, /* 010111 */ + 0x00, /* 000000 */ // /* // * code=157, hex=0x9D, ascii="!^]" // */ - // 0x44, /* 010001 */ - // 0x28, /* 001010 */ - // 0x10, /* 000100 */ - // 0x7C, /* 011111 */ - // 0x10, /* 000100 */ - // 0x7C, /* 011111 */ - // 0x10, /* 000100 */ - // 0x00, /* 000000 */ + 0x44, /* 010001 */ + 0x28, /* 001010 */ + 0x10, /* 000100 */ + 0x7C, /* 011111 */ + 0x10, /* 000100 */ + 0x7C, /* 011111 */ + 0x10, /* 000100 */ + 0x00, /* 000000 */ // /* // * code=158, hex=0x9E, ascii="!^^" // */ - // 0x60, /* 011000 */ - // 0x50, /* 010100 */ - // 0x50, /* 010100 */ - // 0x68, /* 011010 */ - // 0x5C, /* 010111 */ - // 0x48, /* 010010 */ - // 0x48, /* 010010 */ - // 0x00, /* 000000 */ + 0x60, /* 011000 */ + 0x50, /* 010100 */ + 0x50, /* 010100 */ + 0x68, /* 011010 */ + 0x5C, /* 010111 */ + 0x48, /* 010010 */ + 0x48, /* 010010 */ + 0x00, /* 000000 */ // /* // * code=159, hex=0x9F, ascii="!^_" // */ - // 0x08, /* 000010 */ - // 0x14, /* 000101 */ - // 0x10, /* 000100 */ - // 0x38, /* 001110 */ - // 0x10, /* 000100 */ - // 0x10, /* 000100 */ - // 0x50, /* 010100 */ - // 0x20, /* 001000 */ + 0x08, /* 000010 */ + 0x14, /* 000101 */ + 0x10, /* 000100 */ + 0x38, /* 001110 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x50, /* 010100 */ + 0x20, /* 001000 */ // /* // * code=160, hex=0xA0, ascii="! " // */ - // 0x18, /* 000110 */ - // 0x00, /* 000000 */ - // 0x38, /* 001110 */ - // 0x04, /* 000001 */ - // 0x3C, /* 001111 */ - // 0x44, /* 010001 */ - // 0x3C, /* 001111 */ - // 0x00, /* 000000 */ + 0x18, /* 000110 */ + 0x00, /* 000000 */ + 0x38, /* 001110 */ + 0x04, /* 000001 */ + 0x3C, /* 001111 */ + 0x44, /* 010001 */ + 0x3C, /* 001111 */ + 0x00, /* 000000 */ // /* // * code=161, hex=0xA1, ascii="!!" // */ - // 0x18, /* 000110 */ - // 0x00, /* 000000 */ - // 0x10, /* 000100 */ - // 0x10, /* 000100 */ - // 0x10, /* 000100 */ - // 0x10, /* 000100 */ - // 0x18, /* 000110 */ - // 0x00, /* 000000 */ + 0x18, /* 000110 */ + 0x00, /* 000000 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x18, /* 000110 */ + 0x00, /* 000000 */ // /* // * code=162, hex=0xA2, ascii="!"" // */ - // 0x18, /* 000110 */ - // 0x00, /* 000000 */ - // 0x30, /* 001100 */ - // 0x48, /* 010010 */ - // 0x48, /* 010010 */ - // 0x48, /* 010010 */ - // 0x30, /* 001100 */ - // 0x00, /* 000000 */ + 0x18, /* 000110 */ + 0x00, /* 000000 */ + 0x30, /* 001100 */ + 0x48, /* 010010 */ + 0x48, /* 010010 */ + 0x48, /* 010010 */ + 0x30, /* 001100 */ + 0x00, /* 000000 */ // /* // * code=163, hex=0xA3, ascii="!#" // */ - // 0x18, /* 000110 */ - // 0x00, /* 000000 */ - // 0x48, /* 010010 */ - // 0x48, /* 010010 */ - // 0x48, /* 010010 */ - // 0x58, /* 010110 */ - // 0x28, /* 001010 */ - // 0x00, /* 000000 */ + 0x18, /* 000110 */ + 0x00, /* 000000 */ + 0x48, /* 010010 */ + 0x48, /* 010010 */ + 0x48, /* 010010 */ + 0x58, /* 010110 */ + 0x28, /* 001010 */ + 0x00, /* 000000 */ // /* // * code=164, hex=0xA4, ascii="!$" // */ - // 0x28, /* 001010 */ - // 0x50, /* 010100 */ - // 0x00, /* 000000 */ - // 0x70, /* 011100 */ - // 0x48, /* 010010 */ - // 0x48, /* 010010 */ - // 0x48, /* 010010 */ - // 0x00, /* 000000 */ + 0x28, /* 001010 */ + 0x50, /* 010100 */ + 0x00, /* 000000 */ + 0x70, /* 011100 */ + 0x48, /* 010010 */ + 0x48, /* 010010 */ + 0x48, /* 010010 */ + 0x00, /* 000000 */ // /* // * code=165, hex=0xA5, ascii="!%" // */ - // 0x28, /* 001010 */ - // 0x50, /* 010100 */ - // 0x00, /* 000000 */ - // 0x48, /* 010010 */ - // 0x68, /* 011010 */ - // 0x58, /* 010110 */ - // 0x48, /* 010010 */ - // 0x00, /* 000000 */ + 0x28, /* 001010 */ + 0x50, /* 010100 */ + 0x00, /* 000000 */ + 0x48, /* 010010 */ + 0x68, /* 011010 */ + 0x58, /* 010110 */ + 0x48, /* 010010 */ + 0x00, /* 000000 */ // /* // * code=166, hex=0xA6, ascii="!&" // */ - // 0x38, /* 001110 */ - // 0x04, /* 000001 */ - // 0x3C, /* 001111 */ - // 0x44, /* 010001 */ - // 0x3C, /* 001111 */ - // 0x00, /* 000000 */ - // 0x3C, /* 001111 */ - // 0x00, /* 000000 */ + 0x38, /* 001110 */ + 0x04, /* 000001 */ + 0x3C, /* 001111 */ + 0x44, /* 010001 */ + 0x3C, /* 001111 */ + 0x00, /* 000000 */ + 0x3C, /* 001111 */ + 0x00, /* 000000 */ // /* // * code=167, hex=0xA7, ascii="!'" // */ - // 0x30, /* 001100 */ - // 0x48, /* 010010 */ - // 0x48, /* 010010 */ - // 0x48, /* 010010 */ - // 0x30, /* 001100 */ - // 0x00, /* 000000 */ - // 0x78, /* 011110 */ - // 0x00, /* 000000 */ + 0x30, /* 001100 */ + 0x48, /* 010010 */ + 0x48, /* 010010 */ + 0x48, /* 010010 */ + 0x30, /* 001100 */ + 0x00, /* 000000 */ + 0x78, /* 011110 */ + 0x00, /* 000000 */ // /* // * code=168, hex=0xA8, ascii="!(" // */ - // 0x10, /* 000100 */ - // 0x00, /* 000000 */ - // 0x10, /* 000100 */ - // 0x30, /* 001100 */ - // 0x40, /* 010000 */ - // 0x44, /* 010001 */ - // 0x38, /* 001110 */ - // 0x00, /* 000000 */ + 0x10, /* 000100 */ + 0x00, /* 000000 */ + 0x10, /* 000100 */ + 0x30, /* 001100 */ + 0x40, /* 010000 */ + 0x44, /* 010001 */ + 0x38, /* 001110 */ + 0x00, /* 000000 */ // /* // * code=169, hex=0xA9, ascii="!)" // */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0x7C, /* 011111 */ - // 0x40, /* 010000 */ - // 0x40, /* 010000 */ - // 0x40, /* 010000 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x7C, /* 011111 */ + 0x40, /* 010000 */ + 0x40, /* 010000 */ + 0x40, /* 010000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ // /* // * code=170, hex=0xAA, ascii="!*" // */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0xFC, /* 111111 */ - // 0x04, /* 000001 */ - // 0x04, /* 000001 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0xFC, /* 111111 */ + 0x04, /* 000001 */ + 0x04, /* 000001 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ // /* // * code=171, hex=0xAB, ascii="!+" // */ - // 0x40, /* 010000 */ - // 0x48, /* 010010 */ - // 0x50, /* 010100 */ - // 0x38, /* 001110 */ - // 0x44, /* 010001 */ - // 0x08, /* 000010 */ - // 0x1C, /* 000111 */ - // 0x00, /* 000000 */ + 0x40, /* 010000 */ + 0x48, /* 010010 */ + 0x50, /* 010100 */ + 0x38, /* 001110 */ + 0x44, /* 010001 */ + 0x08, /* 000010 */ + 0x1C, /* 000111 */ + 0x00, /* 000000 */ // /* // * code=172, hex=0xAC, ascii="!," // */ - // 0x40, /* 010000 */ - // 0x48, /* 010010 */ - // 0x50, /* 010100 */ - // 0x2C, /* 001011 */ - // 0x54, /* 010101 */ - // 0x1C, /* 000111 */ - // 0x04, /* 000001 */ - // 0x00, /* 000000 */ + 0x40, /* 010000 */ + 0x48, /* 010010 */ + 0x50, /* 010100 */ + 0x2C, /* 001011 */ + 0x54, /* 010101 */ + 0x1C, /* 000111 */ + 0x04, /* 000001 */ + 0x00, /* 000000 */ // /* // * code=173, hex=0xAD, ascii="!-" // */ - // 0x10, /* 000100 */ - // 0x00, /* 000000 */ - // 0x10, /* 000100 */ - // 0x10, /* 000100 */ - // 0x38, /* 001110 */ - // 0x38, /* 001110 */ - // 0x10, /* 000100 */ - // 0x00, /* 000000 */ + 0x10, /* 000100 */ + 0x00, /* 000000 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x38, /* 001110 */ + 0x38, /* 001110 */ + 0x10, /* 000100 */ + 0x00, /* 000000 */ // /* // * code=174, hex=0xAE, ascii="!." // */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0x24, /* 001001 */ - // 0x48, /* 010010 */ - // 0x24, /* 001001 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x24, /* 001001 */ + 0x48, /* 010010 */ + 0x24, /* 001001 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ // /* // * code=175, hex=0xAF, ascii="!/" // */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0x48, /* 010010 */ - // 0x24, /* 001001 */ - // 0x48, /* 010010 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x48, /* 010010 */ + 0x24, /* 001001 */ + 0x48, /* 010010 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ // /* // * code=176, hex=0xB0, ascii="!0" // */ - // 0x54, /* 010101 */ - // 0x00, /* 000000 */ - // 0xA8, /* 101010 */ - // 0x00, /* 000000 */ - // 0x54, /* 010101 */ - // 0x00, /* 000000 */ - // 0xA8, /* 101010 */ - // 0x00, /* 000000 */ + 0x54, /* 010101 */ + 0x00, /* 000000 */ + 0xA8, /* 101010 */ + 0x00, /* 000000 */ + 0x54, /* 010101 */ + 0x00, /* 000000 */ + 0xA8, /* 101010 */ + 0x00, /* 000000 */ // /* // * code=177, hex=0xB1, ascii="!1" // */ - // 0x54, /* 010101 */ - // 0xA8, /* 101010 */ - // 0x54, /* 010101 */ - // 0xA8, /* 101010 */ - // 0x54, /* 010101 */ - // 0xA8, /* 101010 */ - // 0x54, /* 010101 */ - // 0xA8, /* 101010 */ + 0x54, /* 010101 */ + 0xA8, /* 101010 */ + 0x54, /* 010101 */ + 0xA8, /* 101010 */ + 0x54, /* 010101 */ + 0xA8, /* 101010 */ + 0x54, /* 010101 */ + 0xA8, /* 101010 */ // /* // * code=178, hex=0xB2, ascii="!2" // */ - // 0xA8, /* 101010 */ - // 0xFC, /* 111111 */ - // 0x54, /* 010101 */ - // 0xFC, /* 111111 */ - // 0xA8, /* 101010 */ - // 0xFC, /* 111111 */ - // 0x54, /* 010101 */ - // 0xFC, /* 111111 */ + 0xA8, /* 101010 */ + 0xFC, /* 111111 */ + 0x54, /* 010101 */ + 0xFC, /* 111111 */ + 0xA8, /* 101010 */ + 0xFC, /* 111111 */ + 0x54, /* 010101 */ + 0xFC, /* 111111 */ // /* // * code=179, hex=0xB3, ascii="!3" // */ - // 0x10, /* 000100 */ - // 0x10, /* 000100 */ - // 0x10, /* 000100 */ - // 0x10, /* 000100 */ - // 0x10, /* 000100 */ - // 0x10, /* 000100 */ - // 0x10, /* 000100 */ - // 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ // /* // * code=180, hex=0xB4, ascii="!4" // */ - // 0x10, /* 000100 */ - // 0x10, /* 000100 */ - // 0x10, /* 000100 */ - // 0xF0, /* 111100 */ - // 0x10, /* 000100 */ - // 0x10, /* 000100 */ - // 0x10, /* 000100 */ - // 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0xF0, /* 111100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ // /* // * code=181, hex=0xB5, ascii="!5" // */ - // 0x10, /* 000100 */ - // 0xF0, /* 111100 */ - // 0x10, /* 000100 */ - // 0xF0, /* 111100 */ - // 0x10, /* 000100 */ - // 0x10, /* 000100 */ - // 0x10, /* 000100 */ - // 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0xF0, /* 111100 */ + 0x10, /* 000100 */ + 0xF0, /* 111100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ // /* // * code=182, hex=0xB6, ascii="!6" // */ - // 0x50, /* 010100 */ - // 0x50, /* 010100 */ - // 0x50, /* 010100 */ - // 0xD0, /* 110100 */ - // 0x50, /* 010100 */ - // 0x50, /* 010100 */ - // 0x50, /* 010100 */ - // 0x50, /* 010100 */ + 0x50, /* 010100 */ + 0x50, /* 010100 */ + 0x50, /* 010100 */ + 0xD0, /* 110100 */ + 0x50, /* 010100 */ + 0x50, /* 010100 */ + 0x50, /* 010100 */ + 0x50, /* 010100 */ // /* // * code=183, hex=0xB7, ascii="!7" // */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0xF0, /* 111100 */ - // 0x50, /* 010100 */ - // 0x50, /* 010100 */ - // 0x50, /* 010100 */ - // 0x50, /* 010100 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0xF0, /* 111100 */ + 0x50, /* 010100 */ + 0x50, /* 010100 */ + 0x50, /* 010100 */ + 0x50, /* 010100 */ // /* // * code=184, hex=0xB8, ascii="!8" // */ - // 0x00, /* 000000 */ - // 0xF0, /* 111100 */ - // 0x10, /* 000100 */ - // 0xF0, /* 111100 */ - // 0x10, /* 000100 */ - // 0x10, /* 000100 */ - // 0x10, /* 000100 */ - // 0x10, /* 000100 */ + 0x00, /* 000000 */ + 0xF0, /* 111100 */ + 0x10, /* 000100 */ + 0xF0, /* 111100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ // /* // * code=185, hex=0xB9, ascii="!9" // */ - // 0x50, /* 010100 */ - // 0xD0, /* 110100 */ - // 0x10, /* 000100 */ - // 0xD0, /* 110100 */ - // 0x50, /* 010100 */ - // 0x50, /* 010100 */ - // 0x50, /* 010100 */ - // 0x50, /* 010100 */ + 0x50, /* 010100 */ + 0xD0, /* 110100 */ + 0x10, /* 000100 */ + 0xD0, /* 110100 */ + 0x50, /* 010100 */ + 0x50, /* 010100 */ + 0x50, /* 010100 */ + 0x50, /* 010100 */ // /* // * code=186, hex=0xBA, ascii="!:" // */ - // 0x50, /* 010100 */ - // 0x50, /* 010100 */ - // 0x50, /* 010100 */ - // 0x50, /* 010100 */ - // 0x50, /* 010100 */ - // 0x50, /* 010100 */ - // 0x50, /* 010100 */ - // 0x50, /* 010100 */ + 0x50, /* 010100 */ + 0x50, /* 010100 */ + 0x50, /* 010100 */ + 0x50, /* 010100 */ + 0x50, /* 010100 */ + 0x50, /* 010100 */ + 0x50, /* 010100 */ + 0x50, /* 010100 */ // /* // * code=187, hex=0xBB, ascii="!;" // */ - // 0x00, /* 000000 */ - // 0xF0, /* 111100 */ - // 0x10, /* 000100 */ - // 0xD0, /* 110100 */ - // 0x50, /* 010100 */ - // 0x50, /* 010100 */ - // 0x50, /* 010100 */ - // 0x50, /* 010100 */ + 0x00, /* 000000 */ + 0xF0, /* 111100 */ + 0x10, /* 000100 */ + 0xD0, /* 110100 */ + 0x50, /* 010100 */ + 0x50, /* 010100 */ + 0x50, /* 010100 */ + 0x50, /* 010100 */ // /* // * code=188, hex=0xBC, ascii="!<" // */ - // 0x50, /* 010100 */ - // 0xD0, /* 110100 */ - // 0x10, /* 000100 */ - // 0xF0, /* 111100 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ + 0x50, /* 010100 */ + 0xD0, /* 110100 */ + 0x10, /* 000100 */ + 0xF0, /* 111100 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ // /* // * code=189, hex=0xBD, ascii="!=" // */ - // 0x50, /* 010100 */ - // 0x50, /* 010100 */ - // 0x50, /* 010100 */ - // 0xF0, /* 111100 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ + 0x50, /* 010100 */ + 0x50, /* 010100 */ + 0x50, /* 010100 */ + 0xF0, /* 111100 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ // /* // * code=190, hex=0xBE, ascii="!>" // */ - // 0x10, /* 000100 */ - // 0xF0, /* 111100 */ - // 0x10, /* 000100 */ - // 0xF0, /* 111100 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ + 0x10, /* 000100 */ + 0xF0, /* 111100 */ + 0x10, /* 000100 */ + 0xF0, /* 111100 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ // /* // * code=191, hex=0xBF, ascii="!?" // */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0xF0, /* 111100 */ - // 0x10, /* 000100 */ - // 0x10, /* 000100 */ - // 0x10, /* 000100 */ - // 0x10, /* 000100 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0xF0, /* 111100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ // /* // * code=192, hex=0xC0, ascii="!@" // */ - // 0x10, /* 000100 */ - // 0x10, /* 000100 */ - // 0x10, /* 000100 */ - // 0x1C, /* 000111 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x1C, /* 000111 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ // /* // * code=193, hex=0xC1, ascii="!A" // */ - // 0x10, /* 000100 */ - // 0x10, /* 000100 */ - // 0x10, /* 000100 */ - // 0xFC, /* 111111 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0xFC, /* 111111 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ // /* // * code=194, hex=0xC2, ascii="!B" // */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0xFC, /* 111111 */ - // 0x10, /* 000100 */ - // 0x10, /* 000100 */ - // 0x10, /* 000100 */ - // 0x10, /* 000100 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0xFC, /* 111111 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ // /* // * code=195, hex=0xC3, ascii="!C" // */ - // 0x10, /* 000100 */ - // 0x10, /* 000100 */ - // 0x10, /* 000100 */ - // 0x1C, /* 000111 */ - // 0x10, /* 000100 */ - // 0x10, /* 000100 */ - // 0x10, /* 000100 */ - // 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x1C, /* 000111 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ // /* // * code=196, hex=0xC4, ascii="!D" // */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0xFC, /* 111111 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0xFC, /* 111111 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ // /* // * code=197, hex=0xC5, ascii="!E" // */ - // 0x10, /* 000100 */ - // 0x10, /* 000100 */ - // 0x10, /* 000100 */ - // 0xFC, /* 111111 */ - // 0x10, /* 000100 */ - // 0x10, /* 000100 */ - // 0x10, /* 000100 */ - // 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0xFC, /* 111111 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ // /* // * code=198, hex=0xC6, ascii="!F" // */ - // 0x10, /* 000100 */ - // 0x1C, /* 000111 */ - // 0x10, /* 000100 */ - // 0x1C, /* 000111 */ - // 0x10, /* 000100 */ - // 0x10, /* 000100 */ - // 0x10, /* 000100 */ - // 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x1C, /* 000111 */ + 0x10, /* 000100 */ + 0x1C, /* 000111 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ // /* // * code=199, hex=0xC7, ascii="!G" // */ - // 0x50, /* 010100 */ - // 0x50, /* 010100 */ - // 0x50, /* 010100 */ - // 0x5C, /* 010111 */ - // 0x50, /* 010100 */ - // 0x50, /* 010100 */ - // 0x50, /* 010100 */ - // 0x50, /* 010100 */ + 0x50, /* 010100 */ + 0x50, /* 010100 */ + 0x50, /* 010100 */ + 0x5C, /* 010111 */ + 0x50, /* 010100 */ + 0x50, /* 010100 */ + 0x50, /* 010100 */ + 0x50, /* 010100 */ // /* // * code=200, hex=0xC8, ascii="!H" // */ - // 0x50, /* 010100 */ - // 0x5C, /* 010111 */ - // 0x40, /* 010000 */ - // 0x7C, /* 011111 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ + 0x50, /* 010100 */ + 0x5C, /* 010111 */ + 0x40, /* 010000 */ + 0x7C, /* 011111 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ // /* // * code=201, hex=0xC9, ascii="!I" // */ - // 0x00, /* 000000 */ - // 0x7C, /* 011111 */ - // 0x40, /* 010000 */ - // 0x5C, /* 010111 */ - // 0x50, /* 010100 */ - // 0x50, /* 010100 */ - // 0x50, /* 010100 */ - // 0x50, /* 010100 */ + 0x00, /* 000000 */ + 0x7C, /* 011111 */ + 0x40, /* 010000 */ + 0x5C, /* 010111 */ + 0x50, /* 010100 */ + 0x50, /* 010100 */ + 0x50, /* 010100 */ + 0x50, /* 010100 */ // /* // * code=202, hex=0xCA, ascii="!J" // */ - // 0x50, /* 010100 */ - // 0xDC, /* 110111 */ - // 0x00, /* 000000 */ - // 0xFC, /* 111111 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ + 0x50, /* 010100 */ + 0xDC, /* 110111 */ + 0x00, /* 000000 */ + 0xFC, /* 111111 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ // /* // * code=203, hex=0xCB, ascii="!K" // */ - // 0x00, /* 000000 */ - // 0xFC, /* 111111 */ - // 0x00, /* 000000 */ - // 0xDC, /* 110111 */ - // 0x50, /* 010100 */ - // 0x50, /* 010100 */ - // 0x50, /* 010100 */ - // 0x50, /* 010100 */ + 0x00, /* 000000 */ + 0xFC, /* 111111 */ + 0x00, /* 000000 */ + 0xDC, /* 110111 */ + 0x50, /* 010100 */ + 0x50, /* 010100 */ + 0x50, /* 010100 */ + 0x50, /* 010100 */ // /* // * code=204, hex=0xCC, ascii="!L" // */ - // 0x50, /* 010100 */ - // 0x5C, /* 010111 */ - // 0x40, /* 010000 */ - // 0x5C, /* 010111 */ - // 0x50, /* 010100 */ - // 0x50, /* 010100 */ - // 0x50, /* 010100 */ - // 0x50, /* 010100 */ + 0x50, /* 010100 */ + 0x5C, /* 010111 */ + 0x40, /* 010000 */ + 0x5C, /* 010111 */ + 0x50, /* 010100 */ + 0x50, /* 010100 */ + 0x50, /* 010100 */ + 0x50, /* 010100 */ // /* // * code=205, hex=0xCD, ascii="!M" // */ - // 0x00, /* 000000 */ - // 0xFC, /* 111111 */ - // 0x00, /* 000000 */ - // 0xFC, /* 111111 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0xFC, /* 111111 */ + 0x00, /* 000000 */ + 0xFC, /* 111111 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ // /* // * code=206, hex=0xCE, ascii="!N" // */ - // 0x50, /* 010100 */ - // 0xDC, /* 110111 */ - // 0x00, /* 000000 */ - // 0xDC, /* 110111 */ - // 0x50, /* 010100 */ - // 0x50, /* 010100 */ - // 0x50, /* 010100 */ - // 0x50, /* 010100 */ + 0x50, /* 010100 */ + 0xDC, /* 110111 */ + 0x00, /* 000000 */ + 0xDC, /* 110111 */ + 0x50, /* 010100 */ + 0x50, /* 010100 */ + 0x50, /* 010100 */ + 0x50, /* 010100 */ // /* // * code=207, hex=0xCF, ascii="!O" // */ - // 0x10, /* 000100 */ - // 0xFC, /* 111111 */ - // 0x00, /* 000000 */ - // 0xFC, /* 111111 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ + 0x10, /* 000100 */ + 0xFC, /* 111111 */ + 0x00, /* 000000 */ + 0xFC, /* 111111 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ // /* // * code=208, hex=0xD0, ascii="!P" // */ - // 0x50, /* 010100 */ - // 0x50, /* 010100 */ - // 0x50, /* 010100 */ - // 0xFC, /* 111111 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ + 0x50, /* 010100 */ + 0x50, /* 010100 */ + 0x50, /* 010100 */ + 0xFC, /* 111111 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ // /* // * code=209, hex=0xD1, ascii="!Q" // */ - // 0x00, /* 000000 */ - // 0xFC, /* 111111 */ - // 0x00, /* 000000 */ - // 0xFC, /* 111111 */ - // 0x10, /* 000100 */ - // 0x10, /* 000100 */ - // 0x10, /* 000100 */ - // 0x10, /* 000100 */ + 0x00, /* 000000 */ + 0xFC, /* 111111 */ + 0x00, /* 000000 */ + 0xFC, /* 111111 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ // /* // * code=210, hex=0xD2, ascii="!R" // */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0xFC, /* 111111 */ - // 0x50, /* 010100 */ - // 0x50, /* 010100 */ - // 0x50, /* 010100 */ - // 0x50, /* 010100 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0xFC, /* 111111 */ + 0x50, /* 010100 */ + 0x50, /* 010100 */ + 0x50, /* 010100 */ + 0x50, /* 010100 */ // /* // * code=211, hex=0xD3, ascii="!S" // */ - // 0x50, /* 010100 */ - // 0x50, /* 010100 */ - // 0x50, /* 010100 */ - // 0x7C, /* 011111 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ + 0x50, /* 010100 */ + 0x50, /* 010100 */ + 0x50, /* 010100 */ + 0x7C, /* 011111 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ // /* // * code=212, hex=0xD4, ascii="!T" // */ - // 0x10, /* 000100 */ - // 0x1C, /* 000111 */ - // 0x10, /* 000100 */ - // 0x1C, /* 000111 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ + 0x10, /* 000100 */ + 0x1C, /* 000111 */ + 0x10, /* 000100 */ + 0x1C, /* 000111 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ // /* // * code=213, hex=0xD5, ascii="!U" // */ - // 0x00, /* 000000 */ - // 0x1C, /* 000111 */ - // 0x10, /* 000100 */ - // 0x1C, /* 000111 */ - // 0x10, /* 000100 */ - // 0x10, /* 000100 */ - // 0x10, /* 000100 */ - // 0x10, /* 000100 */ + 0x00, /* 000000 */ + 0x1C, /* 000111 */ + 0x10, /* 000100 */ + 0x1C, /* 000111 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ // /* // * code=214, hex=0xD6, ascii="!V" // */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0x7C, /* 011111 */ - // 0x50, /* 010100 */ - // 0x50, /* 010100 */ - // 0x50, /* 010100 */ - // 0x50, /* 010100 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x7C, /* 011111 */ + 0x50, /* 010100 */ + 0x50, /* 010100 */ + 0x50, /* 010100 */ + 0x50, /* 010100 */ // /* // * code=215, hex=0xD7, ascii="!W" // */ - // 0x50, /* 010100 */ - // 0x50, /* 010100 */ - // 0x50, /* 010100 */ - // 0xDC, /* 110111 */ - // 0x50, /* 010100 */ - // 0x50, /* 010100 */ - // 0x50, /* 010100 */ - // 0x50, /* 010100 */ + 0x50, /* 010100 */ + 0x50, /* 010100 */ + 0x50, /* 010100 */ + 0xDC, /* 110111 */ + 0x50, /* 010100 */ + 0x50, /* 010100 */ + 0x50, /* 010100 */ + 0x50, /* 010100 */ // /* // * code=216, hex=0xD8, ascii="!X" // */ - // 0x10, /* 000100 */ - // 0xFC, /* 111111 */ - // 0x00, /* 000000 */ - // 0xFC, /* 111111 */ - // 0x10, /* 000100 */ - // 0x10, /* 000100 */ - // 0x10, /* 000100 */ - // 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0xFC, /* 111111 */ + 0x00, /* 000000 */ + 0xFC, /* 111111 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ // /* // * code=217, hex=0xD9, ascii="!Y" // */ - // 0x10, /* 000100 */ - // 0x10, /* 000100 */ - // 0x10, /* 000100 */ - // 0xF0, /* 111100 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0xF0, /* 111100 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ // /* // * code=218, hex=0xDA, ascii="!Z" // */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0x1C, /* 000111 */ - // 0x10, /* 000100 */ - // 0x10, /* 000100 */ - // 0x10, /* 000100 */ - // 0x10, /* 000100 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x1C, /* 000111 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ // /* // * code=219, hex=0xDB, ascii="![" // */ - // 0xFC, /* 111111 */ - // 0xFC, /* 111111 */ - // 0xFC, /* 111111 */ - // 0xFC, /* 111111 */ - // 0xFC, /* 111111 */ - // 0xFC, /* 111111 */ - // 0xFC, /* 111111 */ - // 0xFC, /* 111111 */ + 0xFC, /* 111111 */ + 0xFC, /* 111111 */ + 0xFC, /* 111111 */ + 0xFC, /* 111111 */ + 0xFC, /* 111111 */ + 0xFC, /* 111111 */ + 0xFC, /* 111111 */ + 0xFC, /* 111111 */ // /* // * code=220, hex=0xDC, ascii="!\" // */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0xFC, /* 111111 */ - // 0xFC, /* 111111 */ - // 0xFC, /* 111111 */ - // 0xFC, /* 111111 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0xFC, /* 111111 */ + 0xFC, /* 111111 */ + 0xFC, /* 111111 */ + 0xFC, /* 111111 */ // /* // * code=221, hex=0xDD, ascii="!]" // */ - // 0xE0, /* 111000 */ - // 0xE0, /* 111000 */ - // 0xE0, /* 111000 */ - // 0xE0, /* 111000 */ - // 0xE0, /* 111000 */ - // 0xE0, /* 111000 */ - // 0xE0, /* 111000 */ - // 0xE0, /* 111000 */ + 0xE0, /* 111000 */ + 0xE0, /* 111000 */ + 0xE0, /* 111000 */ + 0xE0, /* 111000 */ + 0xE0, /* 111000 */ + 0xE0, /* 111000 */ + 0xE0, /* 111000 */ + 0xE0, /* 111000 */ // /* // * code=222, hex=0xDE, ascii="!^" // */ - // 0x1C, /* 000111 */ - // 0x1C, /* 000111 */ - // 0x1C, /* 000111 */ - // 0x1C, /* 000111 */ - // 0x1C, /* 000111 */ - // 0x1C, /* 000111 */ - // 0x1C, /* 000111 */ - // 0x1C, /* 000111 */ + 0x1C, /* 000111 */ + 0x1C, /* 000111 */ + 0x1C, /* 000111 */ + 0x1C, /* 000111 */ + 0x1C, /* 000111 */ + 0x1C, /* 000111 */ + 0x1C, /* 000111 */ + 0x1C, /* 000111 */ // /* // * code=223, hex=0xDF, ascii="!_" // */ - // 0xFC, /* 111111 */ - // 0xFC, /* 111111 */ - // 0xFC, /* 111111 */ - // 0xFC, /* 111111 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ + 0xFC, /* 111111 */ + 0xFC, /* 111111 */ + 0xFC, /* 111111 */ + 0xFC, /* 111111 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ // /* // * code=224, hex=0xE0, ascii="!`" // */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0x34, /* 001101 */ - // 0x48, /* 010010 */ - // 0x48, /* 010010 */ - // 0x34, /* 001101 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x34, /* 001101 */ + 0x48, /* 010010 */ + 0x48, /* 010010 */ + 0x34, /* 001101 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ // /* // * code=225, hex=0xE1, ascii="!a" // */ - // 0x00, /* 000000 */ - // 0x70, /* 011100 */ - // 0x48, /* 010010 */ - // 0x70, /* 011100 */ - // 0x48, /* 010010 */ - // 0x48, /* 010010 */ - // 0x70, /* 011100 */ - // 0x40, /* 010000 */ + 0x00, /* 000000 */ + 0x70, /* 011100 */ + 0x48, /* 010010 */ + 0x70, /* 011100 */ + 0x48, /* 010010 */ + 0x48, /* 010010 */ + 0x70, /* 011100 */ + 0x40, /* 010000 */ // /* // * code=226, hex=0xE2, ascii="!b" // */ - // 0x78, /* 011110 */ - // 0x48, /* 010010 */ - // 0x40, /* 010000 */ - // 0x40, /* 010000 */ - // 0x40, /* 010000 */ - // 0x40, /* 010000 */ - // 0x40, /* 010000 */ - // 0x00, /* 000000 */ + 0x78, /* 011110 */ + 0x48, /* 010010 */ + 0x40, /* 010000 */ + 0x40, /* 010000 */ + 0x40, /* 010000 */ + 0x40, /* 010000 */ + 0x40, /* 010000 */ + 0x00, /* 000000 */ // /* // * code=227, hex=0xE3, ascii="!c" // */ - // 0x00, /* 000000 */ - // 0x7C, /* 011111 */ - // 0x28, /* 001010 */ - // 0x28, /* 001010 */ - // 0x28, /* 001010 */ - // 0x28, /* 001010 */ - // 0x28, /* 001010 */ - // 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x7C, /* 011111 */ + 0x28, /* 001010 */ + 0x28, /* 001010 */ + 0x28, /* 001010 */ + 0x28, /* 001010 */ + 0x28, /* 001010 */ + 0x00, /* 000000 */ // /* // * code=228, hex=0xE4, ascii="!d" // */ - // 0x78, /* 011110 */ - // 0x48, /* 010010 */ - // 0x20, /* 001000 */ - // 0x10, /* 000100 */ - // 0x20, /* 001000 */ - // 0x48, /* 010010 */ - // 0x78, /* 011110 */ - // 0x00, /* 000000 */ + 0x78, /* 011110 */ + 0x48, /* 010010 */ + 0x20, /* 001000 */ + 0x10, /* 000100 */ + 0x20, /* 001000 */ + 0x48, /* 010010 */ + 0x78, /* 011110 */ + 0x00, /* 000000 */ // /* // * code=229, hex=0xE5, ascii="!e" // */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0x3C, /* 001111 */ - // 0x48, /* 010010 */ - // 0x48, /* 010010 */ - // 0x30, /* 001100 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x3C, /* 001111 */ + 0x48, /* 010010 */ + 0x48, /* 010010 */ + 0x30, /* 001100 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ // /* // * code=230, hex=0xE6, ascii="!f" // */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0x48, /* 010010 */ - // 0x48, /* 010010 */ - // 0x48, /* 010010 */ - // 0x70, /* 011100 */ - // 0x40, /* 010000 */ - // 0x40, /* 010000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x48, /* 010010 */ + 0x48, /* 010010 */ + 0x48, /* 010010 */ + 0x70, /* 011100 */ + 0x40, /* 010000 */ + 0x40, /* 010000 */ // /* // * code=231, hex=0xE7, ascii="!g" // */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0x28, /* 001010 */ - // 0x50, /* 010100 */ - // 0x10, /* 000100 */ - // 0x10, /* 000100 */ - // 0x10, /* 000100 */ - // 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x28, /* 001010 */ + 0x50, /* 010100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x00, /* 000000 */ // /* // * code=232, hex=0xE8, ascii="!h" // */ - // 0x38, /* 001110 */ - // 0x10, /* 000100 */ - // 0x38, /* 001110 */ - // 0x44, /* 010001 */ - // 0x38, /* 001110 */ - // 0x10, /* 000100 */ - // 0x38, /* 001110 */ - // 0x00, /* 000000 */ + 0x38, /* 001110 */ + 0x10, /* 000100 */ + 0x38, /* 001110 */ + 0x44, /* 010001 */ + 0x38, /* 001110 */ + 0x10, /* 000100 */ + 0x38, /* 001110 */ + 0x00, /* 000000 */ // /* // * code=233, hex=0xE9, ascii="!i" // */ - // 0x30, /* 001100 */ - // 0x48, /* 010010 */ - // 0x48, /* 010010 */ - // 0x78, /* 011110 */ - // 0x48, /* 010010 */ - // 0x48, /* 010010 */ - // 0x30, /* 001100 */ - // 0x00, /* 000000 */ + 0x30, /* 001100 */ + 0x48, /* 010010 */ + 0x48, /* 010010 */ + 0x78, /* 011110 */ + 0x48, /* 010010 */ + 0x48, /* 010010 */ + 0x30, /* 001100 */ + 0x00, /* 000000 */ // /* // * code=234, hex=0xEA, ascii="!j" // */ - // 0x00, /* 000000 */ - // 0x38, /* 001110 */ - // 0x44, /* 010001 */ - // 0x44, /* 010001 */ - // 0x28, /* 001010 */ - // 0x28, /* 001010 */ - // 0x6C, /* 011011 */ - // 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x38, /* 001110 */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x28, /* 001010 */ + 0x28, /* 001010 */ + 0x6C, /* 011011 */ + 0x00, /* 000000 */ // /* // * code=235, hex=0xEB, ascii="!k" // */ - // 0x30, /* 001100 */ - // 0x40, /* 010000 */ - // 0x20, /* 001000 */ - // 0x10, /* 000100 */ - // 0x38, /* 001110 */ - // 0x48, /* 010010 */ - // 0x30, /* 001100 */ - // 0x00, /* 000000 */ + 0x30, /* 001100 */ + 0x40, /* 010000 */ + 0x20, /* 001000 */ + 0x10, /* 000100 */ + 0x38, /* 001110 */ + 0x48, /* 010010 */ + 0x30, /* 001100 */ + 0x00, /* 000000 */ // /* // * code=236, hex=0xEC, ascii="!l" // */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0x28, /* 001010 */ - // 0x54, /* 010101 */ - // 0x54, /* 010101 */ - // 0x28, /* 001010 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x28, /* 001010 */ + 0x54, /* 010101 */ + 0x54, /* 010101 */ + 0x28, /* 001010 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ // /* // * code=237, hex=0xED, ascii="!m" // */ - // 0x00, /* 000000 */ - // 0x10, /* 000100 */ - // 0x38, /* 001110 */ - // 0x54, /* 010101 */ - // 0x54, /* 010101 */ - // 0x38, /* 001110 */ - // 0x10, /* 000100 */ - // 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x10, /* 000100 */ + 0x38, /* 001110 */ + 0x54, /* 010101 */ + 0x54, /* 010101 */ + 0x38, /* 001110 */ + 0x10, /* 000100 */ + 0x00, /* 000000 */ // /* // * code=238, hex=0xEE, ascii="!n" // */ - // 0x00, /* 000000 */ - // 0x38, /* 001110 */ - // 0x40, /* 010000 */ - // 0x78, /* 011110 */ - // 0x40, /* 010000 */ - // 0x38, /* 001110 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x38, /* 001110 */ + 0x40, /* 010000 */ + 0x78, /* 011110 */ + 0x40, /* 010000 */ + 0x38, /* 001110 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ // /* // * code=239, hex=0xEF, ascii="!o" // */ - // 0x00, /* 000000 */ - // 0x30, /* 001100 */ - // 0x48, /* 010010 */ - // 0x48, /* 010010 */ - // 0x48, /* 010010 */ - // 0x48, /* 010010 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x30, /* 001100 */ + 0x48, /* 010010 */ + 0x48, /* 010010 */ + 0x48, /* 010010 */ + 0x48, /* 010010 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ // /* // * code=240, hex=0xF0, ascii="!p" // */ - // 0x00, /* 000000 */ - // 0x78, /* 011110 */ - // 0x00, /* 000000 */ - // 0x78, /* 011110 */ - // 0x00, /* 000000 */ - // 0x78, /* 011110 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x78, /* 011110 */ + 0x00, /* 000000 */ + 0x78, /* 011110 */ + 0x00, /* 000000 */ + 0x78, /* 011110 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ // /* // * code=241, hex=0xF1, ascii="!q" // */ - // 0x00, /* 000000 */ - // 0x10, /* 000100 */ - // 0x38, /* 001110 */ - // 0x10, /* 000100 */ - // 0x00, /* 000000 */ - // 0x38, /* 001110 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x10, /* 000100 */ + 0x38, /* 001110 */ + 0x10, /* 000100 */ + 0x00, /* 000000 */ + 0x38, /* 001110 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ // /* // * code=242, hex=0xF2, ascii="!r" // */ - // 0x40, /* 010000 */ - // 0x30, /* 001100 */ - // 0x08, /* 000010 */ - // 0x30, /* 001100 */ - // 0x40, /* 010000 */ - // 0x00, /* 000000 */ - // 0x78, /* 011110 */ - // 0x00, /* 000000 */ + 0x40, /* 010000 */ + 0x30, /* 001100 */ + 0x08, /* 000010 */ + 0x30, /* 001100 */ + 0x40, /* 010000 */ + 0x00, /* 000000 */ + 0x78, /* 011110 */ + 0x00, /* 000000 */ // /* // * code=243, hex=0xF3, ascii="!s" // */ - // 0x08, /* 000010 */ - // 0x30, /* 001100 */ - // 0x40, /* 010000 */ - // 0x30, /* 001100 */ - // 0x08, /* 000010 */ - // 0x00, /* 000000 */ - // 0x78, /* 011110 */ - // 0x00, /* 000000 */ + 0x08, /* 000010 */ + 0x30, /* 001100 */ + 0x40, /* 010000 */ + 0x30, /* 001100 */ + 0x08, /* 000010 */ + 0x00, /* 000000 */ + 0x78, /* 011110 */ + 0x00, /* 000000 */ // /* // * code=244, hex=0xF4, ascii="!t" // */ - // 0x00, /* 000000 */ - // 0x08, /* 000010 */ - // 0x14, /* 000101 */ - // 0x10, /* 000100 */ - // 0x10, /* 000100 */ - // 0x10, /* 000100 */ - // 0x10, /* 000100 */ - // 0x10, /* 000100 */ + 0x00, /* 000000 */ + 0x08, /* 000010 */ + 0x14, /* 000101 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ // /* // * code=245, hex=0xF5, ascii="!u" // */ - // 0x10, /* 000100 */ - // 0x10, /* 000100 */ - // 0x10, /* 000100 */ - // 0x10, /* 000100 */ - // 0x10, /* 000100 */ - // 0x50, /* 010100 */ - // 0x20, /* 001000 */ - // 0x00, /* 000000 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x50, /* 010100 */ + 0x20, /* 001000 */ + 0x00, /* 000000 */ // /* // * code=246, hex=0xF6, ascii="!v" // */ - // 0x00, /* 000000 */ - // 0x10, /* 000100 */ - // 0x00, /* 000000 */ - // 0x7C, /* 011111 */ - // 0x00, /* 000000 */ - // 0x10, /* 000100 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x10, /* 000100 */ + 0x00, /* 000000 */ + 0x7C, /* 011111 */ + 0x00, /* 000000 */ + 0x10, /* 000100 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ // /* // * code=247, hex=0xF7, ascii="!w" // */ - // 0x00, /* 000000 */ - // 0x28, /* 001010 */ - // 0x50, /* 010100 */ - // 0x00, /* 000000 */ - // 0x28, /* 001010 */ - // 0x50, /* 010100 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x28, /* 001010 */ + 0x50, /* 010100 */ + 0x00, /* 000000 */ + 0x28, /* 001010 */ + 0x50, /* 010100 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ // /* // * code=248, hex=0xF8, ascii="!x" // */ - // 0x30, /* 001100 */ - // 0x48, /* 010010 */ - // 0x48, /* 010010 */ - // 0x30, /* 001100 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ + 0x30, /* 001100 */ + 0x48, /* 010010 */ + 0x48, /* 010010 */ + 0x30, /* 001100 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ // /* // * code=249, hex=0xF9, ascii="!y" // */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0x30, /* 001100 */ - // 0x30, /* 001100 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x30, /* 001100 */ + 0x30, /* 001100 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ // /* // * code=250, hex=0xFA, ascii="!z" // */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0x20, /* 001000 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x20, /* 001000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ // /* // * code=251, hex=0xFB, ascii="!{" // */ - // 0x00, /* 000000 */ - // 0x1C, /* 000111 */ - // 0x10, /* 000100 */ - // 0x10, /* 000100 */ - // 0x50, /* 010100 */ - // 0x50, /* 010100 */ - // 0x20, /* 001000 */ - // 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x1C, /* 000111 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x50, /* 010100 */ + 0x50, /* 010100 */ + 0x20, /* 001000 */ + 0x00, /* 000000 */ // /* // * code=252, hex=0xFC, ascii="!|" // */ - // 0x50, /* 010100 */ - // 0x28, /* 001010 */ - // 0x28, /* 001010 */ - // 0x28, /* 001010 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ + 0x50, /* 010100 */ + 0x28, /* 001010 */ + 0x28, /* 001010 */ + 0x28, /* 001010 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ // /* // * code=253, hex=0xFD, ascii="!}" // */ - // 0x60, /* 011000 */ - // 0x10, /* 000100 */ - // 0x20, /* 001000 */ - // 0x70, /* 011100 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ + 0x60, /* 011000 */ + 0x10, /* 000100 */ + 0x20, /* 001000 */ + 0x70, /* 011100 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ // /* // * code=254, hex=0xFE, ascii="!~" // */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0x78, /* 011110 */ - // 0x78, /* 011110 */ - // 0x78, /* 011110 */ - // 0x78, /* 011110 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x78, /* 011110 */ + 0x78, /* 011110 */ + 0x78, /* 011110 */ + 0x78, /* 011110 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ +#endif +#if 0 // skip 255 = NBSP // /* // * code=255, hex=0xFF, ascii="!^ź" // */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0x00, /* 000000 */ - // 0x00 /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00 /* 000000 */ +#endif }; diff --git a/wled00/src/font/console_font_7x9.h b/wled00/src/font/console_font_7x9.h index 30d98b09..a3673b6d 100644 --- a/wled00/src/font/console_font_7x9.h +++ b/wled00/src/font/console_font_7x9.h @@ -1,424 +1,437 @@ +#if !defined(WLED_ENABLE_FULL_FONTS) +constexpr uint16_t console_font_7x9_first = 32; // index 0 = code 32 "" +constexpr uint16_t console_font_7x9_last = 126; // last index = code 126 "~" +#else +constexpr uint16_t console_font_7x9_first = 1; // index 0 = code 1 "☺︎" +constexpr uint16_t console_font_7x9_last = 254; // last index = code 254 "■" +#endif + // font courtesy of https://github.com/idispatch/raster-fonts static const unsigned char console_font_7x9[] PROGMEM = { // code points 0-31 and 127-255 are commented out to save memory, they contain extra characters (CP437), // which could be used with an UTF-8 to CP437 conversion - +#if 0 // skip 0 // /* // * code=0, hex=0x00, ascii="^@" // */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ +#endif + +#if defined(WLED_ENABLE_FULL_FONTS) // /* // * code=1, hex=0x01, ascii="^A" // */ - // 0x38, /* 0011100 */ - // 0x44, /* 0100010 */ - // 0xAA, /* 1010101 */ - // 0xAA, /* 1010101 */ - // 0x82, /* 1000001 */ - // 0xAA, /* 1010101 */ - // 0x94, /* 1001010 */ - // 0x78, /* 0111100 */ - // 0x00, /* 0000000 */ + 0x38, /* 0011100 */ + 0x44, /* 0100010 */ + 0xAA, /* 1010101 */ + 0xAA, /* 1010101 */ + 0x82, /* 1000001 */ + 0xAA, /* 1010101 */ + 0x94, /* 1001010 */ + 0x78, /* 0111100 */ + 0x00, /* 0000000 */ // /* // * code=2, hex=0x02, ascii="^B" // */ - // 0x38, /* 0011100 */ - // 0x7C, /* 0111110 */ - // 0xD6, /* 1101011 */ - // 0xD6, /* 1101011 */ - // 0xFE, /* 1111111 */ - // 0xBA, /* 1011101 */ - // 0xC6, /* 1100011 */ - // 0x7C, /* 0111110 */ - // 0x00, /* 0000000 */ + 0x38, /* 0011100 */ + 0x7C, /* 0111110 */ + 0xD6, /* 1101011 */ + 0xD6, /* 1101011 */ + 0xFE, /* 1111111 */ + 0xBA, /* 1011101 */ + 0xC6, /* 1100011 */ + 0x7C, /* 0111110 */ + 0x00, /* 0000000 */ // /* // * code=3, hex=0x03, ascii="^C" // */ - // 0x00, /* 0000000 */ - // 0x6C, /* 0110110 */ - // 0xFE, /* 1111111 */ - // 0xFE, /* 1111111 */ - // 0xFE, /* 1111111 */ - // 0x7C, /* 0111110 */ - // 0x38, /* 0011100 */ - // 0x10, /* 0001000 */ - // 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x6C, /* 0110110 */ + 0xFE, /* 1111111 */ + 0xFE, /* 1111111 */ + 0xFE, /* 1111111 */ + 0x7C, /* 0111110 */ + 0x38, /* 0011100 */ + 0x10, /* 0001000 */ + 0x00, /* 0000000 */ // /* // * code=4, hex=0x04, ascii="^D" // */ - // 0x00, /* 0000000 */ - // 0x10, /* 0001000 */ - // 0x38, /* 0011100 */ - // 0x7C, /* 0111110 */ - // 0xFE, /* 1111111 */ - // 0x7C, /* 0111110 */ - // 0x38, /* 0011100 */ - // 0x10, /* 0001000 */ - // 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x10, /* 0001000 */ + 0x38, /* 0011100 */ + 0x7C, /* 0111110 */ + 0xFE, /* 1111111 */ + 0x7C, /* 0111110 */ + 0x38, /* 0011100 */ + 0x10, /* 0001000 */ + 0x00, /* 0000000 */ // /* // * code=5, hex=0x05, ascii="^E" // */ - // 0x38, /* 0011100 */ - // 0x38, /* 0011100 */ - // 0x10, /* 0001000 */ - // 0xD6, /* 1101011 */ - // 0xFE, /* 1111111 */ - // 0xD6, /* 1101011 */ - // 0x10, /* 0001000 */ - // 0x7C, /* 0111110 */ - // 0x00, /* 0000000 */ + 0x38, /* 0011100 */ + 0x38, /* 0011100 */ + 0x10, /* 0001000 */ + 0xD6, /* 1101011 */ + 0xFE, /* 1111111 */ + 0xD6, /* 1101011 */ + 0x10, /* 0001000 */ + 0x7C, /* 0111110 */ + 0x00, /* 0000000 */ // /* // * code=6, hex=0x06, ascii="^F" // */ - // 0x10, /* 0001000 */ - // 0x38, /* 0011100 */ - // 0x7C, /* 0111110 */ - // 0xFE, /* 1111111 */ - // 0xFE, /* 1111111 */ - // 0x54, /* 0101010 */ - // 0x10, /* 0001000 */ - // 0x38, /* 0011100 */ - // 0x00, /* 0000000 */ + 0x10, /* 0001000 */ + 0x38, /* 0011100 */ + 0x7C, /* 0111110 */ + 0xFE, /* 1111111 */ + 0xFE, /* 1111111 */ + 0x54, /* 0101010 */ + 0x10, /* 0001000 */ + 0x38, /* 0011100 */ + 0x00, /* 0000000 */ // /* // * code=7, hex=0x07, ascii="^G" // */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x18, /* 0001100 */ - // 0x3C, /* 0011110 */ - // 0x3C, /* 0011110 */ - // 0x18, /* 0001100 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x18, /* 0001100 */ + 0x3C, /* 0011110 */ + 0x3C, /* 0011110 */ + 0x18, /* 0001100 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ // /* // * code=8, hex=0x08, ascii="^H" // */ - // 0xFE, /* 1111111 */ - // 0xFE, /* 1111111 */ - // 0xE6, /* 1110011 */ - // 0xC2, /* 1100001 */ - // 0xC2, /* 1100001 */ - // 0xE6, /* 1110011 */ - // 0xFE, /* 1111111 */ - // 0xFE, /* 1111111 */ - // 0xFE, /* 1111111 */ + 0xFE, /* 1111111 */ + 0xFE, /* 1111111 */ + 0xE6, /* 1110011 */ + 0xC2, /* 1100001 */ + 0xC2, /* 1100001 */ + 0xE6, /* 1110011 */ + 0xFE, /* 1111111 */ + 0xFE, /* 1111111 */ + 0xFE, /* 1111111 */ // /* // * code=9, hex=0x09, ascii="^I" // */ - // 0x00, /* 0000000 */ - // 0x18, /* 0001100 */ - // 0x3C, /* 0011110 */ - // 0x66, /* 0110011 */ - // 0x66, /* 0110011 */ - // 0x3C, /* 0011110 */ - // 0x18, /* 0001100 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x18, /* 0001100 */ + 0x3C, /* 0011110 */ + 0x66, /* 0110011 */ + 0x66, /* 0110011 */ + 0x3C, /* 0011110 */ + 0x18, /* 0001100 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ // /* // * code=10, hex=0x0A, ascii="^J" // */ - // 0xFE, /* 1111111 */ - // 0xE6, /* 1110011 */ - // 0xC2, /* 1100001 */ - // 0x98, /* 1001100 */ - // 0x98, /* 1001100 */ - // 0xC2, /* 1100001 */ - // 0xE6, /* 1110011 */ - // 0xFE, /* 1111111 */ - // 0xFE, /* 1111111 */ + 0xFE, /* 1111111 */ + 0xE6, /* 1110011 */ + 0xC2, /* 1100001 */ + 0x98, /* 1001100 */ + 0x98, /* 1001100 */ + 0xC2, /* 1100001 */ + 0xE6, /* 1110011 */ + 0xFE, /* 1111111 */ + 0xFE, /* 1111111 */ // /* // * code=11, hex=0x0B, ascii="^K" // */ - // 0x0E, /* 0000111 */ - // 0x06, /* 0000011 */ - // 0x0A, /* 0000101 */ - // 0x18, /* 0001100 */ - // 0x3C, /* 0011110 */ - // 0x66, /* 0110011 */ - // 0x66, /* 0110011 */ - // 0x3C, /* 0011110 */ - // 0x00, /* 0000000 */ + 0x0E, /* 0000111 */ + 0x06, /* 0000011 */ + 0x0A, /* 0000101 */ + 0x18, /* 0001100 */ + 0x3C, /* 0011110 */ + 0x66, /* 0110011 */ + 0x66, /* 0110011 */ + 0x3C, /* 0011110 */ + 0x00, /* 0000000 */ // /* // * code=12, hex=0x0C, ascii="^L" // */ - // 0x3C, /* 0011110 */ - // 0x66, /* 0110011 */ - // 0x66, /* 0110011 */ - // 0x3C, /* 0011110 */ - // 0x18, /* 0001100 */ - // 0x3C, /* 0011110 */ - // 0x18, /* 0001100 */ - // 0x18, /* 0001100 */ - // 0x00, /* 0000000 */ + 0x3C, /* 0011110 */ + 0x66, /* 0110011 */ + 0x66, /* 0110011 */ + 0x3C, /* 0011110 */ + 0x18, /* 0001100 */ + 0x3C, /* 0011110 */ + 0x18, /* 0001100 */ + 0x18, /* 0001100 */ + 0x00, /* 0000000 */ // /* // * code=13, hex=0x0D, ascii="^M" // */ - // 0x00, /* 0000000 */ - // 0x38, /* 0011100 */ - // 0x2C, /* 0010110 */ - // 0x20, /* 0010000 */ - // 0x20, /* 0010000 */ - // 0x20, /* 0010000 */ - // 0x60, /* 0110000 */ - // 0x60, /* 0110000 */ - // 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x38, /* 0011100 */ + 0x2C, /* 0010110 */ + 0x20, /* 0010000 */ + 0x20, /* 0010000 */ + 0x20, /* 0010000 */ + 0x60, /* 0110000 */ + 0x60, /* 0110000 */ + 0x00, /* 0000000 */ // /* // * code=14, hex=0x0E, ascii="^N" // */ - // 0x00, /* 0000000 */ - // 0x3C, /* 0011110 */ - // 0x24, /* 0010010 */ - // 0x3C, /* 0011110 */ - // 0x24, /* 0010010 */ - // 0x24, /* 0010010 */ - // 0x6C, /* 0110110 */ - // 0x6C, /* 0110110 */ - // 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x3C, /* 0011110 */ + 0x24, /* 0010010 */ + 0x3C, /* 0011110 */ + 0x24, /* 0010010 */ + 0x24, /* 0010010 */ + 0x6C, /* 0110110 */ + 0x6C, /* 0110110 */ + 0x00, /* 0000000 */ // /* // * code=15, hex=0x0F, ascii="^O" // */ - // 0x92, /* 1001001 */ - // 0x54, /* 0101010 */ - // 0x38, /* 0011100 */ - // 0x28, /* 0010100 */ - // 0xEE, /* 1110111 */ - // 0x38, /* 0011100 */ - // 0x54, /* 0101010 */ - // 0x92, /* 1001001 */ - // 0x00, /* 0000000 */ + 0x92, /* 1001001 */ + 0x54, /* 0101010 */ + 0x38, /* 0011100 */ + 0x28, /* 0010100 */ + 0xEE, /* 1110111 */ + 0x38, /* 0011100 */ + 0x54, /* 0101010 */ + 0x92, /* 1001001 */ + 0x00, /* 0000000 */ // /* // * code=16, hex=0x10, ascii="^P" // */ - // 0x00, /* 0000000 */ - // 0x20, /* 0010000 */ - // 0x30, /* 0011000 */ - // 0x38, /* 0011100 */ - // 0x3C, /* 0011110 */ - // 0x38, /* 0011100 */ - // 0x30, /* 0011000 */ - // 0x20, /* 0010000 */ - // 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x20, /* 0010000 */ + 0x30, /* 0011000 */ + 0x38, /* 0011100 */ + 0x3C, /* 0011110 */ + 0x38, /* 0011100 */ + 0x30, /* 0011000 */ + 0x20, /* 0010000 */ + 0x00, /* 0000000 */ // /* // * code=17, hex=0x11, ascii="^Q" // */ - // 0x00, /* 0000000 */ - // 0x04, /* 0000010 */ - // 0x0C, /* 0000110 */ - // 0x1C, /* 0001110 */ - // 0x3C, /* 0011110 */ - // 0x1C, /* 0001110 */ - // 0x0C, /* 0000110 */ - // 0x04, /* 0000010 */ - // 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x04, /* 0000010 */ + 0x0C, /* 0000110 */ + 0x1C, /* 0001110 */ + 0x3C, /* 0011110 */ + 0x1C, /* 0001110 */ + 0x0C, /* 0000110 */ + 0x04, /* 0000010 */ + 0x00, /* 0000000 */ // /* // * code=18, hex=0x12, ascii="^R" // */ - // 0x10, /* 0001000 */ - // 0x38, /* 0011100 */ - // 0x7C, /* 0111110 */ - // 0x10, /* 0001000 */ - // 0x10, /* 0001000 */ - // 0x7C, /* 0111110 */ - // 0x38, /* 0011100 */ - // 0x10, /* 0001000 */ - // 0x00, /* 0000000 */ + 0x10, /* 0001000 */ + 0x38, /* 0011100 */ + 0x7C, /* 0111110 */ + 0x10, /* 0001000 */ + 0x10, /* 0001000 */ + 0x7C, /* 0111110 */ + 0x38, /* 0011100 */ + 0x10, /* 0001000 */ + 0x00, /* 0000000 */ // /* // * code=19, hex=0x13, ascii="^S" // */ - // 0x6C, /* 0110110 */ - // 0x6C, /* 0110110 */ - // 0x6C, /* 0110110 */ - // 0x6C, /* 0110110 */ - // 0x6C, /* 0110110 */ - // 0x00, /* 0000000 */ - // 0x6C, /* 0110110 */ - // 0x6C, /* 0110110 */ - // 0x00, /* 0000000 */ + 0x6C, /* 0110110 */ + 0x6C, /* 0110110 */ + 0x6C, /* 0110110 */ + 0x6C, /* 0110110 */ + 0x6C, /* 0110110 */ + 0x00, /* 0000000 */ + 0x6C, /* 0110110 */ + 0x6C, /* 0110110 */ + 0x00, /* 0000000 */ // /* // * code=20, hex=0x14, ascii="^T" // */ - // 0x00, /* 0000000 */ - // 0x3C, /* 0011110 */ - // 0x54, /* 0101010 */ - // 0x54, /* 0101010 */ - // 0x3C, /* 0011110 */ - // 0x14, /* 0001010 */ - // 0x14, /* 0001010 */ - // 0x14, /* 0001010 */ - // 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x3C, /* 0011110 */ + 0x54, /* 0101010 */ + 0x54, /* 0101010 */ + 0x3C, /* 0011110 */ + 0x14, /* 0001010 */ + 0x14, /* 0001010 */ + 0x14, /* 0001010 */ + 0x00, /* 0000000 */ // /* // * code=21, hex=0x15, ascii="^U" // */ - // 0x3C, /* 0011110 */ - // 0x66, /* 0110011 */ - // 0x60, /* 0110000 */ - // 0x3C, /* 0011110 */ - // 0x66, /* 0110011 */ - // 0x66, /* 0110011 */ - // 0x3C, /* 0011110 */ - // 0x06, /* 0000011 */ - // 0x66, /* 0110011 */ + 0x3C, /* 0011110 */ + 0x66, /* 0110011 */ + 0x60, /* 0110000 */ + 0x3C, /* 0011110 */ + 0x66, /* 0110011 */ + 0x66, /* 0110011 */ + 0x3C, /* 0011110 */ + 0x06, /* 0000011 */ + 0x66, /* 0110011 */ // /* // * code=22, hex=0x16, ascii="^V" // */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x7C, /* 0111110 */ - // 0x7C, /* 0111110 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x7C, /* 0111110 */ + 0x7C, /* 0111110 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ // /* // * code=23, hex=0x17, ascii="^W" // */ - // 0x10, /* 0001000 */ - // 0x38, /* 0011100 */ - // 0x7C, /* 0111110 */ - // 0x10, /* 0001000 */ - // 0x10, /* 0001000 */ - // 0x7C, /* 0111110 */ - // 0x38, /* 0011100 */ - // 0x10, /* 0001000 */ - // 0x7C, /* 0111110 */ + 0x10, /* 0001000 */ + 0x38, /* 0011100 */ + 0x7C, /* 0111110 */ + 0x10, /* 0001000 */ + 0x10, /* 0001000 */ + 0x7C, /* 0111110 */ + 0x38, /* 0011100 */ + 0x10, /* 0001000 */ + 0x7C, /* 0111110 */ // /* // * code=24, hex=0x18, ascii="^X" // */ - // 0x00, /* 0000000 */ - // 0x18, /* 0001100 */ - // 0x3C, /* 0011110 */ - // 0x5A, /* 0101101 */ - // 0x18, /* 0001100 */ - // 0x18, /* 0001100 */ - // 0x18, /* 0001100 */ - // 0x18, /* 0001100 */ - // 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x18, /* 0001100 */ + 0x3C, /* 0011110 */ + 0x5A, /* 0101101 */ + 0x18, /* 0001100 */ + 0x18, /* 0001100 */ + 0x18, /* 0001100 */ + 0x18, /* 0001100 */ + 0x00, /* 0000000 */ // /* // * code=25, hex=0x19, ascii="^Y" // */ - // 0x00, /* 0000000 */ - // 0x18, /* 0001100 */ - // 0x18, /* 0001100 */ - // 0x18, /* 0001100 */ - // 0x18, /* 0001100 */ - // 0x5A, /* 0101101 */ - // 0x3C, /* 0011110 */ - // 0x18, /* 0001100 */ - // 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x18, /* 0001100 */ + 0x18, /* 0001100 */ + 0x18, /* 0001100 */ + 0x18, /* 0001100 */ + 0x5A, /* 0101101 */ + 0x3C, /* 0011110 */ + 0x18, /* 0001100 */ + 0x00, /* 0000000 */ // /* // * code=26, hex=0x1A, ascii="^Z" // */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x18, /* 0001100 */ - // 0x0C, /* 0000110 */ - // 0x7E, /* 0111111 */ - // 0x0C, /* 0000110 */ - // 0x18, /* 0001100 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x18, /* 0001100 */ + 0x0C, /* 0000110 */ + 0x7E, /* 0111111 */ + 0x0C, /* 0000110 */ + 0x18, /* 0001100 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ // /* // * code=27, hex=0x1B, ascii="^[" // */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x18, /* 0001100 */ - // 0x30, /* 0011000 */ - // 0x7E, /* 0111111 */ - // 0x30, /* 0011000 */ - // 0x18, /* 0001100 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x18, /* 0001100 */ + 0x30, /* 0011000 */ + 0x7E, /* 0111111 */ + 0x30, /* 0011000 */ + 0x18, /* 0001100 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ // /* // * code=28, hex=0x1C, ascii="^\" // */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x60, /* 0110000 */ - // 0x60, /* 0110000 */ - // 0x7C, /* 0111110 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x60, /* 0110000 */ + 0x60, /* 0110000 */ + 0x7C, /* 0111110 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ // /* // * code=29, hex=0x1D, ascii="^]" // */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x24, /* 0010010 */ - // 0x66, /* 0110011 */ - // 0xFE, /* 1111111 */ - // 0x66, /* 0110011 */ - // 0x24, /* 0010010 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x24, /* 0010010 */ + 0x66, /* 0110011 */ + 0xFE, /* 1111111 */ + 0x66, /* 0110011 */ + 0x24, /* 0010010 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ // /* // * code=30, hex=0x1E, ascii="^^" // */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x10, /* 0001000 */ - // 0x38, /* 0011100 */ - // 0x7C, /* 0111110 */ - // 0xFE, /* 1111111 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x10, /* 0001000 */ + 0x38, /* 0011100 */ + 0x7C, /* 0111110 */ + 0xFE, /* 1111111 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ // /* // * code=31, hex=0x1F, ascii="^_" // */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0xFE, /* 1111111 */ - // 0x7C, /* 0111110 */ - // 0x38, /* 0011100 */ - // 0x10, /* 0001000 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0xFE, /* 1111111 */ + 0x7C, /* 0111110 */ + 0x38, /* 0011100 */ + 0x10, /* 0001000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + +#endif /* * code=32, hex=0x20, ascii=" " @@ -1655,1680 +1668,1686 @@ static const unsigned char console_font_7x9[] PROGMEM = { 0x00, /* 0000000 */ 0x00, /* 0000000 */ +#if defined(WLED_ENABLE_FULL_FONTS) + // /* // * code=127, hex=0x7F, ascii="^?" // */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x08, /* 0000100 */ - // 0x1C, /* 0001110 */ - // 0x36, /* 0011011 */ - // 0x62, /* 0110001 */ - // 0x7E, /* 0111111 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x08, /* 0000100 */ + 0x1C, /* 0001110 */ + 0x36, /* 0011011 */ + 0x62, /* 0110001 */ + 0x7E, /* 0111111 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ // /* // * code=128, hex=0x80, ascii="!^@" // */ - // 0x00, /* 0000000 */ - // 0x3C, /* 0011110 */ - // 0x66, /* 0110011 */ - // 0x60, /* 0110000 */ - // 0x60, /* 0110000 */ - // 0x60, /* 0110000 */ - // 0x66, /* 0110011 */ - // 0x3C, /* 0011110 */ - // 0x78, /* 0111100 */ + 0x00, /* 0000000 */ + 0x3C, /* 0011110 */ + 0x66, /* 0110011 */ + 0x60, /* 0110000 */ + 0x60, /* 0110000 */ + 0x60, /* 0110000 */ + 0x66, /* 0110011 */ + 0x3C, /* 0011110 */ + 0x78, /* 0111100 */ // /* // * code=129, hex=0x81, ascii="!^A" // */ - // 0x66, /* 0110011 */ - // 0x66, /* 0110011 */ - // 0x00, /* 0000000 */ - // 0x66, /* 0110011 */ - // 0x66, /* 0110011 */ - // 0x66, /* 0110011 */ - // 0x66, /* 0110011 */ - // 0x3A, /* 0011101 */ - // 0x00, /* 0000000 */ + 0x66, /* 0110011 */ + 0x66, /* 0110011 */ + 0x00, /* 0000000 */ + 0x66, /* 0110011 */ + 0x66, /* 0110011 */ + 0x66, /* 0110011 */ + 0x66, /* 0110011 */ + 0x3A, /* 0011101 */ + 0x00, /* 0000000 */ // /* // * code=130, hex=0x82, ascii="!^B" // */ - // 0x0C, /* 0000110 */ - // 0x18, /* 0001100 */ - // 0x00, /* 0000000 */ - // 0x3E, /* 0011111 */ - // 0x62, /* 0110001 */ - // 0x7E, /* 0111111 */ - // 0x60, /* 0110000 */ - // 0x3E, /* 0011111 */ - // 0x00, /* 0000000 */ + 0x0C, /* 0000110 */ + 0x18, /* 0001100 */ + 0x00, /* 0000000 */ + 0x3E, /* 0011111 */ + 0x62, /* 0110001 */ + 0x7E, /* 0111111 */ + 0x60, /* 0110000 */ + 0x3E, /* 0011111 */ + 0x00, /* 0000000 */ // /* // * code=131, hex=0x83, ascii="!^C" // */ - // 0x1C, /* 0001110 */ - // 0x36, /* 0011011 */ - // 0x00, /* 0000000 */ - // 0x3C, /* 0011110 */ - // 0x06, /* 0000011 */ - // 0x3E, /* 0011111 */ - // 0x66, /* 0110011 */ - // 0x3E, /* 0011111 */ - // 0x00, /* 0000000 */ + 0x1C, /* 0001110 */ + 0x36, /* 0011011 */ + 0x00, /* 0000000 */ + 0x3C, /* 0011110 */ + 0x06, /* 0000011 */ + 0x3E, /* 0011111 */ + 0x66, /* 0110011 */ + 0x3E, /* 0011111 */ + 0x00, /* 0000000 */ // /* // * code=132, hex=0x84, ascii="!^D" // */ - // 0x36, /* 0011011 */ - // 0x36, /* 0011011 */ - // 0x00, /* 0000000 */ - // 0x3C, /* 0011110 */ - // 0x06, /* 0000011 */ - // 0x3E, /* 0011111 */ - // 0x66, /* 0110011 */ - // 0x3E, /* 0011111 */ - // 0x00, /* 0000000 */ + 0x36, /* 0011011 */ + 0x36, /* 0011011 */ + 0x00, /* 0000000 */ + 0x3C, /* 0011110 */ + 0x06, /* 0000011 */ + 0x3E, /* 0011111 */ + 0x66, /* 0110011 */ + 0x3E, /* 0011111 */ + 0x00, /* 0000000 */ // /* // * code=133, hex=0x85, ascii="!^E" // */ - // 0x18, /* 0001100 */ - // 0x0C, /* 0000110 */ - // 0x00, /* 0000000 */ - // 0x3C, /* 0011110 */ - // 0x06, /* 0000011 */ - // 0x3E, /* 0011111 */ - // 0x66, /* 0110011 */ - // 0x3A, /* 0011101 */ - // 0x00, /* 0000000 */ + 0x18, /* 0001100 */ + 0x0C, /* 0000110 */ + 0x00, /* 0000000 */ + 0x3C, /* 0011110 */ + 0x06, /* 0000011 */ + 0x3E, /* 0011111 */ + 0x66, /* 0110011 */ + 0x3A, /* 0011101 */ + 0x00, /* 0000000 */ // /* // * code=134, hex=0x86, ascii="!^F" // */ - // 0x1C, /* 0001110 */ - // 0x14, /* 0001010 */ - // 0x00, /* 0000000 */ - // 0x3C, /* 0011110 */ - // 0x06, /* 0000011 */ - // 0x3E, /* 0011111 */ - // 0x66, /* 0110011 */ - // 0x3A, /* 0011101 */ - // 0x00, /* 0000000 */ + 0x1C, /* 0001110 */ + 0x14, /* 0001010 */ + 0x00, /* 0000000 */ + 0x3C, /* 0011110 */ + 0x06, /* 0000011 */ + 0x3E, /* 0011111 */ + 0x66, /* 0110011 */ + 0x3A, /* 0011101 */ + 0x00, /* 0000000 */ // /* // * code=135, hex=0x87, ascii="!^G" // */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x1C, /* 0001110 */ - // 0x36, /* 0011011 */ - // 0x60, /* 0110000 */ - // 0x36, /* 0011011 */ - // 0x1C, /* 0001110 */ - // 0x78, /* 0111100 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x1C, /* 0001110 */ + 0x36, /* 0011011 */ + 0x60, /* 0110000 */ + 0x36, /* 0011011 */ + 0x1C, /* 0001110 */ + 0x78, /* 0111100 */ // /* // * code=136, hex=0x88, ascii="!^H" // */ - // 0x08, /* 0000100 */ - // 0x1C, /* 0001110 */ - // 0x00, /* 0000000 */ - // 0x3C, /* 0011110 */ - // 0x66, /* 0110011 */ - // 0x7E, /* 0111111 */ - // 0x60, /* 0110000 */ - // 0x3E, /* 0011111 */ - // 0x00, /* 0000000 */ + 0x08, /* 0000100 */ + 0x1C, /* 0001110 */ + 0x00, /* 0000000 */ + 0x3C, /* 0011110 */ + 0x66, /* 0110011 */ + 0x7E, /* 0111111 */ + 0x60, /* 0110000 */ + 0x3E, /* 0011111 */ + 0x00, /* 0000000 */ // /* // * code=137, hex=0x89, ascii="!^I" // */ - // 0x66, /* 0110011 */ - // 0x66, /* 0110011 */ - // 0x00, /* 0000000 */ - // 0x3C, /* 0011110 */ - // 0x66, /* 0110011 */ - // 0x7E, /* 0111111 */ - // 0x60, /* 0110000 */ - // 0x3E, /* 0011111 */ - // 0x00, /* 0000000 */ + 0x66, /* 0110011 */ + 0x66, /* 0110011 */ + 0x00, /* 0000000 */ + 0x3C, /* 0011110 */ + 0x66, /* 0110011 */ + 0x7E, /* 0111111 */ + 0x60, /* 0110000 */ + 0x3E, /* 0011111 */ + 0x00, /* 0000000 */ // /* // * code=138, hex=0x8A, ascii="!^J" // */ - // 0x18, /* 0001100 */ - // 0x0C, /* 0000110 */ - // 0x00, /* 0000000 */ - // 0x3C, /* 0011110 */ - // 0x66, /* 0110011 */ - // 0x7E, /* 0111111 */ - // 0x60, /* 0110000 */ - // 0x3E, /* 0011111 */ - // 0x00, /* 0000000 */ + 0x18, /* 0001100 */ + 0x0C, /* 0000110 */ + 0x00, /* 0000000 */ + 0x3C, /* 0011110 */ + 0x66, /* 0110011 */ + 0x7E, /* 0111111 */ + 0x60, /* 0110000 */ + 0x3E, /* 0011111 */ + 0x00, /* 0000000 */ // /* // * code=139, hex=0x8B, ascii="!^K" // */ - // 0x66, /* 0110011 */ - // 0x66, /* 0110011 */ - // 0x00, /* 0000000 */ - // 0x38, /* 0011100 */ - // 0x18, /* 0001100 */ - // 0x18, /* 0001100 */ - // 0x18, /* 0001100 */ - // 0x3C, /* 0011110 */ - // 0x00, /* 0000000 */ + 0x66, /* 0110011 */ + 0x66, /* 0110011 */ + 0x00, /* 0000000 */ + 0x38, /* 0011100 */ + 0x18, /* 0001100 */ + 0x18, /* 0001100 */ + 0x18, /* 0001100 */ + 0x3C, /* 0011110 */ + 0x00, /* 0000000 */ // /* // * code=140, hex=0x8C, ascii="!^L" // */ - // 0x10, /* 0001000 */ - // 0x38, /* 0011100 */ - // 0x00, /* 0000000 */ - // 0x38, /* 0011100 */ - // 0x18, /* 0001100 */ - // 0x18, /* 0001100 */ - // 0x18, /* 0001100 */ - // 0x3C, /* 0011110 */ - // 0x00, /* 0000000 */ + 0x10, /* 0001000 */ + 0x38, /* 0011100 */ + 0x00, /* 0000000 */ + 0x38, /* 0011100 */ + 0x18, /* 0001100 */ + 0x18, /* 0001100 */ + 0x18, /* 0001100 */ + 0x3C, /* 0011110 */ + 0x00, /* 0000000 */ // /* // * code=141, hex=0x8D, ascii="!^M" // */ - // 0x30, /* 0011000 */ - // 0x18, /* 0001100 */ - // 0x00, /* 0000000 */ - // 0x38, /* 0011100 */ - // 0x18, /* 0001100 */ - // 0x18, /* 0001100 */ - // 0x18, /* 0001100 */ - // 0x3C, /* 0011110 */ - // 0x00, /* 0000000 */ + 0x30, /* 0011000 */ + 0x18, /* 0001100 */ + 0x00, /* 0000000 */ + 0x38, /* 0011100 */ + 0x18, /* 0001100 */ + 0x18, /* 0001100 */ + 0x18, /* 0001100 */ + 0x3C, /* 0011110 */ + 0x00, /* 0000000 */ // /* // * code=142, hex=0x8E, ascii="!^N" // */ - // 0xC6, /* 1100011 */ - // 0x10, /* 0001000 */ - // 0x38, /* 0011100 */ - // 0x28, /* 0010100 */ - // 0x6C, /* 0110110 */ - // 0x7C, /* 0111110 */ - // 0xC6, /* 1100011 */ - // 0xC6, /* 1100011 */ - // 0x00, /* 0000000 */ + 0xC6, /* 1100011 */ + 0x10, /* 0001000 */ + 0x38, /* 0011100 */ + 0x28, /* 0010100 */ + 0x6C, /* 0110110 */ + 0x7C, /* 0111110 */ + 0xC6, /* 1100011 */ + 0xC6, /* 1100011 */ + 0x00, /* 0000000 */ // /* // * code=143, hex=0x8F, ascii="!^O" // */ - // 0x38, /* 0011100 */ - // 0x28, /* 0010100 */ - // 0x38, /* 0011100 */ - // 0x28, /* 0010100 */ - // 0x6C, /* 0110110 */ - // 0x7C, /* 0111110 */ - // 0xC6, /* 1100011 */ - // 0xC6, /* 1100011 */ - // 0x00, /* 0000000 */ + 0x38, /* 0011100 */ + 0x28, /* 0010100 */ + 0x38, /* 0011100 */ + 0x28, /* 0010100 */ + 0x6C, /* 0110110 */ + 0x7C, /* 0111110 */ + 0xC6, /* 1100011 */ + 0xC6, /* 1100011 */ + 0x00, /* 0000000 */ // /* // * code=144, hex=0x90, ascii="!^P" // */ - // 0x1C, /* 0001110 */ - // 0x30, /* 0011000 */ - // 0x7E, /* 0111111 */ - // 0x60, /* 0110000 */ - // 0x7C, /* 0111110 */ - // 0x60, /* 0110000 */ - // 0x60, /* 0110000 */ - // 0x7E, /* 0111111 */ - // 0x00, /* 0000000 */ + 0x1C, /* 0001110 */ + 0x30, /* 0011000 */ + 0x7E, /* 0111111 */ + 0x60, /* 0110000 */ + 0x7C, /* 0111110 */ + 0x60, /* 0110000 */ + 0x60, /* 0110000 */ + 0x7E, /* 0111111 */ + 0x00, /* 0000000 */ // /* // * code=145, hex=0x91, ascii="!^Q" // */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x7C, /* 0111110 */ - // 0x1A, /* 0001101 */ - // 0x7E, /* 0111111 */ - // 0xD8, /* 1101100 */ - // 0x7E, /* 0111111 */ - // 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x7C, /* 0111110 */ + 0x1A, /* 0001101 */ + 0x7E, /* 0111111 */ + 0xD8, /* 1101100 */ + 0x7E, /* 0111111 */ + 0x00, /* 0000000 */ // /* // * code=146, hex=0x92, ascii="!^R" // */ - // 0x00, /* 0000000 */ - // 0x1E, /* 0001111 */ - // 0x38, /* 0011100 */ - // 0x58, /* 0101100 */ - // 0x5E, /* 0101111 */ - // 0xF8, /* 1111100 */ - // 0xD8, /* 1101100 */ - // 0xDE, /* 1101111 */ - // 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x1E, /* 0001111 */ + 0x38, /* 0011100 */ + 0x58, /* 0101100 */ + 0x5E, /* 0101111 */ + 0xF8, /* 1111100 */ + 0xD8, /* 1101100 */ + 0xDE, /* 1101111 */ + 0x00, /* 0000000 */ // /* // * code=147, hex=0x93, ascii="!^S" // */ - // 0x10, /* 0001000 */ - // 0x38, /* 0011100 */ - // 0x00, /* 0000000 */ - // 0x3C, /* 0011110 */ - // 0x66, /* 0110011 */ - // 0x66, /* 0110011 */ - // 0x66, /* 0110011 */ - // 0x3C, /* 0011110 */ - // 0x00, /* 0000000 */ + 0x10, /* 0001000 */ + 0x38, /* 0011100 */ + 0x00, /* 0000000 */ + 0x3C, /* 0011110 */ + 0x66, /* 0110011 */ + 0x66, /* 0110011 */ + 0x66, /* 0110011 */ + 0x3C, /* 0011110 */ + 0x00, /* 0000000 */ // /* // * code=148, hex=0x94, ascii="!^T" // */ - // 0x66, /* 0110011 */ - // 0x66, /* 0110011 */ - // 0x00, /* 0000000 */ - // 0x3C, /* 0011110 */ - // 0x66, /* 0110011 */ - // 0x66, /* 0110011 */ - // 0x66, /* 0110011 */ - // 0x3C, /* 0011110 */ - // 0x00, /* 0000000 */ + 0x66, /* 0110011 */ + 0x66, /* 0110011 */ + 0x00, /* 0000000 */ + 0x3C, /* 0011110 */ + 0x66, /* 0110011 */ + 0x66, /* 0110011 */ + 0x66, /* 0110011 */ + 0x3C, /* 0011110 */ + 0x00, /* 0000000 */ // /* // * code=149, hex=0x95, ascii="!^U" // */ - // 0x18, /* 0001100 */ - // 0x0C, /* 0000110 */ - // 0x00, /* 0000000 */ - // 0x3C, /* 0011110 */ - // 0x66, /* 0110011 */ - // 0x66, /* 0110011 */ - // 0x66, /* 0110011 */ - // 0x3C, /* 0011110 */ - // 0x00, /* 0000000 */ + 0x18, /* 0001100 */ + 0x0C, /* 0000110 */ + 0x00, /* 0000000 */ + 0x3C, /* 0011110 */ + 0x66, /* 0110011 */ + 0x66, /* 0110011 */ + 0x66, /* 0110011 */ + 0x3C, /* 0011110 */ + 0x00, /* 0000000 */ // /* // * code=150, hex=0x96, ascii="!^V" // */ - // 0x08, /* 0000100 */ - // 0x1C, /* 0001110 */ - // 0x00, /* 0000000 */ - // 0x66, /* 0110011 */ - // 0x66, /* 0110011 */ - // 0x66, /* 0110011 */ - // 0x66, /* 0110011 */ - // 0x3A, /* 0011101 */ - // 0x00, /* 0000000 */ + 0x08, /* 0000100 */ + 0x1C, /* 0001110 */ + 0x00, /* 0000000 */ + 0x66, /* 0110011 */ + 0x66, /* 0110011 */ + 0x66, /* 0110011 */ + 0x66, /* 0110011 */ + 0x3A, /* 0011101 */ + 0x00, /* 0000000 */ // /* // * code=151, hex=0x97, ascii="!^W" // */ - // 0x18, /* 0001100 */ - // 0x0C, /* 0000110 */ - // 0x00, /* 0000000 */ - // 0x66, /* 0110011 */ - // 0x66, /* 0110011 */ - // 0x66, /* 0110011 */ - // 0x66, /* 0110011 */ - // 0x3A, /* 0011101 */ - // 0x00, /* 0000000 */ + 0x18, /* 0001100 */ + 0x0C, /* 0000110 */ + 0x00, /* 0000000 */ + 0x66, /* 0110011 */ + 0x66, /* 0110011 */ + 0x66, /* 0110011 */ + 0x66, /* 0110011 */ + 0x3A, /* 0011101 */ + 0x00, /* 0000000 */ // /* // * code=152, hex=0x98, ascii="!^X" // */ - // 0x66, /* 0110011 */ - // 0x66, /* 0110011 */ - // 0x00, /* 0000000 */ - // 0x66, /* 0110011 */ - // 0x66, /* 0110011 */ - // 0x36, /* 0011011 */ - // 0x1C, /* 0001110 */ - // 0x6C, /* 0110110 */ - // 0x38, /* 0011100 */ + 0x66, /* 0110011 */ + 0x66, /* 0110011 */ + 0x00, /* 0000000 */ + 0x66, /* 0110011 */ + 0x66, /* 0110011 */ + 0x36, /* 0011011 */ + 0x1C, /* 0001110 */ + 0x6C, /* 0110110 */ + 0x38, /* 0011100 */ // /* // * code=153, hex=0x99, ascii="!^Y" // */ - // 0x66, /* 0110011 */ - // 0x00, /* 0000000 */ - // 0x3C, /* 0011110 */ - // 0x66, /* 0110011 */ - // 0x66, /* 0110011 */ - // 0x66, /* 0110011 */ - // 0x66, /* 0110011 */ - // 0x3C, /* 0011110 */ - // 0x00, /* 0000000 */ + 0x66, /* 0110011 */ + 0x00, /* 0000000 */ + 0x3C, /* 0011110 */ + 0x66, /* 0110011 */ + 0x66, /* 0110011 */ + 0x66, /* 0110011 */ + 0x66, /* 0110011 */ + 0x3C, /* 0011110 */ + 0x00, /* 0000000 */ // /* // * code=154, hex=0x9A, ascii="!^Z" // */ - // 0x66, /* 0110011 */ - // 0x00, /* 0000000 */ - // 0x66, /* 0110011 */ - // 0x66, /* 0110011 */ - // 0x66, /* 0110011 */ - // 0x66, /* 0110011 */ - // 0x66, /* 0110011 */ - // 0x3C, /* 0011110 */ - // 0x00, /* 0000000 */ + 0x66, /* 0110011 */ + 0x00, /* 0000000 */ + 0x66, /* 0110011 */ + 0x66, /* 0110011 */ + 0x66, /* 0110011 */ + 0x66, /* 0110011 */ + 0x66, /* 0110011 */ + 0x3C, /* 0011110 */ + 0x00, /* 0000000 */ // /* // * code=155, hex=0x9B, ascii="!^[" // */ - // 0x08, /* 0000100 */ - // 0x08, /* 0000100 */ - // 0x3C, /* 0011110 */ - // 0x60, /* 0110000 */ - // 0x60, /* 0110000 */ - // 0x3C, /* 0011110 */ - // 0x10, /* 0001000 */ - // 0x10, /* 0001000 */ - // 0x00, /* 0000000 */ + 0x08, /* 0000100 */ + 0x08, /* 0000100 */ + 0x3C, /* 0011110 */ + 0x60, /* 0110000 */ + 0x60, /* 0110000 */ + 0x3C, /* 0011110 */ + 0x10, /* 0001000 */ + 0x10, /* 0001000 */ + 0x00, /* 0000000 */ // /* // * code=156, hex=0x9C, ascii="!^\" // */ - // 0x1C, /* 0001110 */ - // 0x36, /* 0011011 */ - // 0x30, /* 0011000 */ - // 0x30, /* 0011000 */ - // 0x7C, /* 0111110 */ - // 0x30, /* 0011000 */ - // 0x3C, /* 0011110 */ - // 0x66, /* 0110011 */ - // 0x00, /* 0000000 */ + 0x1C, /* 0001110 */ + 0x36, /* 0011011 */ + 0x30, /* 0011000 */ + 0x30, /* 0011000 */ + 0x7C, /* 0111110 */ + 0x30, /* 0011000 */ + 0x3C, /* 0011110 */ + 0x66, /* 0110011 */ + 0x00, /* 0000000 */ // /* // * code=157, hex=0x9D, ascii="!^]" // */ - // 0x66, /* 0110011 */ - // 0x66, /* 0110011 */ - // 0x3C, /* 0011110 */ - // 0x18, /* 0001100 */ - // 0x7E, /* 0111111 */ - // 0x18, /* 0001100 */ - // 0x7E, /* 0111111 */ - // 0x18, /* 0001100 */ - // 0x00, /* 0000000 */ + 0x66, /* 0110011 */ + 0x66, /* 0110011 */ + 0x3C, /* 0011110 */ + 0x18, /* 0001100 */ + 0x7E, /* 0111111 */ + 0x18, /* 0001100 */ + 0x7E, /* 0111111 */ + 0x18, /* 0001100 */ + 0x00, /* 0000000 */ // /* // * code=158, hex=0x9E, ascii="!^^" // */ - // 0xE0, /* 1110000 */ - // 0xD0, /* 1101000 */ - // 0xD0, /* 1101000 */ - // 0xF4, /* 1111010 */ - // 0xCC, /* 1100110 */ - // 0xDE, /* 1101111 */ - // 0xCC, /* 1100110 */ - // 0x06, /* 0000011 */ - // 0x00, /* 0000000 */ + 0xE0, /* 1110000 */ + 0xD0, /* 1101000 */ + 0xD0, /* 1101000 */ + 0xF4, /* 1111010 */ + 0xCC, /* 1100110 */ + 0xDE, /* 1101111 */ + 0xCC, /* 1100110 */ + 0x06, /* 0000011 */ + 0x00, /* 0000000 */ // /* // * code=159, hex=0x9F, ascii="!^_" // */ - // 0x0E, /* 0000111 */ - // 0x18, /* 0001100 */ - // 0x18, /* 0001100 */ - // 0x18, /* 0001100 */ - // 0x7E, /* 0111111 */ - // 0x18, /* 0001100 */ - // 0x18, /* 0001100 */ - // 0x18, /* 0001100 */ - // 0x70, /* 0111000 */ + 0x0E, /* 0000111 */ + 0x18, /* 0001100 */ + 0x18, /* 0001100 */ + 0x18, /* 0001100 */ + 0x7E, /* 0111111 */ + 0x18, /* 0001100 */ + 0x18, /* 0001100 */ + 0x18, /* 0001100 */ + 0x70, /* 0111000 */ // /* // * code=160, hex=0xA0, ascii="! " // */ - // 0x06, /* 0000011 */ - // 0x0C, /* 0000110 */ - // 0x00, /* 0000000 */ - // 0x3C, /* 0011110 */ - // 0x06, /* 0000011 */ - // 0x3E, /* 0011111 */ - // 0x66, /* 0110011 */ - // 0x3A, /* 0011101 */ - // 0x00, /* 0000000 */ + 0x06, /* 0000011 */ + 0x0C, /* 0000110 */ + 0x00, /* 0000000 */ + 0x3C, /* 0011110 */ + 0x06, /* 0000011 */ + 0x3E, /* 0011111 */ + 0x66, /* 0110011 */ + 0x3A, /* 0011101 */ + 0x00, /* 0000000 */ // /* // * code=161, hex=0xA1, ascii="!!" // */ - // 0x0C, /* 0000110 */ - // 0x18, /* 0001100 */ - // 0x00, /* 0000000 */ - // 0x38, /* 0011100 */ - // 0x18, /* 0001100 */ - // 0x18, /* 0001100 */ - // 0x18, /* 0001100 */ - // 0x3C, /* 0011110 */ - // 0x00, /* 0000000 */ + 0x0C, /* 0000110 */ + 0x18, /* 0001100 */ + 0x00, /* 0000000 */ + 0x38, /* 0011100 */ + 0x18, /* 0001100 */ + 0x18, /* 0001100 */ + 0x18, /* 0001100 */ + 0x3C, /* 0011110 */ + 0x00, /* 0000000 */ // /* // * code=162, hex=0xA2, ascii="!"" // */ - // 0x0C, /* 0000110 */ - // 0x18, /* 0001100 */ - // 0x00, /* 0000000 */ - // 0x3C, /* 0011110 */ - // 0x66, /* 0110011 */ - // 0x66, /* 0110011 */ - // 0x66, /* 0110011 */ - // 0x3C, /* 0011110 */ - // 0x00, /* 0000000 */ + 0x0C, /* 0000110 */ + 0x18, /* 0001100 */ + 0x00, /* 0000000 */ + 0x3C, /* 0011110 */ + 0x66, /* 0110011 */ + 0x66, /* 0110011 */ + 0x66, /* 0110011 */ + 0x3C, /* 0011110 */ + 0x00, /* 0000000 */ // /* // * code=163, hex=0xA3, ascii="!#" // */ - // 0x0C, /* 0000110 */ - // 0x18, /* 0001100 */ - // 0x00, /* 0000000 */ - // 0x66, /* 0110011 */ - // 0x66, /* 0110011 */ - // 0x66, /* 0110011 */ - // 0x66, /* 0110011 */ - // 0x3A, /* 0011101 */ - // 0x00, /* 0000000 */ + 0x0C, /* 0000110 */ + 0x18, /* 0001100 */ + 0x00, /* 0000000 */ + 0x66, /* 0110011 */ + 0x66, /* 0110011 */ + 0x66, /* 0110011 */ + 0x66, /* 0110011 */ + 0x3A, /* 0011101 */ + 0x00, /* 0000000 */ // /* // * code=164, hex=0xA4, ascii="!$" // */ - // 0x76, /* 0111011 */ - // 0xDC, /* 1101110 */ - // 0x00, /* 0000000 */ - // 0x6C, /* 0110110 */ - // 0x76, /* 0111011 */ - // 0x66, /* 0110011 */ - // 0x66, /* 0110011 */ - // 0x66, /* 0110011 */ - // 0x00, /* 0000000 */ + 0x76, /* 0111011 */ + 0xDC, /* 1101110 */ + 0x00, /* 0000000 */ + 0x6C, /* 0110110 */ + 0x76, /* 0111011 */ + 0x66, /* 0110011 */ + 0x66, /* 0110011 */ + 0x66, /* 0110011 */ + 0x00, /* 0000000 */ // /* // * code=165, hex=0xA5, ascii="!%" // */ - // 0x76, /* 0111011 */ - // 0xDC, /* 1101110 */ - // 0x00, /* 0000000 */ - // 0x66, /* 0110011 */ - // 0x76, /* 0111011 */ - // 0x7E, /* 0111111 */ - // 0x6E, /* 0110111 */ - // 0x66, /* 0110011 */ - // 0x00, /* 0000000 */ + 0x76, /* 0111011 */ + 0xDC, /* 1101110 */ + 0x00, /* 0000000 */ + 0x66, /* 0110011 */ + 0x76, /* 0111011 */ + 0x7E, /* 0111111 */ + 0x6E, /* 0110111 */ + 0x66, /* 0110011 */ + 0x00, /* 0000000 */ // /* // * code=166, hex=0xA6, ascii="!&" // */ - // 0x38, /* 0011100 */ - // 0x0C, /* 0000110 */ - // 0x3C, /* 0011110 */ - // 0x6C, /* 0110110 */ - // 0x34, /* 0011010 */ - // 0x00, /* 0000000 */ - // 0x7C, /* 0111110 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ + 0x38, /* 0011100 */ + 0x0C, /* 0000110 */ + 0x3C, /* 0011110 */ + 0x6C, /* 0110110 */ + 0x34, /* 0011010 */ + 0x00, /* 0000000 */ + 0x7C, /* 0111110 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ // /* // * code=167, hex=0xA7, ascii="!'" // */ - // 0x3C, /* 0011110 */ - // 0x66, /* 0110011 */ - // 0x66, /* 0110011 */ - // 0x3C, /* 0011110 */ - // 0x00, /* 0000000 */ - // 0x7E, /* 0111111 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ + 0x3C, /* 0011110 */ + 0x66, /* 0110011 */ + 0x66, /* 0110011 */ + 0x3C, /* 0011110 */ + 0x00, /* 0000000 */ + 0x7E, /* 0111111 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ // /* // * code=168, hex=0xA8, ascii="!(" // */ - // 0x00, /* 0000000 */ - // 0x18, /* 0001100 */ - // 0x00, /* 0000000 */ - // 0x18, /* 0001100 */ - // 0x30, /* 0011000 */ - // 0x60, /* 0110000 */ - // 0x66, /* 0110011 */ - // 0x3C, /* 0011110 */ - // 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x18, /* 0001100 */ + 0x00, /* 0000000 */ + 0x18, /* 0001100 */ + 0x30, /* 0011000 */ + 0x60, /* 0110000 */ + 0x66, /* 0110011 */ + 0x3C, /* 0011110 */ + 0x00, /* 0000000 */ // /* // * code=169, hex=0xA9, ascii="!)" // */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x3C, /* 0011110 */ - // 0x3C, /* 0011110 */ - // 0x30, /* 0011000 */ - // 0x30, /* 0011000 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x3C, /* 0011110 */ + 0x3C, /* 0011110 */ + 0x30, /* 0011000 */ + 0x30, /* 0011000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ // /* // * code=170, hex=0xAA, ascii="!*" // */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x7C, /* 0111110 */ - // 0x7C, /* 0111110 */ - // 0x0C, /* 0000110 */ - // 0x0C, /* 0000110 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x7C, /* 0111110 */ + 0x7C, /* 0111110 */ + 0x0C, /* 0000110 */ + 0x0C, /* 0000110 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ // /* // * code=171, hex=0xAB, ascii="!+" // */ - // 0x60, /* 0110000 */ - // 0x60, /* 0110000 */ - // 0x60, /* 0110000 */ - // 0x6E, /* 0110111 */ - // 0x1A, /* 0001101 */ - // 0x04, /* 0000010 */ - // 0x18, /* 0001100 */ - // 0x1E, /* 0001111 */ - // 0x00, /* 0000000 */ + 0x60, /* 0110000 */ + 0x60, /* 0110000 */ + 0x60, /* 0110000 */ + 0x6E, /* 0110111 */ + 0x1A, /* 0001101 */ + 0x04, /* 0000010 */ + 0x18, /* 0001100 */ + 0x1E, /* 0001111 */ + 0x00, /* 0000000 */ // /* // * code=172, hex=0xAC, ascii="!," // */ - // 0x60, /* 0110000 */ - // 0x60, /* 0110000 */ - // 0x60, /* 0110000 */ - // 0x6C, /* 0110110 */ - // 0x7C, /* 0111110 */ - // 0x2C, /* 0010110 */ - // 0x7C, /* 0111110 */ - // 0x0C, /* 0000110 */ - // 0x00, /* 0000000 */ + 0x60, /* 0110000 */ + 0x60, /* 0110000 */ + 0x60, /* 0110000 */ + 0x6C, /* 0110110 */ + 0x7C, /* 0111110 */ + 0x2C, /* 0010110 */ + 0x7C, /* 0111110 */ + 0x0C, /* 0000110 */ + 0x00, /* 0000000 */ // /* // * code=173, hex=0xAD, ascii="!-" // */ - // 0x00, /* 0000000 */ - // 0x18, /* 0001100 */ - // 0x00, /* 0000000 */ - // 0x18, /* 0001100 */ - // 0x18, /* 0001100 */ - // 0x3C, /* 0011110 */ - // 0x3C, /* 0011110 */ - // 0x18, /* 0001100 */ - // 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x18, /* 0001100 */ + 0x00, /* 0000000 */ + 0x18, /* 0001100 */ + 0x18, /* 0001100 */ + 0x3C, /* 0011110 */ + 0x3C, /* 0011110 */ + 0x18, /* 0001100 */ + 0x00, /* 0000000 */ // /* // * code=174, hex=0xAE, ascii="!." // */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x32, /* 0011001 */ - // 0x66, /* 0110011 */ - // 0xCC, /* 1100110 */ - // 0x66, /* 0110011 */ - // 0x32, /* 0011001 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x32, /* 0011001 */ + 0x66, /* 0110011 */ + 0xCC, /* 1100110 */ + 0x66, /* 0110011 */ + 0x32, /* 0011001 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ // /* // * code=175, hex=0xAF, ascii="!/" // */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0xCC, /* 1100110 */ - // 0x66, /* 0110011 */ - // 0x32, /* 0011001 */ - // 0x66, /* 0110011 */ - // 0xCC, /* 1100110 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0xCC, /* 1100110 */ + 0x66, /* 0110011 */ + 0x32, /* 0011001 */ + 0x66, /* 0110011 */ + 0xCC, /* 1100110 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ // /* // * code=176, hex=0xB0, ascii="!0" // */ - // 0x54, /* 0101010 */ - // 0x00, /* 0000000 */ - // 0xAA, /* 1010101 */ - // 0x00, /* 0000000 */ - // 0x54, /* 0101010 */ - // 0x00, /* 0000000 */ - // 0xAA, /* 1010101 */ - // 0x00, /* 0000000 */ - // 0x54, /* 0101010 */ + 0x54, /* 0101010 */ + 0x00, /* 0000000 */ + 0xAA, /* 1010101 */ + 0x00, /* 0000000 */ + 0x54, /* 0101010 */ + 0x00, /* 0000000 */ + 0xAA, /* 1010101 */ + 0x00, /* 0000000 */ + 0x54, /* 0101010 */ // /* // * code=177, hex=0xB1, ascii="!1" // */ - // 0x92, /* 1001001 */ - // 0x48, /* 0100100 */ - // 0x24, /* 0010010 */ - // 0x92, /* 1001001 */ - // 0x48, /* 0100100 */ - // 0x24, /* 0010010 */ - // 0x92, /* 1001001 */ - // 0x48, /* 0100100 */ - // 0x24, /* 0010010 */ + 0x92, /* 1001001 */ + 0x48, /* 0100100 */ + 0x24, /* 0010010 */ + 0x92, /* 1001001 */ + 0x48, /* 0100100 */ + 0x24, /* 0010010 */ + 0x92, /* 1001001 */ + 0x48, /* 0100100 */ + 0x24, /* 0010010 */ // /* // * code=178, hex=0xB2, ascii="!2" // */ - // 0xAA, /* 1010101 */ - // 0x54, /* 0101010 */ - // 0xAA, /* 1010101 */ - // 0x54, /* 0101010 */ - // 0xAA, /* 1010101 */ - // 0x54, /* 0101010 */ - // 0xAA, /* 1010101 */ - // 0x54, /* 0101010 */ - // 0xAA, /* 1010101 */ + 0xAA, /* 1010101 */ + 0x54, /* 0101010 */ + 0xAA, /* 1010101 */ + 0x54, /* 0101010 */ + 0xAA, /* 1010101 */ + 0x54, /* 0101010 */ + 0xAA, /* 1010101 */ + 0x54, /* 0101010 */ + 0xAA, /* 1010101 */ // /* // * code=179, hex=0xB3, ascii="!3" // */ - // 0x10, /* 0001000 */ - // 0x10, /* 0001000 */ - // 0x10, /* 0001000 */ - // 0x10, /* 0001000 */ - // 0x10, /* 0001000 */ - // 0x10, /* 0001000 */ - // 0x10, /* 0001000 */ - // 0x10, /* 0001000 */ - // 0x10, /* 0001000 */ + 0x10, /* 0001000 */ + 0x10, /* 0001000 */ + 0x10, /* 0001000 */ + 0x10, /* 0001000 */ + 0x10, /* 0001000 */ + 0x10, /* 0001000 */ + 0x10, /* 0001000 */ + 0x10, /* 0001000 */ + 0x10, /* 0001000 */ // /* // * code=180, hex=0xB4, ascii="!4" // */ - // 0x10, /* 0001000 */ - // 0x10, /* 0001000 */ - // 0x10, /* 0001000 */ - // 0x10, /* 0001000 */ - // 0xF0, /* 1111000 */ - // 0x10, /* 0001000 */ - // 0x10, /* 0001000 */ - // 0x10, /* 0001000 */ - // 0x10, /* 0001000 */ + 0x10, /* 0001000 */ + 0x10, /* 0001000 */ + 0x10, /* 0001000 */ + 0x10, /* 0001000 */ + 0xF0, /* 1111000 */ + 0x10, /* 0001000 */ + 0x10, /* 0001000 */ + 0x10, /* 0001000 */ + 0x10, /* 0001000 */ // /* // * code=181, hex=0xB5, ascii="!5" // */ - // 0x10, /* 0001000 */ - // 0x10, /* 0001000 */ - // 0x10, /* 0001000 */ - // 0xF0, /* 1111000 */ - // 0x10, /* 0001000 */ - // 0xF0, /* 1111000 */ - // 0x10, /* 0001000 */ - // 0x10, /* 0001000 */ - // 0x10, /* 0001000 */ + 0x10, /* 0001000 */ + 0x10, /* 0001000 */ + 0x10, /* 0001000 */ + 0xF0, /* 1111000 */ + 0x10, /* 0001000 */ + 0xF0, /* 1111000 */ + 0x10, /* 0001000 */ + 0x10, /* 0001000 */ + 0x10, /* 0001000 */ // /* // * code=182, hex=0xB6, ascii="!6" // */ - // 0x28, /* 0010100 */ - // 0x28, /* 0010100 */ - // 0x28, /* 0010100 */ - // 0x28, /* 0010100 */ - // 0xE8, /* 1110100 */ - // 0x28, /* 0010100 */ - // 0x28, /* 0010100 */ - // 0x28, /* 0010100 */ - // 0x28, /* 0010100 */ + 0x28, /* 0010100 */ + 0x28, /* 0010100 */ + 0x28, /* 0010100 */ + 0x28, /* 0010100 */ + 0xE8, /* 1110100 */ + 0x28, /* 0010100 */ + 0x28, /* 0010100 */ + 0x28, /* 0010100 */ + 0x28, /* 0010100 */ // /* // * code=183, hex=0xB7, ascii="!7" // */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0xF8, /* 1111100 */ - // 0x28, /* 0010100 */ - // 0x28, /* 0010100 */ - // 0x28, /* 0010100 */ - // 0x28, /* 0010100 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0xF8, /* 1111100 */ + 0x28, /* 0010100 */ + 0x28, /* 0010100 */ + 0x28, /* 0010100 */ + 0x28, /* 0010100 */ // /* // * code=184, hex=0xB8, ascii="!8" // */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0xF0, /* 1111000 */ - // 0x10, /* 0001000 */ - // 0xF0, /* 1111000 */ - // 0x10, /* 0001000 */ - // 0x10, /* 0001000 */ - // 0x10, /* 0001000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0xF0, /* 1111000 */ + 0x10, /* 0001000 */ + 0xF0, /* 1111000 */ + 0x10, /* 0001000 */ + 0x10, /* 0001000 */ + 0x10, /* 0001000 */ // /* // * code=185, hex=0xB9, ascii="!9" // */ - // 0x28, /* 0010100 */ - // 0x28, /* 0010100 */ - // 0x28, /* 0010100 */ - // 0xE8, /* 1110100 */ - // 0x08, /* 0000100 */ - // 0xE8, /* 1110100 */ - // 0x28, /* 0010100 */ - // 0x28, /* 0010100 */ - // 0x28, /* 0010100 */ + 0x28, /* 0010100 */ + 0x28, /* 0010100 */ + 0x28, /* 0010100 */ + 0xE8, /* 1110100 */ + 0x08, /* 0000100 */ + 0xE8, /* 1110100 */ + 0x28, /* 0010100 */ + 0x28, /* 0010100 */ + 0x28, /* 0010100 */ // /* // * code=186, hex=0xBA, ascii="!:" // */ - // 0x28, /* 0010100 */ - // 0x28, /* 0010100 */ - // 0x28, /* 0010100 */ - // 0x28, /* 0010100 */ - // 0x28, /* 0010100 */ - // 0x28, /* 0010100 */ - // 0x28, /* 0010100 */ - // 0x28, /* 0010100 */ - // 0x28, /* 0010100 */ + 0x28, /* 0010100 */ + 0x28, /* 0010100 */ + 0x28, /* 0010100 */ + 0x28, /* 0010100 */ + 0x28, /* 0010100 */ + 0x28, /* 0010100 */ + 0x28, /* 0010100 */ + 0x28, /* 0010100 */ + 0x28, /* 0010100 */ // /* // * code=187, hex=0xBB, ascii="!;" // */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0xF8, /* 1111100 */ - // 0x08, /* 0000100 */ - // 0xE8, /* 1110100 */ - // 0x28, /* 0010100 */ - // 0x28, /* 0010100 */ - // 0x28, /* 0010100 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0xF8, /* 1111100 */ + 0x08, /* 0000100 */ + 0xE8, /* 1110100 */ + 0x28, /* 0010100 */ + 0x28, /* 0010100 */ + 0x28, /* 0010100 */ // /* // * code=188, hex=0xBC, ascii="!<" // */ - // 0x28, /* 0010100 */ - // 0x28, /* 0010100 */ - // 0x28, /* 0010100 */ - // 0xE8, /* 1110100 */ - // 0x08, /* 0000100 */ - // 0xF8, /* 1111100 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ + 0x28, /* 0010100 */ + 0x28, /* 0010100 */ + 0x28, /* 0010100 */ + 0xE8, /* 1110100 */ + 0x08, /* 0000100 */ + 0xF8, /* 1111100 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ // /* // * code=189, hex=0xBD, ascii="!=" // */ - // 0x28, /* 0010100 */ - // 0x28, /* 0010100 */ - // 0x28, /* 0010100 */ - // 0x28, /* 0010100 */ - // 0xF8, /* 1111100 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ + 0x28, /* 0010100 */ + 0x28, /* 0010100 */ + 0x28, /* 0010100 */ + 0x28, /* 0010100 */ + 0xF8, /* 1111100 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ // /* // * code=190, hex=0xBE, ascii="!>" // */ - // 0x10, /* 0001000 */ - // 0x10, /* 0001000 */ - // 0x10, /* 0001000 */ - // 0xF0, /* 1111000 */ - // 0x10, /* 0001000 */ - // 0xF0, /* 1111000 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ + 0x10, /* 0001000 */ + 0x10, /* 0001000 */ + 0x10, /* 0001000 */ + 0xF0, /* 1111000 */ + 0x10, /* 0001000 */ + 0xF0, /* 1111000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ // /* // * code=191, hex=0xBF, ascii="!?" // */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0xF0, /* 1111000 */ - // 0x10, /* 0001000 */ - // 0x10, /* 0001000 */ - // 0x10, /* 0001000 */ - // 0x10, /* 0001000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0xF0, /* 1111000 */ + 0x10, /* 0001000 */ + 0x10, /* 0001000 */ + 0x10, /* 0001000 */ + 0x10, /* 0001000 */ // /* // * code=192, hex=0xC0, ascii="!@" // */ - // 0x10, /* 0001000 */ - // 0x10, /* 0001000 */ - // 0x10, /* 0001000 */ - // 0x10, /* 0001000 */ - // 0x1E, /* 0001111 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ + 0x10, /* 0001000 */ + 0x10, /* 0001000 */ + 0x10, /* 0001000 */ + 0x10, /* 0001000 */ + 0x1E, /* 0001111 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ // /* // * code=193, hex=0xC1, ascii="!A" // */ - // 0x10, /* 0001000 */ - // 0x10, /* 0001000 */ - // 0x10, /* 0001000 */ - // 0x10, /* 0001000 */ - // 0xFE, /* 1111111 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ + 0x10, /* 0001000 */ + 0x10, /* 0001000 */ + 0x10, /* 0001000 */ + 0x10, /* 0001000 */ + 0xFE, /* 1111111 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ // /* // * code=194, hex=0xC2, ascii="!B" // */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0xFE, /* 1111111 */ - // 0x10, /* 0001000 */ - // 0x10, /* 0001000 */ - // 0x10, /* 0001000 */ - // 0x10, /* 0001000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0xFE, /* 1111111 */ + 0x10, /* 0001000 */ + 0x10, /* 0001000 */ + 0x10, /* 0001000 */ + 0x10, /* 0001000 */ // /* // * code=195, hex=0xC3, ascii="!C" // */ - // 0x10, /* 0001000 */ - // 0x10, /* 0001000 */ - // 0x10, /* 0001000 */ - // 0x10, /* 0001000 */ - // 0x1E, /* 0001111 */ - // 0x10, /* 0001000 */ - // 0x10, /* 0001000 */ - // 0x10, /* 0001000 */ - // 0x10, /* 0001000 */ + 0x10, /* 0001000 */ + 0x10, /* 0001000 */ + 0x10, /* 0001000 */ + 0x10, /* 0001000 */ + 0x1E, /* 0001111 */ + 0x10, /* 0001000 */ + 0x10, /* 0001000 */ + 0x10, /* 0001000 */ + 0x10, /* 0001000 */ // /* // * code=196, hex=0xC4, ascii="!D" // */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0xFE, /* 1111111 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0xFE, /* 1111111 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ // /* // * code=197, hex=0xC5, ascii="!E" // */ - // 0x10, /* 0001000 */ - // 0x10, /* 0001000 */ - // 0x10, /* 0001000 */ - // 0x10, /* 0001000 */ - // 0xFE, /* 1111111 */ - // 0x10, /* 0001000 */ - // 0x10, /* 0001000 */ - // 0x10, /* 0001000 */ - // 0x10, /* 0001000 */ + 0x10, /* 0001000 */ + 0x10, /* 0001000 */ + 0x10, /* 0001000 */ + 0x10, /* 0001000 */ + 0xFE, /* 1111111 */ + 0x10, /* 0001000 */ + 0x10, /* 0001000 */ + 0x10, /* 0001000 */ + 0x10, /* 0001000 */ // /* // * code=198, hex=0xC6, ascii="!F" // */ - // 0x10, /* 0001000 */ - // 0x10, /* 0001000 */ - // 0x10, /* 0001000 */ - // 0x1E, /* 0001111 */ - // 0x10, /* 0001000 */ - // 0x1E, /* 0001111 */ - // 0x10, /* 0001000 */ - // 0x10, /* 0001000 */ - // 0x10, /* 0001000 */ + 0x10, /* 0001000 */ + 0x10, /* 0001000 */ + 0x10, /* 0001000 */ + 0x1E, /* 0001111 */ + 0x10, /* 0001000 */ + 0x1E, /* 0001111 */ + 0x10, /* 0001000 */ + 0x10, /* 0001000 */ + 0x10, /* 0001000 */ // /* // * code=199, hex=0xC7, ascii="!G" // */ - // 0x28, /* 0010100 */ - // 0x28, /* 0010100 */ - // 0x28, /* 0010100 */ - // 0x28, /* 0010100 */ - // 0x2E, /* 0010111 */ - // 0x28, /* 0010100 */ - // 0x28, /* 0010100 */ - // 0x28, /* 0010100 */ - // 0x28, /* 0010100 */ + 0x28, /* 0010100 */ + 0x28, /* 0010100 */ + 0x28, /* 0010100 */ + 0x28, /* 0010100 */ + 0x2E, /* 0010111 */ + 0x28, /* 0010100 */ + 0x28, /* 0010100 */ + 0x28, /* 0010100 */ + 0x28, /* 0010100 */ // /* // * code=200, hex=0xC8, ascii="!H" // */ - // 0x28, /* 0010100 */ - // 0x28, /* 0010100 */ - // 0x28, /* 0010100 */ - // 0x2E, /* 0010111 */ - // 0x20, /* 0010000 */ - // 0x3E, /* 0011111 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ + 0x28, /* 0010100 */ + 0x28, /* 0010100 */ + 0x28, /* 0010100 */ + 0x2E, /* 0010111 */ + 0x20, /* 0010000 */ + 0x3E, /* 0011111 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ // /* // * code=201, hex=0xC9, ascii="!I" // */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x3E, /* 0011111 */ - // 0x20, /* 0010000 */ - // 0x2E, /* 0010111 */ - // 0x28, /* 0010100 */ - // 0x28, /* 0010100 */ - // 0x28, /* 0010100 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x3E, /* 0011111 */ + 0x20, /* 0010000 */ + 0x2E, /* 0010111 */ + 0x28, /* 0010100 */ + 0x28, /* 0010100 */ + 0x28, /* 0010100 */ // /* // * code=202, hex=0xCA, ascii="!J" // */ - // 0x28, /* 0010100 */ - // 0x28, /* 0010100 */ - // 0x28, /* 0010100 */ - // 0xEE, /* 1110111 */ - // 0x00, /* 0000000 */ - // 0xFE, /* 1111111 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ + 0x28, /* 0010100 */ + 0x28, /* 0010100 */ + 0x28, /* 0010100 */ + 0xEE, /* 1110111 */ + 0x00, /* 0000000 */ + 0xFE, /* 1111111 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ // /* // * code=203, hex=0xCB, ascii="!K" // */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0xFE, /* 1111111 */ - // 0x00, /* 0000000 */ - // 0xEE, /* 1110111 */ - // 0x28, /* 0010100 */ - // 0x28, /* 0010100 */ - // 0x28, /* 0010100 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0xFE, /* 1111111 */ + 0x00, /* 0000000 */ + 0xEE, /* 1110111 */ + 0x28, /* 0010100 */ + 0x28, /* 0010100 */ + 0x28, /* 0010100 */ // /* // * code=204, hex=0xCC, ascii="!L" // */ - // 0x28, /* 0010100 */ - // 0x28, /* 0010100 */ - // 0x28, /* 0010100 */ - // 0x2E, /* 0010111 */ - // 0x20, /* 0010000 */ - // 0x2E, /* 0010111 */ - // 0x28, /* 0010100 */ - // 0x28, /* 0010100 */ - // 0x28, /* 0010100 */ + 0x28, /* 0010100 */ + 0x28, /* 0010100 */ + 0x28, /* 0010100 */ + 0x2E, /* 0010111 */ + 0x20, /* 0010000 */ + 0x2E, /* 0010111 */ + 0x28, /* 0010100 */ + 0x28, /* 0010100 */ + 0x28, /* 0010100 */ // /* // * code=205, hex=0xCD, ascii="!M" // */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0xFE, /* 1111111 */ - // 0x00, /* 0000000 */ - // 0xFE, /* 1111111 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0xFE, /* 1111111 */ + 0x00, /* 0000000 */ + 0xFE, /* 1111111 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ // /* // * code=206, hex=0xCE, ascii="!N" // */ - // 0x28, /* 0010100 */ - // 0x28, /* 0010100 */ - // 0x28, /* 0010100 */ - // 0xEE, /* 1110111 */ - // 0x00, /* 0000000 */ - // 0xEE, /* 1110111 */ - // 0x28, /* 0010100 */ - // 0x28, /* 0010100 */ - // 0x28, /* 0010100 */ + 0x28, /* 0010100 */ + 0x28, /* 0010100 */ + 0x28, /* 0010100 */ + 0xEE, /* 1110111 */ + 0x00, /* 0000000 */ + 0xEE, /* 1110111 */ + 0x28, /* 0010100 */ + 0x28, /* 0010100 */ + 0x28, /* 0010100 */ // /* // * code=207, hex=0xCF, ascii="!O" // */ - // 0x10, /* 0001000 */ - // 0x10, /* 0001000 */ - // 0x10, /* 0001000 */ - // 0xFE, /* 1111111 */ - // 0x00, /* 0000000 */ - // 0xFE, /* 1111111 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ + 0x10, /* 0001000 */ + 0x10, /* 0001000 */ + 0x10, /* 0001000 */ + 0xFE, /* 1111111 */ + 0x00, /* 0000000 */ + 0xFE, /* 1111111 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ // /* // * code=208, hex=0xD0, ascii="!P" // */ - // 0x28, /* 0010100 */ - // 0x28, /* 0010100 */ - // 0x28, /* 0010100 */ - // 0x28, /* 0010100 */ - // 0xF8, /* 1111100 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ + 0x28, /* 0010100 */ + 0x28, /* 0010100 */ + 0x28, /* 0010100 */ + 0x28, /* 0010100 */ + 0xF8, /* 1111100 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ // /* // * code=209, hex=0xD1, ascii="!Q" // */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0xFE, /* 1111111 */ - // 0x00, /* 0000000 */ - // 0xFE, /* 1111111 */ - // 0x10, /* 0001000 */ - // 0x10, /* 0001000 */ - // 0x10, /* 0001000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0xFE, /* 1111111 */ + 0x00, /* 0000000 */ + 0xFE, /* 1111111 */ + 0x10, /* 0001000 */ + 0x10, /* 0001000 */ + 0x10, /* 0001000 */ // /* // * code=210, hex=0xD2, ascii="!R" // */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0xF8, /* 1111100 */ - // 0x28, /* 0010100 */ - // 0x28, /* 0010100 */ - // 0x28, /* 0010100 */ - // 0x28, /* 0010100 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0xF8, /* 1111100 */ + 0x28, /* 0010100 */ + 0x28, /* 0010100 */ + 0x28, /* 0010100 */ + 0x28, /* 0010100 */ // /* // * code=211, hex=0xD3, ascii="!S" // */ - // 0x28, /* 0010100 */ - // 0x28, /* 0010100 */ - // 0x28, /* 0010100 */ - // 0x28, /* 0010100 */ - // 0x3E, /* 0011111 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ + 0x28, /* 0010100 */ + 0x28, /* 0010100 */ + 0x28, /* 0010100 */ + 0x28, /* 0010100 */ + 0x3E, /* 0011111 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ // /* // * code=212, hex=0xD4, ascii="!T" // */ - // 0x10, /* 0001000 */ - // 0x10, /* 0001000 */ - // 0x10, /* 0001000 */ - // 0x1E, /* 0001111 */ - // 0x10, /* 0001000 */ - // 0x1E, /* 0001111 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ + 0x10, /* 0001000 */ + 0x10, /* 0001000 */ + 0x10, /* 0001000 */ + 0x1E, /* 0001111 */ + 0x10, /* 0001000 */ + 0x1E, /* 0001111 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ // /* // * code=213, hex=0xD5, ascii="!U" // */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x1E, /* 0001111 */ - // 0x10, /* 0001000 */ - // 0x1E, /* 0001111 */ - // 0x10, /* 0001000 */ - // 0x10, /* 0001000 */ - // 0x10, /* 0001000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x1E, /* 0001111 */ + 0x10, /* 0001000 */ + 0x1E, /* 0001111 */ + 0x10, /* 0001000 */ + 0x10, /* 0001000 */ + 0x10, /* 0001000 */ // /* // * code=214, hex=0xD6, ascii="!V" // */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x3E, /* 0011111 */ - // 0x28, /* 0010100 */ - // 0x28, /* 0010100 */ - // 0x28, /* 0010100 */ - // 0x28, /* 0010100 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x3E, /* 0011111 */ + 0x28, /* 0010100 */ + 0x28, /* 0010100 */ + 0x28, /* 0010100 */ + 0x28, /* 0010100 */ // /* // * code=215, hex=0xD7, ascii="!W" // */ - // 0x28, /* 0010100 */ - // 0x28, /* 0010100 */ - // 0x28, /* 0010100 */ - // 0x28, /* 0010100 */ - // 0xE8, /* 1110100 */ - // 0x28, /* 0010100 */ - // 0x28, /* 0010100 */ - // 0x28, /* 0010100 */ - // 0x28, /* 0010100 */ + 0x28, /* 0010100 */ + 0x28, /* 0010100 */ + 0x28, /* 0010100 */ + 0x28, /* 0010100 */ + 0xE8, /* 1110100 */ + 0x28, /* 0010100 */ + 0x28, /* 0010100 */ + 0x28, /* 0010100 */ + 0x28, /* 0010100 */ // /* // * code=216, hex=0xD8, ascii="!X" // */ - // 0x10, /* 0001000 */ - // 0x10, /* 0001000 */ - // 0x10, /* 0001000 */ - // 0xFE, /* 1111111 */ - // 0x10, /* 0001000 */ - // 0xFE, /* 1111111 */ - // 0x10, /* 0001000 */ - // 0x10, /* 0001000 */ - // 0x10, /* 0001000 */ + 0x10, /* 0001000 */ + 0x10, /* 0001000 */ + 0x10, /* 0001000 */ + 0xFE, /* 1111111 */ + 0x10, /* 0001000 */ + 0xFE, /* 1111111 */ + 0x10, /* 0001000 */ + 0x10, /* 0001000 */ + 0x10, /* 0001000 */ // /* // * code=217, hex=0xD9, ascii="!Y" // */ - // 0x10, /* 0001000 */ - // 0x10, /* 0001000 */ - // 0x10, /* 0001000 */ - // 0x10, /* 0001000 */ - // 0xF0, /* 1111000 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ + 0x10, /* 0001000 */ + 0x10, /* 0001000 */ + 0x10, /* 0001000 */ + 0x10, /* 0001000 */ + 0xF0, /* 1111000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ // /* // * code=218, hex=0xDA, ascii="!Z" // */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x1E, /* 0001111 */ - // 0x10, /* 0001000 */ - // 0x10, /* 0001000 */ - // 0x10, /* 0001000 */ - // 0x10, /* 0001000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x1E, /* 0001111 */ + 0x10, /* 0001000 */ + 0x10, /* 0001000 */ + 0x10, /* 0001000 */ + 0x10, /* 0001000 */ // /* // * code=219, hex=0xDB, ascii="![" // */ - // 0xFE, /* 1111111 */ - // 0xFE, /* 1111111 */ - // 0xFE, /* 1111111 */ - // 0xFE, /* 1111111 */ - // 0xFE, /* 1111111 */ - // 0xFE, /* 1111111 */ - // 0xFE, /* 1111111 */ - // 0xFE, /* 1111111 */ - // 0xFE, /* 1111111 */ + 0xFE, /* 1111111 */ + 0xFE, /* 1111111 */ + 0xFE, /* 1111111 */ + 0xFE, /* 1111111 */ + 0xFE, /* 1111111 */ + 0xFE, /* 1111111 */ + 0xFE, /* 1111111 */ + 0xFE, /* 1111111 */ + 0xFE, /* 1111111 */ // /* // * code=220, hex=0xDC, ascii="!\" // */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0xFE, /* 1111111 */ - // 0xFE, /* 1111111 */ - // 0xFE, /* 1111111 */ - // 0xFE, /* 1111111 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0xFE, /* 1111111 */ + 0xFE, /* 1111111 */ + 0xFE, /* 1111111 */ + 0xFE, /* 1111111 */ // /* // * code=221, hex=0xDD, ascii="!]" // */ - // 0xF0, /* 1111000 */ - // 0xF0, /* 1111000 */ - // 0xF0, /* 1111000 */ - // 0xF0, /* 1111000 */ - // 0xF0, /* 1111000 */ - // 0xF0, /* 1111000 */ - // 0xF0, /* 1111000 */ - // 0xF0, /* 1111000 */ - // 0xF0, /* 1111000 */ + 0xF0, /* 1111000 */ + 0xF0, /* 1111000 */ + 0xF0, /* 1111000 */ + 0xF0, /* 1111000 */ + 0xF0, /* 1111000 */ + 0xF0, /* 1111000 */ + 0xF0, /* 1111000 */ + 0xF0, /* 1111000 */ + 0xF0, /* 1111000 */ // /* // * code=222, hex=0xDE, ascii="!^" // */ - // 0x0E, /* 0000111 */ - // 0x0E, /* 0000111 */ - // 0x0E, /* 0000111 */ - // 0x0E, /* 0000111 */ - // 0x0E, /* 0000111 */ - // 0x0E, /* 0000111 */ - // 0x0E, /* 0000111 */ - // 0x0E, /* 0000111 */ - // 0x0E, /* 0000111 */ + 0x0E, /* 0000111 */ + 0x0E, /* 0000111 */ + 0x0E, /* 0000111 */ + 0x0E, /* 0000111 */ + 0x0E, /* 0000111 */ + 0x0E, /* 0000111 */ + 0x0E, /* 0000111 */ + 0x0E, /* 0000111 */ + 0x0E, /* 0000111 */ // /* // * code=223, hex=0xDF, ascii="!_" // */ - // 0xFE, /* 1111111 */ - // 0xFE, /* 1111111 */ - // 0xFE, /* 1111111 */ - // 0xFE, /* 1111111 */ - // 0xFE, /* 1111111 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ + 0xFE, /* 1111111 */ + 0xFE, /* 1111111 */ + 0xFE, /* 1111111 */ + 0xFE, /* 1111111 */ + 0xFE, /* 1111111 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ // /* // * code=224, hex=0xE0, ascii="!`" // */ - // 0x00, /* 0000000 */ - // 0x34, /* 0011010 */ - // 0x68, /* 0110100 */ - // 0x68, /* 0110100 */ - // 0x68, /* 0110100 */ - // 0x34, /* 0011010 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x34, /* 0011010 */ + 0x68, /* 0110100 */ + 0x68, /* 0110100 */ + 0x68, /* 0110100 */ + 0x34, /* 0011010 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ // /* // * code=225, hex=0xE1, ascii="!a" // */ - // 0x7C, /* 0111110 */ - // 0x66, /* 0110011 */ - // 0x66, /* 0110011 */ - // 0x6C, /* 0110110 */ - // 0x66, /* 0110011 */ - // 0x62, /* 0110001 */ - // 0x66, /* 0110011 */ - // 0x6C, /* 0110110 */ - // 0x08, /* 0000100 */ + 0x7C, /* 0111110 */ + 0x66, /* 0110011 */ + 0x66, /* 0110011 */ + 0x6C, /* 0110110 */ + 0x66, /* 0110011 */ + 0x62, /* 0110001 */ + 0x66, /* 0110011 */ + 0x6C, /* 0110110 */ + 0x08, /* 0000100 */ // /* // * code=226, hex=0xE2, ascii="!b" // */ - // 0x00, /* 0000000 */ - // 0x7E, /* 0111111 */ - // 0x62, /* 0110001 */ - // 0x60, /* 0110000 */ - // 0x60, /* 0110000 */ - // 0x60, /* 0110000 */ - // 0x60, /* 0110000 */ - // 0x60, /* 0110000 */ - // 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x7E, /* 0111111 */ + 0x62, /* 0110001 */ + 0x60, /* 0110000 */ + 0x60, /* 0110000 */ + 0x60, /* 0110000 */ + 0x60, /* 0110000 */ + 0x60, /* 0110000 */ + 0x00, /* 0000000 */ // /* // * code=227, hex=0xE3, ascii="!c" // */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x6C, /* 0110110 */ - // 0xFE, /* 1111111 */ - // 0xF6, /* 1111011 */ - // 0x66, /* 0110011 */ - // 0x6C, /* 0110110 */ - // 0x6C, /* 0110110 */ - // 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x6C, /* 0110110 */ + 0xFE, /* 1111111 */ + 0xF6, /* 1111011 */ + 0x66, /* 0110011 */ + 0x6C, /* 0110110 */ + 0x6C, /* 0110110 */ + 0x00, /* 0000000 */ // /* // * code=228, hex=0xE4, ascii="!d" // */ - // 0x00, /* 0000000 */ - // 0xFE, /* 1111111 */ - // 0xC6, /* 1100011 */ - // 0x60, /* 0110000 */ - // 0x38, /* 0011100 */ - // 0x30, /* 0011000 */ - // 0x66, /* 0110011 */ - // 0xFE, /* 1111111 */ - // 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0xFE, /* 1111111 */ + 0xC6, /* 1100011 */ + 0x60, /* 0110000 */ + 0x38, /* 0011100 */ + 0x30, /* 0011000 */ + 0x66, /* 0110011 */ + 0xFE, /* 1111111 */ + 0x00, /* 0000000 */ // /* // * code=229, hex=0xE5, ascii="!e" // */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x3E, /* 0011111 */ - // 0x6C, /* 0110110 */ - // 0x6C, /* 0110110 */ - // 0x6C, /* 0110110 */ - // 0x38, /* 0011100 */ - // 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x3E, /* 0011111 */ + 0x6C, /* 0110110 */ + 0x6C, /* 0110110 */ + 0x6C, /* 0110110 */ + 0x38, /* 0011100 */ + 0x00, /* 0000000 */ // /* // * code=230, hex=0xE6, ascii="!f" // */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x36, /* 0011011 */ - // 0x36, /* 0011011 */ - // 0x36, /* 0011011 */ - // 0x3E, /* 0011111 */ - // 0x62, /* 0110001 */ - // 0x40, /* 0100000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x36, /* 0011011 */ + 0x36, /* 0011011 */ + 0x36, /* 0011011 */ + 0x3E, /* 0011111 */ + 0x62, /* 0110001 */ + 0x40, /* 0100000 */ // /* // * code=231, hex=0xE7, ascii="!g" // */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x7A, /* 0111101 */ - // 0x6A, /* 0110101 */ - // 0x0E, /* 0000111 */ - // 0x0C, /* 0000110 */ - // 0x18, /* 0001100 */ - // 0x18, /* 0001100 */ - // 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x7A, /* 0111101 */ + 0x6A, /* 0110101 */ + 0x0E, /* 0000111 */ + 0x0C, /* 0000110 */ + 0x18, /* 0001100 */ + 0x18, /* 0001100 */ + 0x00, /* 0000000 */ // /* // * code=232, hex=0xE8, ascii="!h" // */ - // 0x3C, /* 0011110 */ - // 0x18, /* 0001100 */ - // 0x3C, /* 0011110 */ - // 0x66, /* 0110011 */ - // 0x66, /* 0110011 */ - // 0x3C, /* 0011110 */ - // 0x18, /* 0001100 */ - // 0x3C, /* 0011110 */ - // 0x00, /* 0000000 */ + 0x3C, /* 0011110 */ + 0x18, /* 0001100 */ + 0x3C, /* 0011110 */ + 0x66, /* 0110011 */ + 0x66, /* 0110011 */ + 0x3C, /* 0011110 */ + 0x18, /* 0001100 */ + 0x3C, /* 0011110 */ + 0x00, /* 0000000 */ // /* // * code=233, hex=0xE9, ascii="!i" // */ - // 0x00, /* 0000000 */ - // 0x3C, /* 0011110 */ - // 0x66, /* 0110011 */ - // 0x66, /* 0110011 */ - // 0x7E, /* 0111111 */ - // 0x66, /* 0110011 */ - // 0x66, /* 0110011 */ - // 0x3C, /* 0011110 */ - // 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x3C, /* 0011110 */ + 0x66, /* 0110011 */ + 0x66, /* 0110011 */ + 0x7E, /* 0111111 */ + 0x66, /* 0110011 */ + 0x66, /* 0110011 */ + 0x3C, /* 0011110 */ + 0x00, /* 0000000 */ // /* // * code=234, hex=0xEA, ascii="!j" // */ - // 0x00, /* 0000000 */ - // 0x3C, /* 0011110 */ - // 0x66, /* 0110011 */ - // 0x66, /* 0110011 */ - // 0x66, /* 0110011 */ - // 0x66, /* 0110011 */ - // 0x24, /* 0010010 */ - // 0x66, /* 0110011 */ - // 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x3C, /* 0011110 */ + 0x66, /* 0110011 */ + 0x66, /* 0110011 */ + 0x66, /* 0110011 */ + 0x66, /* 0110011 */ + 0x24, /* 0010010 */ + 0x66, /* 0110011 */ + 0x00, /* 0000000 */ // /* // * code=235, hex=0xEB, ascii="!k" // */ - // 0x00, /* 0000000 */ - // 0x3C, /* 0011110 */ - // 0x60, /* 0110000 */ - // 0x30, /* 0011000 */ - // 0x18, /* 0001100 */ - // 0x3C, /* 0011110 */ - // 0x66, /* 0110011 */ - // 0x3C, /* 0011110 */ - // 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x3C, /* 0011110 */ + 0x60, /* 0110000 */ + 0x30, /* 0011000 */ + 0x18, /* 0001100 */ + 0x3C, /* 0011110 */ + 0x66, /* 0110011 */ + 0x3C, /* 0011110 */ + 0x00, /* 0000000 */ // /* // * code=236, hex=0xEC, ascii="!l" // */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x34, /* 0011010 */ - // 0x4A, /* 0100101 */ - // 0x4A, /* 0100101 */ - // 0x4A, /* 0100101 */ - // 0x34, /* 0011010 */ - // 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x34, /* 0011010 */ + 0x4A, /* 0100101 */ + 0x4A, /* 0100101 */ + 0x4A, /* 0100101 */ + 0x34, /* 0011010 */ + 0x00, /* 0000000 */ // /* // * code=237, hex=0xED, ascii="!m" // */ - // 0x04, /* 0000010 */ - // 0x3C, /* 0011110 */ - // 0x66, /* 0110011 */ - // 0x6E, /* 0110111 */ - // 0x76, /* 0111011 */ - // 0x66, /* 0110011 */ - // 0x3C, /* 0011110 */ - // 0x10, /* 0001000 */ - // 0x20, /* 0010000 */ + 0x04, /* 0000010 */ + 0x3C, /* 0011110 */ + 0x66, /* 0110011 */ + 0x6E, /* 0110111 */ + 0x76, /* 0111011 */ + 0x66, /* 0110011 */ + 0x3C, /* 0011110 */ + 0x10, /* 0001000 */ + 0x20, /* 0010000 */ // /* // * code=238, hex=0xEE, ascii="!n" // */ - // 0x1E, /* 0001111 */ - // 0x30, /* 0011000 */ - // 0x60, /* 0110000 */ - // 0x60, /* 0110000 */ - // 0x7E, /* 0111111 */ - // 0x60, /* 0110000 */ - // 0x30, /* 0011000 */ - // 0x1E, /* 0001111 */ - // 0x00, /* 0000000 */ + 0x1E, /* 0001111 */ + 0x30, /* 0011000 */ + 0x60, /* 0110000 */ + 0x60, /* 0110000 */ + 0x7E, /* 0111111 */ + 0x60, /* 0110000 */ + 0x30, /* 0011000 */ + 0x1E, /* 0001111 */ + 0x00, /* 0000000 */ // /* // * code=239, hex=0xEF, ascii="!o" // */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x3C, /* 0011110 */ - // 0x66, /* 0110011 */ - // 0x66, /* 0110011 */ - // 0x66, /* 0110011 */ - // 0x66, /* 0110011 */ - // 0x66, /* 0110011 */ - // 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x3C, /* 0011110 */ + 0x66, /* 0110011 */ + 0x66, /* 0110011 */ + 0x66, /* 0110011 */ + 0x66, /* 0110011 */ + 0x66, /* 0110011 */ + 0x00, /* 0000000 */ // /* // * code=240, hex=0xF0, ascii="!p" // */ - // 0x00, /* 0000000 */ - // 0x7C, /* 0111110 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x7C, /* 0111110 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x7C, /* 0111110 */ - // 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x7C, /* 0111110 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x7C, /* 0111110 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x7C, /* 0111110 */ + 0x00, /* 0000000 */ // /* // * code=241, hex=0xF1, ascii="!q" // */ - // 0x00, /* 0000000 */ - // 0x18, /* 0001100 */ - // 0x18, /* 0001100 */ - // 0x7E, /* 0111111 */ - // 0x18, /* 0001100 */ - // 0x18, /* 0001100 */ - // 0x00, /* 0000000 */ - // 0x7E, /* 0111111 */ - // 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x18, /* 0001100 */ + 0x18, /* 0001100 */ + 0x7E, /* 0111111 */ + 0x18, /* 0001100 */ + 0x18, /* 0001100 */ + 0x00, /* 0000000 */ + 0x7E, /* 0111111 */ + 0x00, /* 0000000 */ // /* // * code=242, hex=0xF2, ascii="!r" // */ - // 0x00, /* 0000000 */ - // 0x30, /* 0011000 */ - // 0x18, /* 0001100 */ - // 0x0C, /* 0000110 */ - // 0x18, /* 0001100 */ - // 0x30, /* 0011000 */ - // 0x00, /* 0000000 */ - // 0x3C, /* 0011110 */ - // 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x30, /* 0011000 */ + 0x18, /* 0001100 */ + 0x0C, /* 0000110 */ + 0x18, /* 0001100 */ + 0x30, /* 0011000 */ + 0x00, /* 0000000 */ + 0x3C, /* 0011110 */ + 0x00, /* 0000000 */ // /* // * code=243, hex=0xF3, ascii="!s" // */ - // 0x00, /* 0000000 */ - // 0x0C, /* 0000110 */ - // 0x18, /* 0001100 */ - // 0x30, /* 0011000 */ - // 0x18, /* 0001100 */ - // 0x0C, /* 0000110 */ - // 0x00, /* 0000000 */ - // 0x3C, /* 0011110 */ - // 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x0C, /* 0000110 */ + 0x18, /* 0001100 */ + 0x30, /* 0011000 */ + 0x18, /* 0001100 */ + 0x0C, /* 0000110 */ + 0x00, /* 0000000 */ + 0x3C, /* 0011110 */ + 0x00, /* 0000000 */ // /* // * code=244, hex=0xF4, ascii="!t" // */ - // 0x0C, /* 0000110 */ - // 0x1A, /* 0001101 */ - // 0x18, /* 0001100 */ - // 0x18, /* 0001100 */ - // 0x18, /* 0001100 */ - // 0x18, /* 0001100 */ - // 0x18, /* 0001100 */ - // 0x18, /* 0001100 */ - // 0x18, /* 0001100 */ + 0x0C, /* 0000110 */ + 0x1A, /* 0001101 */ + 0x18, /* 0001100 */ + 0x18, /* 0001100 */ + 0x18, /* 0001100 */ + 0x18, /* 0001100 */ + 0x18, /* 0001100 */ + 0x18, /* 0001100 */ + 0x18, /* 0001100 */ // /* // * code=245, hex=0xF5, ascii="!u" // */ - // 0x18, /* 0001100 */ - // 0x18, /* 0001100 */ - // 0x18, /* 0001100 */ - // 0x18, /* 0001100 */ - // 0x18, /* 0001100 */ - // 0x18, /* 0001100 */ - // 0x18, /* 0001100 */ - // 0x58, /* 0101100 */ - // 0x30, /* 0011000 */ + 0x18, /* 0001100 */ + 0x18, /* 0001100 */ + 0x18, /* 0001100 */ + 0x18, /* 0001100 */ + 0x18, /* 0001100 */ + 0x18, /* 0001100 */ + 0x18, /* 0001100 */ + 0x58, /* 0101100 */ + 0x30, /* 0011000 */ // /* // * code=246, hex=0xF6, ascii="!v" // */ - // 0x00, /* 0000000 */ - // 0x18, /* 0001100 */ - // 0x18, /* 0001100 */ - // 0x00, /* 0000000 */ - // 0x7E, /* 0111111 */ - // 0x00, /* 0000000 */ - // 0x18, /* 0001100 */ - // 0x18, /* 0001100 */ - // 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x18, /* 0001100 */ + 0x18, /* 0001100 */ + 0x00, /* 0000000 */ + 0x7E, /* 0111111 */ + 0x00, /* 0000000 */ + 0x18, /* 0001100 */ + 0x18, /* 0001100 */ + 0x00, /* 0000000 */ // /* // * code=247, hex=0xF7, ascii="!w" // */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x1A, /* 0001101 */ - // 0x76, /* 0111011 */ - // 0x00, /* 0000000 */ - // 0x1A, /* 0001101 */ - // 0x76, /* 0111011 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x1A, /* 0001101 */ + 0x76, /* 0111011 */ + 0x00, /* 0000000 */ + 0x1A, /* 0001101 */ + 0x76, /* 0111011 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ // /* // * code=248, hex=0xF8, ascii="!x" // */ - // 0x00, /* 0000000 */ - // 0x3C, /* 0011110 */ - // 0x66, /* 0110011 */ - // 0x66, /* 0110011 */ - // 0x3C, /* 0011110 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x3C, /* 0011110 */ + 0x66, /* 0110011 */ + 0x66, /* 0110011 */ + 0x3C, /* 0011110 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ // /* // * code=249, hex=0xF9, ascii="!y" // */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x18, /* 0001100 */ - // 0x3C, /* 0011110 */ - // 0x3C, /* 0011110 */ - // 0x18, /* 0001100 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x18, /* 0001100 */ + 0x3C, /* 0011110 */ + 0x3C, /* 0011110 */ + 0x18, /* 0001100 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ // /* // * code=250, hex=0xFA, ascii="!z" // */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x18, /* 0001100 */ - // 0x18, /* 0001100 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x18, /* 0001100 */ + 0x18, /* 0001100 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ // /* // * code=251, hex=0xFB, ascii="!{" // */ - // 0x0E, /* 0000111 */ - // 0x0C, /* 0000110 */ - // 0x0C, /* 0000110 */ - // 0x0C, /* 0000110 */ - // 0x0C, /* 0000110 */ - // 0x6C, /* 0110110 */ - // 0x3C, /* 0011110 */ - // 0x0C, /* 0000110 */ - // 0x00, /* 0000000 */ + 0x0E, /* 0000111 */ + 0x0C, /* 0000110 */ + 0x0C, /* 0000110 */ + 0x0C, /* 0000110 */ + 0x0C, /* 0000110 */ + 0x6C, /* 0110110 */ + 0x3C, /* 0011110 */ + 0x0C, /* 0000110 */ + 0x00, /* 0000000 */ // /* // * code=252, hex=0xFC, ascii="!|" // */ - // 0x00, /* 0000000 */ - // 0x78, /* 0111100 */ - // 0x6C, /* 0110110 */ - // 0x6C, /* 0110110 */ - // 0x6C, /* 0110110 */ - // 0x6C, /* 0110110 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x78, /* 0111100 */ + 0x6C, /* 0110110 */ + 0x6C, /* 0110110 */ + 0x6C, /* 0110110 */ + 0x6C, /* 0110110 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ // /* // * code=253, hex=0xFD, ascii="!}" // */ - // 0x00, /* 0000000 */ - // 0x38, /* 0011100 */ - // 0x4C, /* 0100110 */ - // 0x18, /* 0001100 */ - // 0x30, /* 0011000 */ - // 0x7C, /* 0111110 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x38, /* 0011100 */ + 0x4C, /* 0100110 */ + 0x18, /* 0001100 */ + 0x30, /* 0011000 */ + 0x7C, /* 0111110 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ // /* // * code=254, hex=0xFE, ascii="!~" // */ - // 0x00, /* 0000000 */ - // 0x7C, /* 0111110 */ - // 0x7C, /* 0111110 */ - // 0x7C, /* 0111110 */ - // 0x7C, /* 0111110 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x7C, /* 0111110 */ + 0x7C, /* 0111110 */ + 0x7C, /* 0111110 */ + 0x7C, /* 0111110 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ +#endif + +#if 0 // skip 255 = NBSP // /* // * code=255, hex=0xFF, ascii="!^Ÿ" // */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ - // 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ + 0x00, /* 0000000 */ +#endif }; From 55c9741f0147f36e0cc73d9b35f13eb654f1fd26 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Wed, 19 Nov 2025 17:40:11 +0100 Subject: [PATCH 101/170] new functions prototypes, minor fixes * prototypes for UTF-8 ==> wchar16 conversion * minor fixes --- wled00/src/font/codepage437.cpp | 8 +++----- wled00/src/font/codepages.h | 18 ++++++++++++++---- wled00/src/font/unicodetool.cpp | 17 +++++++++++++++++ 3 files changed, 34 insertions(+), 9 deletions(-) create mode 100644 wled00/src/font/unicodetool.cpp diff --git a/wled00/src/font/codepage437.cpp b/wled00/src/font/codepage437.cpp index cea00454..4adadd8c 100644 --- a/wled00/src/font/codepage437.cpp +++ b/wled00/src/font/codepage437.cpp @@ -1,8 +1,9 @@ #if defined(WLED_ENABLE_FULL_FONTS) #include "codepages.h" +#include -// translates unicode 2-byte (UTF-16) "code points" into corresponding characters in codepage 347 (IBM PC aka PC-8) +// translates unicode 2-byte (UTF-16) "code points" into corresponding characters in codepage 437 (IBM PC aka PC-8) // based on a table from https://en.wikipedia.org/wiki/Code_page_437#Character_set uint16_t wchar16ToCodepage437(uint16_t wideChar) { @@ -205,7 +206,4 @@ uint16_t wchar16ToCodepage437(uint16_t wideChar) { } - - - -#endif \ No newline at end of file +#endif diff --git a/wled00/src/font/codepages.h b/wled00/src/font/codepages.h index 4ed5799e..829fcf0f 100644 --- a/wled00/src/font/codepages.h +++ b/wled00/src/font/codepages.h @@ -1,5 +1,15 @@ -#include -#include +#ifndef WLED_CODEPAGES_H +#define WLED_CODEPAGES_H +#include // needed to get uint16_t definition -// translates unicode 2-byte (UTF-16) "code points" into corresponding characters in codepage 347 (IBM PC aka PC-8) -uint16_t wchar16ToCodepage437(uint16_t wideChar); // codepage437.cpp \ No newline at end of file +// translates unicode UTF-8 "character code" into 2-byte "code point" (reduced UTF-16) +uint16_t unicodeToWchar16(const char* utf8, size_t maxLen); // unicodetool.cpp + +// returns a pointer to the next unicode item - can be used to "advance" conversion after unicodeToWchar16() +// return nullptr at end of input +const char* nextUnicode(const char* utf8, size_t maxLen); // unicodetool.cpp + +// translates unicode 2-byte (UTF-16) "code point" into corresponding character in codepage 437 (IBM PC aka PC-8) +uint16_t wchar16ToCodepage437(uint16_t wideChar); // codepage437.cpp + +#endif diff --git a/wled00/src/font/unicodetool.cpp b/wled00/src/font/unicodetool.cpp new file mode 100644 index 00000000..9388247b --- /dev/null +++ b/wled00/src/font/unicodetool.cpp @@ -0,0 +1,17 @@ +#if defined(WLED_ENABLE_FULL_FONTS) + +#include "codepages.h" +#include + +// translates the next unicode UTF-8 item to 2-byte "code points" (reduced UTF-16) +uint16_t unicodeToWchar16(const char* utf8, size_t maxLen) { + // to be implemented +} + +// returns a pointer to the next unicode item - can be used to "advance" conversion after unicodeToWchar16() +// return nullptr at end of input +const char* nextUnicode(const char* utf8, size_t maxLen) { + // to be implemented +} + +#endif From 8219feb41e1d049590c7e46c73a3c5d0e0de2149 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Wed, 19 Nov 2025 18:04:09 +0100 Subject: [PATCH 102/170] more dummies just to sketch out the final implementation --- wled00/FX.h | 4 ++++ wled00/src/font/unicodetool.cpp | 11 +++++++++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/wled00/FX.h b/wled00/FX.h index ad1fd292..42897cb4 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -823,8 +823,12 @@ typedef struct Segment { inline void drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, CRGB c, bool soft = false, uint8_t depth = UINT8_MAX) { drawLine(x0, y0, x1, y1, uint32_t(c) & 0x00FFFFFF, soft, depth); } // automatic inline void drawArc(unsigned x0, unsigned y0, int radius, uint32_t color, uint32_t fillColor = 0); inline void drawArc(unsigned x0, unsigned y0, int radius, CRGB color, CRGB fillColor = BLACK) { drawArc(x0, y0, radius, uint32_t(color) & 0x00FFFFFF, uint32_t(fillColor) & 0x00FFFFFF); } // automatic inline + void drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, uint8_t h, uint32_t color, uint32_t col2 = 0, bool drawShadow = false); inline void drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, uint8_t h, CRGB c, CRGB c2) { drawCharacter(chr, x, y, w, h, uint32_t(c) & 0x00FFFFFF, uint32_t(c2) & 0x00FFFFFF); } // automatic inline + // unicode-aware wrapper for drawCharacter(), to be called from mode_2Dscrollingtext() + void drawText(const unsigned char* Text, int16_t x, int16_t y, uint8_t w, uint8_t h, uint32_t color, uint32_t col2 = 0, bool drawShadow = false); + void wu_pixel(uint32_t x, uint32_t y, CRGB c); //void blur1d(fract8 blur_amount); // blur all rows in 1 dimension void blur2d(fract8 blur_amount) { blur(blur_amount); } diff --git a/wled00/src/font/unicodetool.cpp b/wled00/src/font/unicodetool.cpp index 9388247b..05b86e47 100644 --- a/wled00/src/font/unicodetool.cpp +++ b/wled00/src/font/unicodetool.cpp @@ -5,13 +5,20 @@ // translates the next unicode UTF-8 item to 2-byte "code points" (reduced UTF-16) uint16_t unicodeToWchar16(const char* utf8, size_t maxLen) { - // to be implemented + // TODO: implement proper UTF‑8 → reduced UTF‑16 decoding + (void)utf8; + (void)maxLen; + return 0; // sentinel: "no character" } // returns a pointer to the next unicode item - can be used to "advance" conversion after unicodeToWchar16() // return nullptr at end of input const char* nextUnicode(const char* utf8, size_t maxLen) { - // to be implemented + (void)maxLen; + if (!utf8) return nullptr; + if (strlen(utf8)>0) return utf8+1; + else return nullptr; // last code read + // TODO: implement proper UTF‑8 iteration } #endif From 55976958653d8208fa6d93d2b5caf9d8e585c335 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Wed, 19 Nov 2025 23:48:30 +0100 Subject: [PATCH 103/170] UFT-8 to UTF-16 decoder MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * should properly decode all unicodes that fit into 2bytes UTF-16 * with error handling for well-known "malformed UTF-8" expoits * puh, this stuff looks simple but the details are CRAZY 😝 --- wled00/src/font/codepages.h | 10 +++-- wled00/src/font/unicodetool.cpp | 68 +++++++++++++++++++++++++++------ 2 files changed, 62 insertions(+), 16 deletions(-) diff --git a/wled00/src/font/codepages.h b/wled00/src/font/codepages.h index 829fcf0f..d4d1badd 100644 --- a/wled00/src/font/codepages.h +++ b/wled00/src/font/codepages.h @@ -2,14 +2,16 @@ #define WLED_CODEPAGES_H #include // needed to get uint16_t definition -// translates unicode UTF-8 "character code" into 2-byte "code point" (reduced UTF-16) -uint16_t unicodeToWchar16(const char* utf8, size_t maxLen); // unicodetool.cpp +// UTF‑8 → reduced UTF‑16 decoding +// translates the next unicode UTF-8 item into a 2-byte "code point" +// return "•" in case of input errors, and for unsupported/invalid UTF-8 +uint16_t unicodeToWchar16(const unsigned char* utf8, size_t maxLen); // unicodetool.cpp // returns a pointer to the next unicode item - can be used to "advance" conversion after unicodeToWchar16() // return nullptr at end of input -const char* nextUnicode(const char* utf8, size_t maxLen); // unicodetool.cpp +const unsigned char* nextUnicode(const unsigned char* utf8, size_t maxLen); // unicodetool.cpp // translates unicode 2-byte (UTF-16) "code point" into corresponding character in codepage 437 (IBM PC aka PC-8) -uint16_t wchar16ToCodepage437(uint16_t wideChar); // codepage437.cpp +uint16_t wchar16ToCodepage437(uint16_t wideChar); // codepage437.cpp #endif diff --git a/wled00/src/font/unicodetool.cpp b/wled00/src/font/unicodetool.cpp index 05b86e47..a0d63ce4 100644 --- a/wled00/src/font/unicodetool.cpp +++ b/wled00/src/font/unicodetool.cpp @@ -2,23 +2,67 @@ #include "codepages.h" #include +#include // adds std::min / std::max +using namespace std; // I don't want to write std::min -// translates the next unicode UTF-8 item to 2-byte "code points" (reduced UTF-16) -uint16_t unicodeToWchar16(const char* utf8, size_t maxLen) { - // TODO: implement proper UTF‑8 → reduced UTF‑16 decoding - (void)utf8; - (void)maxLen; - return 0; // sentinel: "no character" +// Helper to validate continuation byte +static inline bool isValidContinuation(unsigned char byte) { + return (byte & 0b11000000) == 0b10000000; +} + +// UTF‑8 → reduced UTF‑16 decoding +// translates the next unicode UTF-8 item into a 2-byte "code point" +uint16_t unicodeToWchar16(const unsigned char* utf8, size_t maxLen) { + if (!utf8 || (maxLen < 1) || *utf8 == '\0') return 0; // sanity check + + size_t length = strlen((const char*) utf8); + length = min(length, maxLen); + if (length < 1) return 0; // sanity check + + unsigned char ch0 = *utf8; // get leading character + uint32_t codepoint = ch0; // our resulting UTF-16 code point + + if (ch0 <= 0x7F) return ch0; // 1-byte ASCII (0x00-0x7F) + if ((ch0 & 0b11100000) == 0b11000000) { // 2-byte sequence (0xC2-0xDF) + // uses lower 5 bits of the first byte, and lower 6 bits from the next byte + if (length < 2 || !isValidContinuation(utf8[1])) return 0x2022; // • for malformed + codepoint = ((ch0 & 0b00011111) << 6) | (utf8[1] & 0b00111111); + if (codepoint < 0x80) return 0x2022; // Reject overlong encodings (must be >= 0x80) + return uint16_t(codepoint); + } else { + if ((ch0 & 0b11110000) == 0b11100000) { // 3-byte sequence (0xE0-0xEF) + // uses lower 4 bits of the first byte, and lower 6 bits from the next byte, lower 6 bits from third byte + if (length < 3 || !isValidContinuation(utf8[1]) || !isValidContinuation(utf8[2])) return 0x2022; // • for malformed + codepoint = ((ch0 & 0b00001111) << 12) | ((utf8[1] & 0b00111111) << 6) | (utf8[2] & 0b00111111); + if (codepoint < 0x800) return 0x2022; // Reject overlong encodings (must be >= 0x800) + if (codepoint >= 0xD800 && codepoint <= 0xDFFF) return 0x2022; // Reject UTF-16 surrogate pairs (U+D800..U+DFFF) + if (codepoint >= 0x010000) codepoint = 0x2022; // result exceeds uint16_t => return • for "unknown" + return uint16_t(codepoint); + } + } + // 4-byte sequence or invalid lead byte - since we only support up to 0xFFFF, return error marker + return 0x2022; // • for unsupported/invalid } // returns a pointer to the next unicode item - can be used to "advance" conversion after unicodeToWchar16() // return nullptr at end of input -const char* nextUnicode(const char* utf8, size_t maxLen) { - (void)maxLen; - if (!utf8) return nullptr; - if (strlen(utf8)>0) return utf8+1; - else return nullptr; // last code read - // TODO: implement proper UTF‑8 iteration +const unsigned char* nextUnicode(const unsigned char* utf8, size_t maxLen) { + if ((!utf8) || (maxLen < 1) || (*utf8 == 0)) return nullptr; // sanity check + size_t length = strlen((const char*) utf8); // safe, because utf8 is a C string with proper NUL termination + length = min(length, maxLen); + if (length < 1) return nullptr; // we are at end of input + + unsigned char ch0 = *utf8; // get leading character + size_t codeLength = 1; // default: 1-byte ASCII + if (ch0 >= 0x80) { + if ((ch0 & 0b11100000) == 0b11000000) codeLength = 2; // 2-byte sequence + else if ((ch0 & 0b11110000) == 0b11100000) codeLength = 3; // 3-byte sequence + else if ((ch0 & 0b11111000) == 0b11110000) codeLength = 4; // 4-byte sequence (not fully supported but we need to skip it) + else codeLength = 1; // Skip single invalid byte and try to resync + } + + if (length < codeLength) return nullptr; // Check if we have enough bytes + else return utf8 + codeLength; // success: advance stream } #endif From 6a4716e49057fe2ae48e7537c897c49d352f515e Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Thu, 20 Nov 2025 00:12:26 +0100 Subject: [PATCH 104/170] decoder robustness improvements, and some nitpick --- wled00/FX.h | 3 ++- wled00/src/font/unicodetool.cpp | 13 ++++++++++--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/wled00/FX.h b/wled00/FX.h index 42897cb4..ee39887f 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -827,7 +827,8 @@ typedef struct Segment { void drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, uint8_t h, uint32_t color, uint32_t col2 = 0, bool drawShadow = false); inline void drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, uint8_t h, CRGB c, CRGB c2) { drawCharacter(chr, x, y, w, h, uint32_t(c) & 0x00FFFFFF, uint32_t(c2) & 0x00FFFFFF); } // automatic inline // unicode-aware wrapper for drawCharacter(), to be called from mode_2Dscrollingtext() - void drawText(const unsigned char* Text, int16_t x, int16_t y, uint8_t w, uint8_t h, uint32_t color, uint32_t col2 = 0, bool drawShadow = false); + void drawText(const unsigned char* text, size_t maxLen, int16_t x, int16_t y, uint8_t w, uint8_t h, uint32_t color, uint32_t col2 = 0, bool drawShadow = false); + // #if !WLED_ENABLE_FULL_FONTS => drawText() will fall back to just forwarding each char to drawCharacter() void wu_pixel(uint32_t x, uint32_t y, CRGB c); //void blur1d(fract8 blur_amount); // blur all rows in 1 dimension diff --git a/wled00/src/font/unicodetool.cpp b/wled00/src/font/unicodetool.cpp index a0d63ce4..37bae2a4 100644 --- a/wled00/src/font/unicodetool.cpp +++ b/wled00/src/font/unicodetool.cpp @@ -53,7 +53,9 @@ const unsigned char* nextUnicode(const unsigned char* utf8, size_t maxLen) { if (length < 1) return nullptr; // we are at end of input unsigned char ch0 = *utf8; // get leading character - size_t codeLength = 1; // default: 1-byte ASCII + + // Calculate code length based on lead byte + size_t codeLength = 1; // default: 1-byte ASCII if (ch0 >= 0x80) { if ((ch0 & 0b11100000) == 0b11000000) codeLength = 2; // 2-byte sequence else if ((ch0 & 0b11110000) == 0b11100000) codeLength = 3; // 3-byte sequence @@ -61,8 +63,13 @@ const unsigned char* nextUnicode(const unsigned char* utf8, size_t maxLen) { else codeLength = 1; // Skip single invalid byte and try to resync } - if (length < codeLength) return nullptr; // Check if we have enough bytes - else return utf8 + codeLength; // success: advance stream + // handle invalid continuation bytes + if ((codeLength >= 2) && (length < 2 || !isValidContinuation(utf8[1]))) codeLength = 1; // try to re-sync + if ((codeLength >= 3) && (length < 3 || !isValidContinuation(utf8[2]))) codeLength = 1; // try to re-sync + if ((codeLength >= 4) && (length < 4 || !isValidContinuation(utf8[3]))) codeLength = 1; // try to re-sync + + if (length < codeLength) return nullptr; // Check if we have enough bytes + else return utf8 + codeLength; // success: advance stream } #endif From 0b1d22b8f1f67eef95495cf422b5a954f5712e26 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Thu, 20 Nov 2025 00:34:33 +0100 Subject: [PATCH 105/170] error codes --- wled00/src/font/codepages.h | 3 +++ wled00/src/font/unicodetool.cpp | 14 +++++++------- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/wled00/src/font/codepages.h b/wled00/src/font/codepages.h index d4d1badd..b57de32d 100644 --- a/wled00/src/font/codepages.h +++ b/wled00/src/font/codepages.h @@ -2,6 +2,9 @@ #define WLED_CODEPAGES_H #include // needed to get uint16_t definition +constexpr uint16_t UNKNOWN_CODE = 0x2022; // • +constexpr uint16_t BAD_CODE = 0x2022; // • + // UTF‑8 → reduced UTF‑16 decoding // translates the next unicode UTF-8 item into a 2-byte "code point" // return "•" in case of input errors, and for unsupported/invalid UTF-8 diff --git a/wled00/src/font/unicodetool.cpp b/wled00/src/font/unicodetool.cpp index 37bae2a4..0fcb9cc8 100644 --- a/wled00/src/font/unicodetool.cpp +++ b/wled00/src/font/unicodetool.cpp @@ -25,23 +25,23 @@ uint16_t unicodeToWchar16(const unsigned char* utf8, size_t maxLen) { if (ch0 <= 0x7F) return ch0; // 1-byte ASCII (0x00-0x7F) if ((ch0 & 0b11100000) == 0b11000000) { // 2-byte sequence (0xC2-0xDF) // uses lower 5 bits of the first byte, and lower 6 bits from the next byte - if (length < 2 || !isValidContinuation(utf8[1])) return 0x2022; // • for malformed + if (length < 2 || !isValidContinuation(utf8[1])) return BAD_CODE; // malformed codepoint = ((ch0 & 0b00011111) << 6) | (utf8[1] & 0b00111111); - if (codepoint < 0x80) return 0x2022; // Reject overlong encodings (must be >= 0x80) + if (codepoint < 0x80) return UNKNOWN_CODE; // Reject overlong encodings (must be >= 0x80) return uint16_t(codepoint); } else { if ((ch0 & 0b11110000) == 0b11100000) { // 3-byte sequence (0xE0-0xEF) // uses lower 4 bits of the first byte, and lower 6 bits from the next byte, lower 6 bits from third byte - if (length < 3 || !isValidContinuation(utf8[1]) || !isValidContinuation(utf8[2])) return 0x2022; // • for malformed + if (length < 3 || !isValidContinuation(utf8[1]) || !isValidContinuation(utf8[2])) return BAD_CODE; // malformed codepoint = ((ch0 & 0b00001111) << 12) | ((utf8[1] & 0b00111111) << 6) | (utf8[2] & 0b00111111); - if (codepoint < 0x800) return 0x2022; // Reject overlong encodings (must be >= 0x800) - if (codepoint >= 0xD800 && codepoint <= 0xDFFF) return 0x2022; // Reject UTF-16 surrogate pairs (U+D800..U+DFFF) - if (codepoint >= 0x010000) codepoint = 0x2022; // result exceeds uint16_t => return • for "unknown" + if (codepoint < 0x800) return UNKNOWN_CODE; // Reject overlong encodings (must be >= 0x800) + if (codepoint >= 0xD800 && codepoint <= 0xDFFF) return UNKNOWN_CODE; // Reject UTF-16 surrogate pairs (U+D800..U+DFFF) + if (codepoint >= 0x010000) codepoint = UNKNOWN_CODE; // result exceeds uint16_t => "unknown" return uint16_t(codepoint); } } // 4-byte sequence or invalid lead byte - since we only support up to 0xFFFF, return error marker - return 0x2022; // • for unsupported/invalid + return BAD_CODE; // unsupported/invalid } // returns a pointer to the next unicode item - can be used to "advance" conversion after unicodeToWchar16() From e4f42942336068630dc75a2f48d5dac7cd30c1d0 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Thu, 20 Nov 2025 00:41:21 +0100 Subject: [PATCH 106/170] strlen => strnlen --- wled00/src/font/unicodetool.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wled00/src/font/unicodetool.cpp b/wled00/src/font/unicodetool.cpp index 0fcb9cc8..0fe775c1 100644 --- a/wled00/src/font/unicodetool.cpp +++ b/wled00/src/font/unicodetool.cpp @@ -15,7 +15,7 @@ static inline bool isValidContinuation(unsigned char byte) { uint16_t unicodeToWchar16(const unsigned char* utf8, size_t maxLen) { if (!utf8 || (maxLen < 1) || *utf8 == '\0') return 0; // sanity check - size_t length = strlen((const char*) utf8); + size_t length = strnlen((const char*) utf8, maxLen); length = min(length, maxLen); if (length < 1) return 0; // sanity check @@ -48,7 +48,7 @@ uint16_t unicodeToWchar16(const unsigned char* utf8, size_t maxLen) { // return nullptr at end of input const unsigned char* nextUnicode(const unsigned char* utf8, size_t maxLen) { if ((!utf8) || (maxLen < 1) || (*utf8 == 0)) return nullptr; // sanity check - size_t length = strlen((const char*) utf8); // safe, because utf8 is a C string with proper NUL termination + size_t length = strnlen((const char*) utf8, maxLen); length = min(length, maxLen); if (length < 1) return nullptr; // we are at end of input From c2b87f863fb85cb515b81c717c72d1a0cbd4abbe Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Thu, 20 Nov 2025 00:54:25 +0100 Subject: [PATCH 107/170] minor update --- wled00/src/font/codepages.h | 1 + 1 file changed, 1 insertion(+) diff --git a/wled00/src/font/codepages.h b/wled00/src/font/codepages.h index b57de32d..4b45c565 100644 --- a/wled00/src/font/codepages.h +++ b/wled00/src/font/codepages.h @@ -1,6 +1,7 @@ #ifndef WLED_CODEPAGES_H #define WLED_CODEPAGES_H #include // needed to get uint16_t definition +#include // helps for code analysis with clang constexpr uint16_t UNKNOWN_CODE = 0x2022; // • constexpr uint16_t BAD_CODE = 0x2022; // • From 29e0afc0d76986f84b5cbca194143a51fec6bc6b Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Thu, 20 Nov 2025 01:42:04 +0100 Subject: [PATCH 108/170] align error characters always use "small dot" for unsupported char, "bigger dot" to indicate unicode error --- wled00/src/font/codepage437.cpp | 6 ++++-- wled00/src/font/codepages.h | 5 +++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/wled00/src/font/codepage437.cpp b/wled00/src/font/codepage437.cpp index 4adadd8c..a9e8c5b1 100644 --- a/wled00/src/font/codepage437.cpp +++ b/wled00/src/font/codepage437.cpp @@ -3,6 +3,8 @@ #include "codepages.h" #include +constexpr uint8_t CP437_UNKNOWN = 250; // small middle dot · // not sure if we better return " " ? + // translates unicode 2-byte (UTF-16) "code points" into corresponding characters in codepage 437 (IBM PC aka PC-8) // based on a table from https://en.wikipedia.org/wiki/Code_page_437#Character_set uint16_t wchar16ToCodepage437(uint16_t wideChar) { @@ -45,7 +47,7 @@ uint16_t wchar16ToCodepage437(uint16_t wideChar) { case 0x25BC: return 0x1F; break; // ▼ // characters 127 - 254 - case 0x2302: return 0x7F; break; // ⌂ + case 0x2302: return 0x7F; break; // ⌂ (aka DEL) case 0x00C7: return 0x80; break; // Ç case 0x00FC: return 0x81; break; // ü case 0x00E9: return 0x82; break; // é @@ -201,7 +203,7 @@ uint16_t wchar16ToCodepage437(uint16_t wideChar) { // everything else: unknown //default: return 32; // blank - default: return 250; // small middle dot · + default: return CP437_UNKNOWN; // small middle dot · } } diff --git a/wled00/src/font/codepages.h b/wled00/src/font/codepages.h index 4b45c565..edb2cb99 100644 --- a/wled00/src/font/codepages.h +++ b/wled00/src/font/codepages.h @@ -3,8 +3,9 @@ #include // needed to get uint16_t definition #include // helps for code analysis with clang -constexpr uint16_t UNKNOWN_CODE = 0x2022; // • -constexpr uint16_t BAD_CODE = 0x2022; // • +//constexpr uint16_t UNKNOWN_CODE = 0x2219; // ∙ multiplication dot +constexpr uint16_t UNKNOWN_CODE = 0x00B7; // · middle dot +constexpr uint16_t BAD_CODE = 0x2022; // • bigger dot // UTF‑8 → reduced UTF‑16 decoding // translates the next unicode UTF-8 item into a 2-byte "code point" From c3b8e0182b6dd21c24b11e2a4e8b066e80f8e77d Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Thu, 20 Nov 2025 02:07:30 +0100 Subject: [PATCH 109/170] plan: next steps just an empty framework --- wled00/FX_2Dfcn.cpp | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/wled00/FX_2Dfcn.cpp b/wled00/FX_2Dfcn.cpp index 0b1c01f6..c0a9a774 100644 --- a/wled00/FX_2Dfcn.cpp +++ b/wled00/FX_2Dfcn.cpp @@ -882,6 +882,27 @@ bool Segment::jsonToPixels(char * name, uint8_t fileNr) { #include "src/font/console_font_5x12.h" #include "src/font/console_font_6x8.h" #include "src/font/console_font_7x9.h" +#if defined(WLED_ENABLE_FULL_FONTS) +#include "src/font/codepages.h" +#endif + +//upstream compatibility +#if !defined(WLED_MAX_SEGNAME_LEN) +#define WLED_MAX_SEGNAME_LEN 32 // ToDO: inrease default to 48 +#endif + +// unicode-aware wrapper for drawCharacter(), to be called from mode_2Dscrollingtext() +void Segment::drawText(const unsigned char* text, size_t maxLen, int16_t x, int16_t y, uint8_t w, uint8_t h, uint32_t color, uint32_t col2, bool drawShadow) { + size_t textLength = min(maxLen, size_t(WLED_MAX_SEGNAME_LEN)); +#if defined(WLED_ENABLE_FULL_FONTS) + uint16_t decoded_text[WLED_MAX_SEGNAME_LEN+1] = { 0 }; // UTF-16 converted text. Cannot be longer than WLED_MAX_SEGNAME_LEN + // ToDO: UTF-8 decode text into local buffer => decoded_text + // ToDO: decoded_text to CP437 => decoded_text (in-place conversion) +#else + const unsigned char* decoded_text = text; // fallback +#endif + // ToDO: pass decoded characters to drawCharacter() +} // draws a raster font character on canvas // only supports: 4x6=24, 5x8=40, 5x12=60, 6x8=48 and 7x9=63 fonts ATM From a3ccc5a8eb43f8e78451cf56c8e9edf1354e2652 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Thu, 20 Nov 2025 02:36:12 +0100 Subject: [PATCH 110/170] work in progress it just compiles, don't ship it ! --- wled00/FX_2Dfcn.cpp | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/wled00/FX_2Dfcn.cpp b/wled00/FX_2Dfcn.cpp index c0a9a774..27605c22 100644 --- a/wled00/FX_2Dfcn.cpp +++ b/wled00/FX_2Dfcn.cpp @@ -894,10 +894,19 @@ bool Segment::jsonToPixels(char * name, uint8_t fileNr) { // unicode-aware wrapper for drawCharacter(), to be called from mode_2Dscrollingtext() void Segment::drawText(const unsigned char* text, size_t maxLen, int16_t x, int16_t y, uint8_t w, uint8_t h, uint32_t color, uint32_t col2, bool drawShadow) { size_t textLength = min(maxLen, size_t(WLED_MAX_SEGNAME_LEN)); + // ToDO: find font _first/_last, based on width / height #if defined(WLED_ENABLE_FULL_FONTS) uint16_t decoded_text[WLED_MAX_SEGNAME_LEN+1] = { 0 }; // UTF-16 converted text. Cannot be longer than WLED_MAX_SEGNAME_LEN - // ToDO: UTF-8 decode text into local buffer => decoded_text - // ToDO: decoded_text to CP437 => decoded_text (in-place conversion) + size_t utf16_index = 0; + for(const unsigned char* now = text; now != nullptr && now[0] != 0; now = nextUnicode(now, maxLen)) { + decoded_text[utf16_index] = unicodeToWchar16(now, maxLen); // UTF-8 decode into decoded_text + decoded_text[utf16_index] = wchar16ToCodepage437(decoded_text[utf16_index]); // decoded_text to CP437 (in-place conversion) + // toDo: ensure that decoded_text[i] is between console_font_YxZ_first and console_font_YxZ_last + // if (chr < 32 || chr > 126) --> clamp chr + // chr -= 32; // align with font table entries + utf16_index++; + } + decoded_text[utf16_index] = 0; // NUL terminate string #else const unsigned char* decoded_text = text; // fallback #endif @@ -908,8 +917,13 @@ void Segment::drawText(const unsigned char* text, size_t maxLen, int16_t x, int1 // only supports: 4x6=24, 5x8=40, 5x12=60, 6x8=48 and 7x9=63 fonts ATM void Segment::drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, uint8_t h, uint32_t color, uint32_t col2, bool drawShadow) { if (!isActive()) return; // not active - if (chr < 32 || chr > 126) return; // only ASCII 32-126 supported +#if !defined(WLED_ENABLE_FULL_FONTS) + if (chr < 32 || chr > 126) return; // legacy mode - only ASCII 32-126 supported chr -= 32; // align with font table entries +#else + // ToDO: clamp to font limits +#endif + const uint16_t cols = virtualWidth(); const uint16_t rows = virtualHeight(); const int font = w*h; @@ -926,7 +940,10 @@ void Segment::drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, if (y0 >= rows) break; // drawing off-screen uint8_t bits = 0; uint8_t bits_up = 0; // WLEDMM this is the previous line: font[(chr * h) + i -1] - switch (font) { + + // ToDO: move font selection logic into separate function + + switch (font) { // font = w * h case 24: bits = pgm_read_byte_near(&console_font_4x6[(chr * h) + i]); if ((i>0) && drawShadow) bits_up = pgm_read_byte_near(&console_font_4x6[(chr * h) + i -1]); break; // 5x8 font From 0a593b4d39b5f1cca37c30d8d98c09c032e61d79 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Thu, 20 Nov 2025 11:41:26 +0100 Subject: [PATCH 111/170] codepage update --- wled00/src/font/codepage437.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/wled00/src/font/codepage437.cpp b/wled00/src/font/codepage437.cpp index a9e8c5b1..99ef6b0e 100644 --- a/wled00/src/font/codepage437.cpp +++ b/wled00/src/font/codepage437.cpp @@ -168,7 +168,7 @@ uint16_t wchar16ToCodepage437(uint16_t wideChar) { case 0x2321: return 0xF5; break; // ⌡ case 0x00F7: return 0xF6; break; // ÷ case 0x2248: return 0xF7; break; // ≈ - case 0x00B0: return 0xF8; break; // ° + case 0x00B0: return 0xF8; break; // ° degree case 0x2219: return 0xF9; break; // ∙ multiplication dot case 0x00B7: return 0xFA; break; // · middle dot case 0x221A: return 0xFB; break; // √ @@ -194,6 +194,7 @@ uint16_t wchar16ToCodepage437(uint16_t wideChar) { case 0x2300: return 237; break; // diameter ⌀ case 0x00D8: return 237; break; // 0 strikethrough Ø case 0x00F8: return 237; break; // 0 strikethrough small ø + case 0x02DA: return 0xF8; break; // small circle (up) ˚ case 0x2208: return 238; break; // element-of ∈ case 0x017F: return 244; break; // long S ſ From 45f793b3385202aab0f5c4b2447c7b90d413a85e Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Thu, 20 Nov 2025 13:57:55 +0100 Subject: [PATCH 112/170] =?UTF-8?q?first=20light=20=F0=9F=91=8D?= =?UTF-8?q?=F0=9F=98=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * idea seems to work * scrolling is broken, probably I need to create a unicode-aware ``strlen`` --- wled00/FX.cpp | 23 ++++++++++++++++++--- wled00/FX.h | 2 +- wled00/FX_2Dfcn.cpp | 50 ++++++++++++++++++++++++++++----------------- 3 files changed, 52 insertions(+), 23 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index e9d8c01e..e7104156 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -6810,9 +6810,15 @@ uint16_t mode_2Dscrollingtext(void) { case 5: letterWidth = 5; letterHeight = 12; break; } const int yoffset = map(SEGMENT.intensity, 0, 255, -rows/2, rows/2) + (rows-letterHeight)/2; - char text[33] = {'\0'}; - unsigned maxLen = (SEGMENT.name) ? min(32, (int)strlen(SEGMENT.name)) : 0; // WLEDMM make it robust against too long segment names - if (SEGMENT.name) for (size_t i=0,j=0; i31 && SEGMENT.name[i]<128) text[j++] = SEGMENT.name[i]; + char text[33] = {'\0'}; // ToDO use WLED_MAX_SEGNAME_LEN + 1 + unsigned maxLen = (SEGMENT.name) ? min(32, (int)strlen(SEGMENT.name)) : 0; // WLEDMM make it robust against too long segment names, ToDO use WLED_MAX_SEGNAME_LEN + +#if !defined(WLED_ENABLE_FULL_FONTS) + if (SEGMENT.name) for (size_t i=0,j=0; i31 && SEGMENT.name[i]<128) text[j++] = SEGMENT.name[i]; // unicode killer +#else + if (SEGMENT.name) for (size_t i=0,j=0; i= 0) || (abs(delayTime) > 1500)) { // WLEDMM keep on scrolling if timebase jumps (supersync, or brightness off, or wifi delay) + //WLEDMM ToDO: adjust scolling logic for unicode (single UTF-8 letters need up to 4 chars) if ((numberOfLetters * letterWidth) > cols) ++SEGENV.aux0 %= (numberOfLetters * letterWidth) + cols; // offset else SEGENV.aux0 = (cols + (numberOfLetters * letterWidth))/2; SEGENV.aux1 = (SEGENV.aux1 + 1) & 0xFF; // color shift // WLEDMM changed to prevent overflow @@ -6875,6 +6882,7 @@ uint16_t mode_2Dscrollingtext(void) { } if (SEGENV.check2 && ((numberOfLetters * letterWidth) > cols)) drawShadow = true; // scrolling overlay is easier to read with shadow +#if !defined(WLED_ENABLE_FULL_FONTS) for (int i = 0; i < numberOfLetters; i++) { if (int(cols) - int(SEGENV.aux0) + letterWidth*(i+1) < 0) continue; // don't draw characters off-screen uint32_t col1 = SEGMENT.color_from_palette(SEGENV.aux1, false, PALETTE_SOLID_WRAP, 0); @@ -6885,6 +6893,15 @@ uint16_t mode_2Dscrollingtext(void) { } SEGMENT.drawCharacter(text[i], int(cols) - int(SEGENV.aux0) + letterWidth*i, yoffset, letterWidth, letterHeight, col1, col2, drawShadow); } +#else + uint32_t col1 = SEGMENT.color_from_palette(SEGENV.aux1, false, PALETTE_SOLID_WRAP, 0); + uint32_t col2 = BLACK; + if (SEGMENT.check1 && SEGMENT.palette == 0) { + col1 = SEGCOLOR(0); + col2 = SEGCOLOR(2); + } + SEGMENT.drawText((unsigned char*)text, maxLen, numberOfLetters, int(cols) - int(SEGENV.aux0), yoffset, letterWidth, letterHeight, col1, col2, drawShadow); +#endif return FRAMETIME; } diff --git a/wled00/FX.h b/wled00/FX.h index ee39887f..1c4695f8 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -827,7 +827,7 @@ typedef struct Segment { void drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, uint8_t h, uint32_t color, uint32_t col2 = 0, bool drawShadow = false); inline void drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, uint8_t h, CRGB c, CRGB c2) { drawCharacter(chr, x, y, w, h, uint32_t(c) & 0x00FFFFFF, uint32_t(c2) & 0x00FFFFFF); } // automatic inline // unicode-aware wrapper for drawCharacter(), to be called from mode_2Dscrollingtext() - void drawText(const unsigned char* text, size_t maxLen, int16_t x, int16_t y, uint8_t w, uint8_t h, uint32_t color, uint32_t col2 = 0, bool drawShadow = false); + void drawText(const unsigned char* text, size_t maxLen, int maxLetters, int16_t x, int16_t y, uint8_t w, uint8_t h, uint32_t color, uint32_t col2 = 0, bool drawShadow = false); // #if !WLED_ENABLE_FULL_FONTS => drawText() will fall back to just forwarding each char to drawCharacter() void wu_pixel(uint32_t x, uint32_t y, CRGB c); diff --git a/wled00/FX_2Dfcn.cpp b/wled00/FX_2Dfcn.cpp index 27605c22..f2883a20 100644 --- a/wled00/FX_2Dfcn.cpp +++ b/wled00/FX_2Dfcn.cpp @@ -892,25 +892,33 @@ bool Segment::jsonToPixels(char * name, uint8_t fileNr) { #endif // unicode-aware wrapper for drawCharacter(), to be called from mode_2Dscrollingtext() -void Segment::drawText(const unsigned char* text, size_t maxLen, int16_t x, int16_t y, uint8_t w, uint8_t h, uint32_t color, uint32_t col2, bool drawShadow) { - size_t textLength = min(maxLen, size_t(WLED_MAX_SEGNAME_LEN)); +void Segment::drawText(const unsigned char* text, size_t maxLen, int maxLetters, int16_t x, int16_t y, uint8_t w, uint8_t h, uint32_t color, uint32_t col2, bool drawShadow) { + if (!isActive()) return; // not active // ToDO: find font _first/_last, based on width / height #if defined(WLED_ENABLE_FULL_FONTS) uint16_t decoded_text[WLED_MAX_SEGNAME_LEN+1] = { 0 }; // UTF-16 converted text. Cannot be longer than WLED_MAX_SEGNAME_LEN size_t utf16_index = 0; - for(const unsigned char* now = text; now != nullptr && now[0] != 0; now = nextUnicode(now, maxLen)) { - decoded_text[utf16_index] = unicodeToWchar16(now, maxLen); // UTF-8 decode into decoded_text - decoded_text[utf16_index] = wchar16ToCodepage437(decoded_text[utf16_index]); // decoded_text to CP437 (in-place conversion) - // toDo: ensure that decoded_text[i] is between console_font_YxZ_first and console_font_YxZ_last - // if (chr < 32 || chr > 126) --> clamp chr - // chr -= 32; // align with font table entries - utf16_index++; + for(const unsigned char* now = text; now != nullptr && now[0] != '\0'; now = nextUnicode(now, maxLen)) { + if (utf16_index <= WLED_MAX_SEGNAME_LEN) { + decoded_text[utf16_index] = unicodeToWchar16(now, maxLen); // UTF-8 decode into decoded_text + decoded_text[utf16_index] = wchar16ToCodepage437(decoded_text[utf16_index]); // decoded_text to CP437 (in-place conversion) + // toDo: ensure that decoded_text[i] is between console_font_YxZ_first and console_font_YxZ_last + // if (chr < 32 || chr > 126) --> clamp chr + // chr -= 32; // align with font table entries + utf16_index++; + } } decoded_text[utf16_index] = 0; // NUL terminate string + size_t textLength = min(utf16_index, size_t(maxLetters)); #else const unsigned char* decoded_text = text; // fallback + size_t textLength = min(strnlen((char*)text, maxLen), size_t(maxLetters)); #endif - // ToDO: pass decoded characters to drawCharacter() + + // pass characters to drawCharacter() + for (int i = 0; i < textLength; i++) { + SEGMENT.drawCharacter((unsigned char) decoded_text[i], x + w*i, y, w, h, color, col2, drawShadow); + } } // draws a raster font character on canvas @@ -918,10 +926,14 @@ void Segment::drawText(const unsigned char* text, size_t maxLen, int16_t x, int1 void Segment::drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, uint8_t h, uint32_t color, uint32_t col2, bool drawShadow) { if (!isActive()) return; // not active #if !defined(WLED_ENABLE_FULL_FONTS) + constexpr int space = 0; // font index of " " (space) if (chr < 32 || chr > 126) return; // legacy mode - only ASCII 32-126 supported chr -= 32; // align with font table entries #else - // ToDO: clamp to font limits + constexpr int space = 31; // font index of " " + // ToDO: clamp to actual font limits + if (chr < 1 || chr > 254) return; // sanity check // ToDO needs improvements + chr = chr -1; // all fonts start at 1 // ToDO needs improvements #endif const uint16_t cols = virtualWidth(); @@ -935,7 +947,7 @@ void Segment::drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, //if (w<5 || w>6 || h!=8) return; if (drawShadow) w++; // one more column for shadow on right side for (int i = 0; i= rows) break; // drawing off-screen uint8_t bits = 0; @@ -945,19 +957,19 @@ void Segment::drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, switch (font) { // font = w * h case 24: bits = pgm_read_byte_near(&console_font_4x6[(chr * h) + i]); - if ((i>0) && drawShadow) bits_up = pgm_read_byte_near(&console_font_4x6[(chr * h) + i -1]); - break; // 5x8 font + if ((i>space) && drawShadow) bits_up = pgm_read_byte_near(&console_font_4x6[(chr * h) + i -1]); + break; // 4x6 font case 40: bits = pgm_read_byte_near(&console_font_5x8[(chr * h) + i]); - if ((i>0) && drawShadow) bits_up = pgm_read_byte_near(&console_font_5x8[(chr * h) + i -1]); + if ((i>space) && drawShadow) bits_up = pgm_read_byte_near(&console_font_5x8[(chr * h) + i -1]); break; // 5x8 font case 48: bits = pgm_read_byte_near(&console_font_6x8[(chr * h) + i]); - if ((i>0) && drawShadow) bits_up = pgm_read_byte_near(&console_font_6x8[(chr * h) + i -1]); + if ((i>space) && drawShadow) bits_up = pgm_read_byte_near(&console_font_6x8[(chr * h) + i -1]); break; // 6x8 font case 63: bits = pgm_read_byte_near(&console_font_7x9[(chr * h) + i]); - if ((i>0) && drawShadow) bits_up = pgm_read_byte_near(&console_font_7x9[(chr * h) + i -1]); + if ((i>space) && drawShadow) bits_up = pgm_read_byte_near(&console_font_7x9[(chr * h) + i -1]); break; // 7x9 font case 60: bits = pgm_read_byte_near(&console_font_5x12[(chr * h) + i]); - if ((i>0) && drawShadow) bits_up = pgm_read_byte_near(&console_font_5x12[(chr * h) + i -1]); + if ((i>space) && drawShadow) bits_up = pgm_read_byte_near(&console_font_5x12[(chr * h) + i -1]); break; // 5x12 font default: return; } @@ -965,7 +977,7 @@ void Segment::drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, uint32_t fgCol = uint32_t(col) & 0x00FFFFFF; // WLEDMM cache color value for (int j = 0; j 0 && x0 < cols" if ((bits>>(j+(8-w))) & 0x01) { // bit set & drawing on-screen setPixelColorXY(x0, y0, fgCol); From 4a4887aabae2b1a8f7adebc7f4d55d07a8a24069 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Thu, 20 Nov 2025 18:05:53 +0100 Subject: [PATCH 113/170] scrolling text scrolling, unicode-aware strlen --- wled00/FX.cpp | 17 +++++++++++++---- wled00/src/font/codepages.h | 3 +++ wled00/src/font/unicodetool.cpp | 11 +++++++++++ 3 files changed, 27 insertions(+), 4 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index e7104156..6795fce0 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -10,6 +10,10 @@ #include "FX.h" #include "fcn_declare.h" +#if defined(WLED_ENABLE_FULL_FONTS) +#include "src/font/codepages.h" +#endif + #ifdef WLEDMM_FASTPATH #undef SEGMENT #undef SEGENV @@ -6861,11 +6865,16 @@ uint16_t mode_2Dscrollingtext(void) { else if ((!strncmp_P(text,PSTR("#AMP"),4)) || (!strncmp_P(text,PSTR("#POW"),4))) sprintf_P(text, PSTR("%3.1fA"), float(strip.currentMilliamps)/1000.0f); // WLEDMM else sprintf_P(text, PSTR("%s %d, %d %d:%02d%s"), monthShortStr(month(localTime)), day(localTime), year(localTime), AmPmHour, minute(localTime), sec); } else drawShadow = false; // static text does not require shadow - const int numberOfLetters = strlen(text); + + const int numberOfChars = strlen(text); +#if defined(WLED_ENABLE_FULL_FONTS) + const int numberOfLetters = strlenUC((unsigned char *)text); // get the mumber of unicode letters +#else + const int numberOfLetters = numberOfChars; +#endif long delayTime = long(strip.now) - long(SEGENV.step); if ((delayTime >= 0) || (abs(delayTime) > 1500)) { // WLEDMM keep on scrolling if timebase jumps (supersync, or brightness off, or wifi delay) - //WLEDMM ToDO: adjust scolling logic for unicode (single UTF-8 letters need up to 4 chars) if ((numberOfLetters * letterWidth) > cols) ++SEGENV.aux0 %= (numberOfLetters * letterWidth) + cols; // offset else SEGENV.aux0 = (cols + (numberOfLetters * letterWidth))/2; SEGENV.aux1 = (SEGENV.aux1 + 1) & 0xFF; // color shift // WLEDMM changed to prevent overflow @@ -6900,12 +6909,12 @@ uint16_t mode_2Dscrollingtext(void) { col1 = SEGCOLOR(0); col2 = SEGCOLOR(2); } - SEGMENT.drawText((unsigned char*)text, maxLen, numberOfLetters, int(cols) - int(SEGENV.aux0), yoffset, letterWidth, letterHeight, col1, col2, drawShadow); + SEGMENT.drawText((unsigned char*)text, maxLen, numberOfChars, int(cols) - int(SEGENV.aux0), yoffset, letterWidth, letterHeight, col1, col2, drawShadow); #endif return FRAMETIME; } -static const char _data_FX_MODE_2DSCROLLTEXT[] PROGMEM = "Scrolling Text@!,Y Offset,Trail,Font size,,Gradient,Overlay;!,!,Gradient;!;2;ix=128,c1=0,rev=0,mi=0,rY=0,mY=0"; +static const char _data_FX_MODE_2DSCROLLTEXT[] PROGMEM = "Scrolling Text@!,Y Offset,Trail,Font size,,Gradient,Overlay,Soft;!,!,Gradient;!;2;ix=128,c1=0,rev=0,mi=0,rY=0,mY=0"; //////////////////////////// diff --git a/wled00/src/font/codepages.h b/wled00/src/font/codepages.h index edb2cb99..c139da51 100644 --- a/wled00/src/font/codepages.h +++ b/wled00/src/font/codepages.h @@ -16,6 +16,9 @@ uint16_t unicodeToWchar16(const unsigned char* utf8, size_t maxLen); / // return nullptr at end of input const unsigned char* nextUnicode(const unsigned char* utf8, size_t maxLen); // unicodetool.cpp +// unicode-aware string length +size_t strlenUC(const unsigned char* utf8); + // translates unicode 2-byte (UTF-16) "code point" into corresponding character in codepage 437 (IBM PC aka PC-8) uint16_t wchar16ToCodepage437(uint16_t wideChar); // codepage437.cpp diff --git a/wled00/src/font/unicodetool.cpp b/wled00/src/font/unicodetool.cpp index 0fe775c1..d7b6bb68 100644 --- a/wled00/src/font/unicodetool.cpp +++ b/wled00/src/font/unicodetool.cpp @@ -72,4 +72,15 @@ const unsigned char* nextUnicode(const unsigned char* utf8, size_t maxLen) { else return utf8 + codeLength; // success: advance stream } +// unicode-aware string length +size_t strlenUC(const unsigned char* utf8) { + if ((utf8 == nullptr) || (utf8[0] == '\0')) return 0; + size_t maxLen = strlen((const char *)utf8); + size_t letters = 0; + for(const unsigned char* now = utf8; now != nullptr && now[0] != '\0'; now = nextUnicode(now, maxLen)) // iterates over utf-8 and count letters + letters++; + + return letters; +} + #endif From 207b197d044c5a8937223a1da249b44cbe207d5c Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Thu, 20 Nov 2025 18:08:18 +0100 Subject: [PATCH 114/170] scrolling text minor exhancements * scroll faster ! * add softening (=blur) option --- wled00/FX.cpp | 8 +++++++- wled00/json.cpp | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index 6795fce0..cfa401ec 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -6878,7 +6878,8 @@ uint16_t mode_2Dscrollingtext(void) { if ((numberOfLetters * letterWidth) > cols) ++SEGENV.aux0 %= (numberOfLetters * letterWidth) + cols; // offset else SEGENV.aux0 = (cols + (numberOfLetters * letterWidth))/2; SEGENV.aux1 = (SEGENV.aux1 + 1) & 0xFF; // color shift // WLEDMM changed to prevent overflow - SEGENV.step = strip.now + map2(SEGMENT.speed, 0, 255, 10*FRAMETIME_FIXED, 2*FRAMETIME_FIXED); + long minDelay = max((FRAMETIME_FIXED/2 + FRAMETIME_FIXED/4), int(FRAMETIME)); + SEGENV.step = strip.now + map2(SEGMENT.speed, 0, 255, 10*FRAMETIME_FIXED, minDelay); // WLEDMM scroll faster if (!SEGMENT.check2) { for (int y = 0; y < rows; y++) for (int x = 0; x < cols; x++ ) SEGMENT.blendPixelColorXY(x, y, SEGCOLOR(1), 255 - (SEGMENT.custom1>>1)); @@ -6910,6 +6911,11 @@ uint16_t mode_2Dscrollingtext(void) { col2 = SEGCOLOR(2); } SEGMENT.drawText((unsigned char*)text, maxLen, numberOfChars, int(cols) - int(SEGENV.aux0), yoffset, letterWidth, letterHeight, col1, col2, drawShadow); + // WLEDMM add some blur + if (SEGENV.check3) { + if (SEGMENT.custom1 < 16) SEGMENT.blurRows(16); // only blur if no trail + SEGMENT.blurCols(20); + } #endif return FRAMETIME; diff --git a/wled00/json.cpp b/wled00/json.cpp index f9f9f5c4..59b646e7 100644 --- a/wled00/json.cpp +++ b/wled00/json.cpp @@ -145,7 +145,7 @@ bool deserializeSegment(JsonObject elem, byte it, byte presetId) const char * name = elem["n"].as(); size_t len = 0; if (name != nullptr) len = strlen(name); - if (len > 0 && len < 32) { + if (len > 0 && len < 32) { // ToDO: this is why long segment names silently get deleted - truncating would be better seg.name = new(std::nothrow) char[len+1]; if (seg.name) strlcpy(seg.name, name, len+1); } else { From 3738735c848f0df97f81e913be5e3a781ec32724 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Thu, 20 Nov 2025 18:28:42 +0100 Subject: [PATCH 115/170] engage make it so --- platformio.ini | 3 +++ wled00/src/font/codepages.h | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/platformio.ini b/platformio.ini index e87678e0..e6f61d37 100644 --- a/platformio.ini +++ b/platformio.ini @@ -1078,6 +1078,7 @@ build_flags_S = -D WLEDMM_FASTPATH ;; WLEDMM experimental option. Reduces audio lag (latency), and allows for faster LED framerates. May break compatibility with previous versions. ; -D WLED_DEBUG_HEAP ;; WLEDMM enable heap debugging -D WLED_ENABLE_GIF + ; -D WLED_ENABLE_FULL_FONTS ;; uncomment for (limited) unicode support in scrolling text - warning: increases firmware size by 6848 bytes lib_deps_S = ;; https://github.com/kosme/arduinoFFT#develop @ 1.9.2+sha.419d7b0 ;; used for USERMOD_AUDIOREACTIVE - using "known working" hash @@ -1093,6 +1094,7 @@ build_flags_M = -D USERMOD_FOUR_LINE_DISPLAY -D USERMOD_ROTARY_ENCODER_UI -D USERMOD_AUTO_SAVE + -D WLED_ENABLE_FULL_FONTS ;; enables (limited) unicode support in scrolling text - warning: increases firmware size by 6848 bytes ${common_mm.animartrix_build_flags} ${common_mm.NetDebug_build_flags} @@ -1677,6 +1679,7 @@ build_flags = ${esp32_4MB_V4_S_base.esp32_build_flags} -D WLED_DISABLE_MQTT -D WLED_DISABLE_INFRARED -D WLED_DISABLE_ADALIGHT + -D WLED_ENABLE_FULL_FONTS ;; increases firmware size by 6848 bytes ;; -D WLED_DEBUG ;; -D SR_DEBUG -D WLED_BOOTUPDELAY=350 diff --git a/wled00/src/font/codepages.h b/wled00/src/font/codepages.h index c139da51..d067da94 100644 --- a/wled00/src/font/codepages.h +++ b/wled00/src/font/codepages.h @@ -3,6 +3,11 @@ #include // needed to get uint16_t definition #include // helps for code analysis with clang +// always disable unicode for 8266 builds - not enough program space +#if !defined(ARDUINO_ARCH_ESP32) && defined(WLED_ENABLE_FULL_FONTS) +#undef WLED_ENABLE_FULL_FONTS +#endif + //constexpr uint16_t UNKNOWN_CODE = 0x2219; // ∙ multiplication dot constexpr uint16_t UNKNOWN_CODE = 0x00B7; // · middle dot constexpr uint16_t BAD_CODE = 0x2022; // • bigger dot From 2c3592c3f3e0adc162c92d87133a5eaf09bd260c Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Thu, 20 Nov 2025 18:43:15 +0100 Subject: [PATCH 116/170] fix off-by-one array violation, debug message wghen segment name is too long * fix possible off-by-one array overflow in drawText * debug message when too-long segment name was dropped --- wled00/FX_2Dfcn.cpp | 2 +- wled00/json.cpp | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/wled00/FX_2Dfcn.cpp b/wled00/FX_2Dfcn.cpp index f2883a20..26417c65 100644 --- a/wled00/FX_2Dfcn.cpp +++ b/wled00/FX_2Dfcn.cpp @@ -899,7 +899,7 @@ void Segment::drawText(const unsigned char* text, size_t maxLen, int maxLetters, uint16_t decoded_text[WLED_MAX_SEGNAME_LEN+1] = { 0 }; // UTF-16 converted text. Cannot be longer than WLED_MAX_SEGNAME_LEN size_t utf16_index = 0; for(const unsigned char* now = text; now != nullptr && now[0] != '\0'; now = nextUnicode(now, maxLen)) { - if (utf16_index <= WLED_MAX_SEGNAME_LEN) { + if (utf16_index < WLED_MAX_SEGNAME_LEN) { decoded_text[utf16_index] = unicodeToWchar16(now, maxLen); // UTF-8 decode into decoded_text decoded_text[utf16_index] = wchar16ToCodepage437(decoded_text[utf16_index]); // decoded_text to CP437 (in-place conversion) // toDo: ensure that decoded_text[i] is between console_font_YxZ_first and console_font_YxZ_last diff --git a/wled00/json.cpp b/wled00/json.cpp index 59b646e7..5b33f6ea 100644 --- a/wled00/json.cpp +++ b/wled00/json.cpp @@ -149,6 +149,7 @@ bool deserializeSegment(JsonObject elem, byte it, byte presetId) seg.name = new(std::nothrow) char[len+1]; if (seg.name) strlcpy(seg.name, name, len+1); } else { + if (len > 0) { USER_PRINTF("! too-long segment name \"%s\" (%d chars) dropped.\n", name, len);} // but is empty (already deleted above) elem.remove("n"); } From 2f48f03e443ce3096eb6eea5a24f6f1adfa2eb5b Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Thu, 20 Nov 2025 22:33:42 +0100 Subject: [PATCH 117/170] truncate long segment name, instead of discarding UX improvement: when segment names are too long (esp. with unicode), truncate it instead of deleting the name completely --- wled00/json.cpp | 18 +++++++++++++++--- wled00/src/font/codepages.h | 4 ++++ wled00/src/font/unicodetool.cpp | 12 ++++++++++++ 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/wled00/json.cpp b/wled00/json.cpp index 5b33f6ea..809dd762 100644 --- a/wled00/json.cpp +++ b/wled00/json.cpp @@ -2,6 +2,10 @@ #include "palettes.h" +#if defined(WLED_ENABLE_FULL_FONTS) +#include "src/font/codepages.h" +#endif + #define JSON_PATH_STATE 1 #define JSON_PATH_INFO 2 #define JSON_PATH_STATE_INFO 3 @@ -145,11 +149,19 @@ bool deserializeSegment(JsonObject elem, byte it, byte presetId) const char * name = elem["n"].as(); size_t len = 0; if (name != nullptr) len = strlen(name); - if (len > 0 && len < 32) { // ToDO: this is why long segment names silently get deleted - truncating would be better + if (len > 0) { + // WLEDMM: truncate segment name, instead of silently deleting + if (len > 32) { // ToDO: use WLED_MAX_SEGNAME_LEN + len = 32; // cut to max segment name length + #if defined(WLED_ENABLE_FULL_FONTS) + if (name[len] > 127) // UTF-8 => don't cut in the middle of a multi-byte char + len = cutUnicodeAt((unsigned char*)name, len-1) +1; // +1 to convert between index and length + #endif + USER_PRINTF("Segment name too long (%d chars), truncated to \"%.*s\"\n", strlen(name), (int)len, name); + } seg.name = new(std::nothrow) char[len+1]; - if (seg.name) strlcpy(seg.name, name, len+1); + if (seg.name) strlcpy(seg.name, name, len+1); // copies at most size-1 characters and always null-terminates } else { - if (len > 0) { USER_PRINTF("! too-long segment name \"%s\" (%d chars) dropped.\n", name, len);} // but is empty (already deleted above) elem.remove("n"); } diff --git a/wled00/src/font/codepages.h b/wled00/src/font/codepages.h index d067da94..bc0c7538 100644 --- a/wled00/src/font/codepages.h +++ b/wled00/src/font/codepages.h @@ -24,6 +24,10 @@ const unsigned char* nextUnicode(const unsigned char* utf8, size_t maxLen); / // unicode-aware string length size_t strlenUC(const unsigned char* utf8); +// the next (lesser) string index that is safe for cutting an UTF-8 string +// Important: calling code is responsible to provide a string with at least _where_ chars +size_t cutUnicodeAt(const unsigned char* utf8, size_t where); + // translates unicode 2-byte (UTF-16) "code point" into corresponding character in codepage 437 (IBM PC aka PC-8) uint16_t wchar16ToCodepage437(uint16_t wideChar); // codepage437.cpp diff --git a/wled00/src/font/unicodetool.cpp b/wled00/src/font/unicodetool.cpp index d7b6bb68..86416a86 100644 --- a/wled00/src/font/unicodetool.cpp +++ b/wled00/src/font/unicodetool.cpp @@ -83,4 +83,16 @@ size_t strlenUC(const unsigned char* utf8) { return letters; } +// returns the next (lesser) string index that is safe for cutting an UTF-8 string +// Important: calling code is responsible to provide a string with at least _where_ chars +size_t cutUnicodeAt(const unsigned char* utf8, size_t where) { + if (utf8[where] <= 127) return where; // ASCII + size_t loopMin = max(0, int(where)-4); // max 4 characters backwards + size_t whereStart = where; + while ((isValidContinuation(utf8[where])) && (where > loopMin)) where--; // UTF-8: back until we find a non-continuation char + + if ((utf8[where] > 127) && isValidContinuation(utf8[whereStart])) where = max(0, int(where)-1); // most likely a UTF-8 lead byte -> go back one step + return where; +} + #endif From dcdc05b59240fd515488a62a38d5a4d55ae8e72a Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Thu, 20 Nov 2025 22:36:46 +0100 Subject: [PATCH 118/170] unicode-related robustness improvements * enable ARDUINOJSON_DECODE_UNICODE (otherwise unicode needs 6(!) bytes for encoding) * robustness: increase a few tiny string buffers for some extra margin * Web UI: allow entering up to 64 chars as segment name --- wled00/data/index.js | 2 +- wled00/file.cpp | 6 +++--- wled00/presets.cpp | 8 ++++---- wled00/wled.h | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/wled00/data/index.js b/wled00/data/index.js index 5d08a3f8..a1b564ec 100644 --- a/wled00/data/index.js +++ b/wled00/data/index.js @@ -827,7 +827,7 @@ function populateSegments(s) (cfg.comp.segpwr ? segp : '') + `
`+ `` + // - ``+ + ``+ `
`+ ``+ ``+ diff --git a/wled00/file.cpp b/wled00/file.cpp index 5a82bdb3..bb853df9 100644 --- a/wled00/file.cpp +++ b/wled00/file.cpp @@ -214,7 +214,7 @@ bool appendObjectToFile(const char* key, JsonDocument* content, uint32_t s, uint if (!f) return false; if (f.size() < 3) { - char init[10]; + char init[12]; strcpy_P(init, PSTR("{\"0\":{}}")); f.print(init); } @@ -285,7 +285,7 @@ bool appendObjectToFile(const char* key, JsonDocument* content, uint32_t s, uint bool writeObjectToFileUsingId(const char* file, uint16_t id, JsonDocument* content) { - char objKey[10]; + char objKey[12]; sprintf(objKey, "\"%d\":", id); return writeObjectToFile(file, objKey, content); } @@ -360,7 +360,7 @@ bool writeObjectToFile(const char* file, const char* key, JsonDocument* content) bool readObjectFromFileUsingId(const char* file, uint16_t id, JsonDocument* dest) { - char objKey[10]; + char objKey[12]; sprintf(objKey, "\"%d\":", id); return readObjectFromFile(file, objKey, dest); } diff --git a/wled00/presets.cpp b/wled00/presets.cpp index 3e5b4142..b8d121d0 100644 --- a/wled00/presets.cpp +++ b/wled00/presets.cpp @@ -12,7 +12,7 @@ static volatile byte presetToApply = 0; static volatile byte callModeToApply = 0; static volatile byte presetToSave = 0; static volatile int8_t saveLedmap = -1; -static char quickLoad[9]; +static char quickLoad[12]; // WLEDMM 9->12 to prevent crashing with unicode static char saveName[33]; static bool includeBri = true, segBounds = true, selectedOnly = false, playlistSave = false; @@ -88,8 +88,8 @@ static void doSaveState() { // clean up saveLedmap = -1; presetToSave = 0; - saveName[0] = '\0'; - quickLoad[0] = '\0'; + memset(saveName, '\0', sizeof(saveName)); + memset(quickLoad,'\0', sizeof(quickLoad)); playlistSave = false; } @@ -306,7 +306,7 @@ void savePreset(byte index, const char* pname, JsonObject sObj) presetToSave = index; playlistSave = false; - if (sObj[F("ql")].is()) strlcpy(quickLoad, sObj[F("ql")].as(), 9); // client limits QL to 2 chars, buffer for 8 bytes to allow unicode + if (sObj[F("ql")].is()) strlcpy(quickLoad, sObj[F("ql")].as(), sizeof(quickLoad)); // client limits QL to 2 chars, buffer for 12 bytes to allow encoded unicode if (sObj.size()==0 || sObj["o"].isNull()) { // no "o" means not a playlist or custom API call, saving of state is async (not immediately) includeBri = sObj["ib"].as() || sObj.size()==0 || index==255; // temporary preset needs brightness diff --git a/wled00/wled.h b/wled00/wled.h index 138157a7..1de5d8fd 100644 --- a/wled00/wled.h +++ b/wled00/wled.h @@ -176,7 +176,7 @@ #include "src/dependencies/async-mqtt-client/AsyncMqttClient.h" #endif -#define ARDUINOJSON_DECODE_UNICODE 0 +#define ARDUINOJSON_DECODE_UNICODE 1 // WLEDMM enable unicode support -> prevents crashes when user enters unicode strings in webUI #include "src/dependencies/json/AsyncJson-v6.h" #include "src/dependencies/json/ArduinoJson-v6.h" From e63dc7e71e9cd21b7621d6cb49ec57375733d023 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Thu, 20 Nov 2025 23:49:26 +0100 Subject: [PATCH 119/170] longer segment names * introducing WLED_MAX_SEGNAME_LEN from upstream * default: max name length = 48 * hopefully found all places where the segment name length was hardcoded (32, 33, 34) * some comments still refer to "32" but wtf --- wled00/FX.cpp | 4 ++-- wled00/FX_2Dfcn.cpp | 7 +------ wled00/FX_fcn.cpp | 20 ++++++++++---------- wled00/const.h | 16 ++++++++++++++++ wled00/image_loader.cpp | 5 ----- wled00/json.cpp | 4 ++-- 6 files changed, 31 insertions(+), 25 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index cfa401ec..3943b592 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -6814,8 +6814,8 @@ uint16_t mode_2Dscrollingtext(void) { case 5: letterWidth = 5; letterHeight = 12; break; } const int yoffset = map(SEGMENT.intensity, 0, 255, -rows/2, rows/2) + (rows-letterHeight)/2; - char text[33] = {'\0'}; // ToDO use WLED_MAX_SEGNAME_LEN + 1 - unsigned maxLen = (SEGMENT.name) ? min(32, (int)strlen(SEGMENT.name)) : 0; // WLEDMM make it robust against too long segment names, ToDO use WLED_MAX_SEGNAME_LEN + char text[WLED_MAX_SEGNAME_LEN+1] = {'\0'}; + unsigned maxLen = (SEGMENT.name) ? min(WLED_MAX_SEGNAME_LEN, (int)strlen(SEGMENT.name)) : 0; // WLEDMM make it robust against too long segment names #if !defined(WLED_ENABLE_FULL_FONTS) if (SEGMENT.name) for (size_t i=0,j=0; i31 && SEGMENT.name[i]<128) text[j++] = SEGMENT.name[i]; // unicode killer diff --git a/wled00/FX_2Dfcn.cpp b/wled00/FX_2Dfcn.cpp index 26417c65..28e8a311 100644 --- a/wled00/FX_2Dfcn.cpp +++ b/wled00/FX_2Dfcn.cpp @@ -842,7 +842,7 @@ void Segment::drawArc(unsigned x0, unsigned y0, int radius, uint32_t color, uint //WLEDMM for artifx bool Segment::jsonToPixels(char * name, uint8_t fileNr) { if (!isActive()) return true; // segment not active, nothing to do - char fileName[42] = { '\0' }; // we need up to 40 bytes (seg.name is 32 bytes max) + char fileName[WLED_MAX_SEGNAME_LEN+12] = { '\0' }; // we need up to 40 bytes (seg.name is 32 bytes max) //WLEDMM: als support segment name ledmaps bool isFile = false; // strcpy_P(fileName, PSTR("/mario")); @@ -886,11 +886,6 @@ bool Segment::jsonToPixels(char * name, uint8_t fileNr) { #include "src/font/codepages.h" #endif -//upstream compatibility -#if !defined(WLED_MAX_SEGNAME_LEN) -#define WLED_MAX_SEGNAME_LEN 32 // ToDO: inrease default to 48 -#endif - // unicode-aware wrapper for drawCharacter(), to be called from mode_2Dscrollingtext() void Segment::drawText(const unsigned char* text, size_t maxLen, int maxLetters, int16_t x, int16_t y, uint8_t w, uint8_t h, uint32_t color, uint32_t col2, bool drawShadow) { if (!isActive()) return; // not active diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index 73eea00c..71355377 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -698,7 +698,7 @@ struct ArrayAndSize { }; class JMapC { public: - char previousSegmentName[50] = ""; + char previousSegmentName[WLED_MAX_SEGNAME_LEN+12] = ""; ~JMapC() { DEBUG_PRINTLN("~JMapC"); @@ -751,7 +751,7 @@ class JMapC { uint32_t dataSize = 0; deletejVectorMap(); DEBUG_PRINT("New "); DEBUG_PRINTLN(SEGMENT.name); - char jMapFileName[50] = {'\0'}; // we need at most 32 + 7 bytes + char jMapFileName[WLED_MAX_SEGNAME_LEN+12] = {'\0'}; // we need at most 32 + 7 bytes strcpy(jMapFileName, "/"); strcat(jMapFileName, SEGMENT.name); strcat(jMapFileName, ".json"); @@ -1728,22 +1728,22 @@ void WS2812FX::enumerateLedmaps() { f = WLED_FS.open(fileName, "r"); if (f) { f.find("\"n\":"); - char name[34] = { '\0' }; // ensure string termination + char name[WLED_MAX_SEGNAME_LEN+2] = { '\0' }; // ensure string termination f.readBytesUntil('\n', name, sizeof(name)-1); size_t len = strlen(name); - if (len > 0 && len < 33) { + if (len > 0 && len < (sizeof(name)-1)) { (void) cleanUpName(name); len = strlen(name); ledmapNames[i-1] = new(std::nothrow) char[len+1]; // +1 to include terminating \0 - if (ledmapNames[i-1]) strlcpy(ledmapNames[i-1], name, 33); + if (ledmapNames[i-1]) strlcpy(ledmapNames[i-1], name, sizeof(name)); } if (!ledmapNames[i-1]) { char tmp[33]; snprintf_P(tmp, 32, PSTR("ledmap%d.json"), i); - len = strlen(tmp); - ledmapNames[i-1] = new(std::nothrow) char[len+1]; - if (ledmapNames[i-1]) strlcpy(ledmapNames[i-1], tmp, 33); + size_t tmplen = strlen(tmp); + ledmapNames[i-1] = new(std::nothrow) char[tmplen+1]; + if (ledmapNames[i-1]) strlcpy(ledmapNames[i-1], tmp, tmplen); } USER_PRINTF("enumerateLedmaps %s \"%s\"", fileName, name); @@ -1779,7 +1779,7 @@ void WS2812FX::enumerateLedmaps() { uint8_t segment_index = 0; for (segment &seg : _segments) { if (seg.name != nullptr && strlen(seg.name) > 0) { - char fileName[33+11] = { '\0' }; // segment name is 32 chars max, so we need 43 chars in worst case + char fileName[WLED_MAX_SEGNAME_LEN+12] = { '\0' }; // segment name is 32 chars max, so we need 43 chars in worst case snprintf_P(fileName, sizeof(fileName)-1, PSTR("/lm%s.json"), seg.name); bool isFile = WLED_FS.exists(fileName); if (isFile) ledMaps |= 1 << (10+segment_index); @@ -2587,7 +2587,7 @@ void WS2812FX::loadCustomPalettes() { bool WS2812FX::deserializeMap(uint8_t n) { // 2D support creates its own ledmap (on the fly) if a ledmap.json exists it will overwrite built one. - char fileName[42] = {'\0'}; // WLEDMM we need at least 32 + 7 bytes + char fileName[WLED_MAX_SEGNAME_LEN+10] = {'\0'}; // WLEDMM we need at least 32 + 7 bytes //WLEDMM: als support segment name ledmaps bool isFile = false;; if (n<10) { diff --git a/wled00/const.h b/wled00/const.h index 388eaad6..e152bc7f 100644 --- a/wled00/const.h +++ b/wled00/const.h @@ -91,6 +91,22 @@ #endif #endif +#ifndef WLED_MAX_SEGNAME_LEN + #ifdef ESP8266 + #define WLED_MAX_SEGNAME_LEN 32 + #else + #define WLED_MAX_SEGNAME_LEN 48 // WLEDMM upstream uses 64, but 48 seems to be a good compromise between flexibility and memory needed + #endif +#else + #if WLED_MAX_SEGNAME_LEN<32 + #undef WLED_MAX_SEGNAME_LEN + #define WLED_MAX_SEGNAME_LEN 32 + #else + #warning WLED UI does not support your modified maximum segment name length! + #endif +#endif + + //Usermod IDs #define USERMOD_ID_RESERVED 0 //Unused. Might indicate no usermod present #define USERMOD_ID_UNSPECIFIED 1 //Default value for a general user mod that does not specify a custom ID diff --git a/wled00/image_loader.cpp b/wled00/image_loader.cpp index bc73a8fc..72aa765f 100644 --- a/wled00/image_loader.cpp +++ b/wled00/image_loader.cpp @@ -5,11 +5,6 @@ #include "GifDecoder.h" -//upstream compatibility -#if !defined(WLED_MAX_SEGNAME_LEN) -#define WLED_MAX_SEGNAME_LEN 32 -#endif - /* * Functions to render images from filesystem to segments, used by the "Image" effect */ diff --git a/wled00/json.cpp b/wled00/json.cpp index 809dd762..ee19ac0b 100644 --- a/wled00/json.cpp +++ b/wled00/json.cpp @@ -151,8 +151,8 @@ bool deserializeSegment(JsonObject elem, byte it, byte presetId) if (name != nullptr) len = strlen(name); if (len > 0) { // WLEDMM: truncate segment name, instead of silently deleting - if (len > 32) { // ToDO: use WLED_MAX_SEGNAME_LEN - len = 32; // cut to max segment name length + if (len > WLED_MAX_SEGNAME_LEN) { + len = WLED_MAX_SEGNAME_LEN; // cut to max segment name length #if defined(WLED_ENABLE_FULL_FONTS) if (name[len] > 127) // UTF-8 => don't cut in the middle of a multi-byte char len = cutUnicodeAt((unsigned char*)name, len-1) +1; // +1 to convert between index and length From c3dce1353c4bbbdf3c314189c90f0d96fa369f4a Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Fri, 21 Nov 2025 00:01:13 +0100 Subject: [PATCH 120/170] fix font shadow code stupid mistake ... it must still be "i>0" because its about the scanline, not the character code --- wled00/FX_2Dfcn.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/wled00/FX_2Dfcn.cpp b/wled00/FX_2Dfcn.cpp index 28e8a311..8cdd1b6c 100644 --- a/wled00/FX_2Dfcn.cpp +++ b/wled00/FX_2Dfcn.cpp @@ -952,19 +952,19 @@ void Segment::drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, switch (font) { // font = w * h case 24: bits = pgm_read_byte_near(&console_font_4x6[(chr * h) + i]); - if ((i>space) && drawShadow) bits_up = pgm_read_byte_near(&console_font_4x6[(chr * h) + i -1]); + if ((i>0) && drawShadow) bits_up = pgm_read_byte_near(&console_font_4x6[(chr * h) + i -1]); break; // 4x6 font case 40: bits = pgm_read_byte_near(&console_font_5x8[(chr * h) + i]); - if ((i>space) && drawShadow) bits_up = pgm_read_byte_near(&console_font_5x8[(chr * h) + i -1]); + if ((i>0) && drawShadow) bits_up = pgm_read_byte_near(&console_font_5x8[(chr * h) + i -1]); break; // 5x8 font case 48: bits = pgm_read_byte_near(&console_font_6x8[(chr * h) + i]); - if ((i>space) && drawShadow) bits_up = pgm_read_byte_near(&console_font_6x8[(chr * h) + i -1]); + if ((i>0) && drawShadow) bits_up = pgm_read_byte_near(&console_font_6x8[(chr * h) + i -1]); break; // 6x8 font case 63: bits = pgm_read_byte_near(&console_font_7x9[(chr * h) + i]); - if ((i>space) && drawShadow) bits_up = pgm_read_byte_near(&console_font_7x9[(chr * h) + i -1]); + if ((i>0) && drawShadow) bits_up = pgm_read_byte_near(&console_font_7x9[(chr * h) + i -1]); break; // 7x9 font case 60: bits = pgm_read_byte_near(&console_font_5x12[(chr * h) + i]); - if ((i>space) && drawShadow) bits_up = pgm_read_byte_near(&console_font_5x12[(chr * h) + i -1]); + if ((i>0) && drawShadow) bits_up = pgm_read_byte_near(&console_font_5x12[(chr * h) + i -1]); break; // 5x12 font default: return; } From 7ef94bc6c720316b18956fdb56ede737f01042ad Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Fri, 21 Nov 2025 00:08:15 +0100 Subject: [PATCH 121/170] use strlcpy instead of strcpy --- wled00/FX_fcn.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index 71355377..341fc52b 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -819,7 +819,7 @@ class JMapC { USER_PRINT(dataSize); USER_PRINT(" scale "); USER_PRINTLN(scale); - strcpy(previousSegmentName, SEGMENT.name); + strlcpy(previousSegmentName, SEGMENT.name, sizeof(previousSegmentName)); } } //updatejMapDoc }; //class JMapC From 415aadc6e09ca1c7983c8f7667ad70ed0d8d7b0b Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Fri, 21 Nov 2025 00:10:33 +0100 Subject: [PATCH 122/170] removing dead code --- wled00/FX_2Dfcn.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/wled00/FX_2Dfcn.cpp b/wled00/FX_2Dfcn.cpp index 8cdd1b6c..3bb6dd51 100644 --- a/wled00/FX_2Dfcn.cpp +++ b/wled00/FX_2Dfcn.cpp @@ -921,11 +921,9 @@ void Segment::drawText(const unsigned char* text, size_t maxLen, int maxLetters, void Segment::drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, uint8_t h, uint32_t color, uint32_t col2, bool drawShadow) { if (!isActive()) return; // not active #if !defined(WLED_ENABLE_FULL_FONTS) - constexpr int space = 0; // font index of " " (space) if (chr < 32 || chr > 126) return; // legacy mode - only ASCII 32-126 supported chr -= 32; // align with font table entries #else - constexpr int space = 31; // font index of " " // ToDO: clamp to actual font limits if (chr < 1 || chr > 254) return; // sanity check // ToDO needs improvements chr = chr -1; // all fonts start at 1 // ToDO needs improvements From c36e493b47d09895c172d49c5e27bb995dcf0052 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Fri, 21 Nov 2025 00:16:25 +0100 Subject: [PATCH 123/170] Fix strlcpy destination size parameters --- wled00/FX_fcn.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index 341fc52b..d307b5b8 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -1736,14 +1736,14 @@ void WS2812FX::enumerateLedmaps() { (void) cleanUpName(name); len = strlen(name); ledmapNames[i-1] = new(std::nothrow) char[len+1]; // +1 to include terminating \0 - if (ledmapNames[i-1]) strlcpy(ledmapNames[i-1], name, sizeof(name)); + if (ledmapNames[i-1]) strlcpy(ledmapNames[i-1], name, len+1); } if (!ledmapNames[i-1]) { char tmp[33]; snprintf_P(tmp, 32, PSTR("ledmap%d.json"), i); size_t tmplen = strlen(tmp); ledmapNames[i-1] = new(std::nothrow) char[tmplen+1]; - if (ledmapNames[i-1]) strlcpy(ledmapNames[i-1], tmp, tmplen); + if (ledmapNames[i-1]) strlcpy(ledmapNames[i-1], tmp, tmplen+1); } USER_PRINTF("enumerateLedmaps %s \"%s\"", fileName, name); From 053551d61deb8be4250dd31e64a3742e974b6e5e Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Fri, 21 Nov 2025 00:36:09 +0100 Subject: [PATCH 124/170] scrolling text blur moved to where it should be accidentally put it into the "full font" ifdef --- wled00/FX.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index 3943b592..5bbdc8cf 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -6911,12 +6911,13 @@ uint16_t mode_2Dscrollingtext(void) { col2 = SEGCOLOR(2); } SEGMENT.drawText((unsigned char*)text, maxLen, numberOfChars, int(cols) - int(SEGENV.aux0), yoffset, letterWidth, letterHeight, col1, col2, drawShadow); +#endif + // WLEDMM add some blur - if (SEGENV.check3) { + if (SEGMENT.check3) { if (SEGMENT.custom1 < 16) SEGMENT.blurRows(16); // only blur if no trail SEGMENT.blurCols(20); } -#endif return FRAMETIME; } From aea83a352f1c677244ab0e36fefb1f7e3a034456 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Fri, 21 Nov 2025 00:55:03 +0100 Subject: [PATCH 125/170] bugfix: incomplete time/date in full font mode maxLen = numberOfChars --- wled00/FX.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index 5bbdc8cf..564f2bd7 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -6910,6 +6910,7 @@ uint16_t mode_2Dscrollingtext(void) { col1 = SEGCOLOR(0); col2 = SEGCOLOR(2); } + maxLen = numberOfChars; // Ensure maxLen reflects the actual rendered text, not the original SEGMENT.name // ToDO remove double parameter SEGMENT.drawText((unsigned char*)text, maxLen, numberOfChars, int(cols) - int(SEGENV.aux0), yoffset, letterWidth, letterHeight, col1, col2, drawShadow); #endif From 527acefdea0bf79e6e73454a19bcad4adc9f6646 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Fri, 21 Nov 2025 02:52:01 +0100 Subject: [PATCH 126/170] improvement for UTF-8 safe string trucation of segment name did I mention already that this is complicated stuff? oh yes, it is. --- wled00/json.cpp | 8 ++++++-- wled00/src/font/unicodetool.cpp | 15 ++++++++++----- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/wled00/json.cpp b/wled00/json.cpp index ee19ac0b..d288eed2 100644 --- a/wled00/json.cpp +++ b/wled00/json.cpp @@ -154,8 +154,12 @@ bool deserializeSegment(JsonObject elem, byte it, byte presetId) if (len > WLED_MAX_SEGNAME_LEN) { len = WLED_MAX_SEGNAME_LEN; // cut to max segment name length #if defined(WLED_ENABLE_FULL_FONTS) - if (name[len] > 127) // UTF-8 => don't cut in the middle of a multi-byte char - len = cutUnicodeAt((unsigned char*)name, len-1) +1; // +1 to convert between index and length + // UTF-8: don't cut in the middle of a multi-byte char + // the "or" condition is need because we have to look at both: + // * name[len-1] - the character that would be included (at the cut boundary) + // * name[len] - the character that would be excluded (after the cut) + if ((name[len] > 127) || (name[len-1] > 127)) + len = cutUnicodeAt((unsigned char*)name, len-1) +1; // find a safe cut // +1 to convert between index and length #endif USER_PRINTF("Segment name too long (%d chars), truncated to \"%.*s\"\n", strlen(name), (int)len, name); } diff --git a/wled00/src/font/unicodetool.cpp b/wled00/src/font/unicodetool.cpp index 86416a86..80312bfa 100644 --- a/wled00/src/font/unicodetool.cpp +++ b/wled00/src/font/unicodetool.cpp @@ -86,12 +86,17 @@ size_t strlenUC(const unsigned char* utf8) { // returns the next (lesser) string index that is safe for cutting an UTF-8 string // Important: calling code is responsible to provide a string with at least _where_ chars size_t cutUnicodeAt(const unsigned char* utf8, size_t where) { - if (utf8[where] <= 127) return where; // ASCII - size_t loopMin = max(0, int(where)-4); // max 4 characters backwards - size_t whereStart = where; - while ((isValidContinuation(utf8[where])) && (where > loopMin)) where--; // UTF-8: back until we find a non-continuation char + if (where == 0 || utf8[where] <= 127) return where; // ASCII or start -> OK to cut off - if ((utf8[where] > 127) && isValidContinuation(utf8[whereStart])) where = max(0, int(where)-1); // most likely a UTF-8 lead byte -> go back one step + size_t loopMin = max(0, int(where)-5); // max 5 characters backwards (UTF-8 max is 4 bytes) + // Back up while we see continuation bytes (10xxxxxx) + while ((isValidContinuation(utf8[where])) && (where > loopMin)) + where--; + + // After the loop, utf8[where] is either ASCII or a UTF-8 lead byte + // If it's a lead byte (> 127), we're at the start of a multi-byte sequence. + // Go back one more position to exclude the entire sequence. + if (utf8[where] > 127) where = max(0, int(where)-1); return where; } From d047ee0984816d1b8017abd95b205db2991baaed Mon Sep 17 00:00:00 2001 From: Will Tatam Date: Fri, 21 Nov 2025 08:39:50 +0000 Subject: [PATCH 127/170] Add deviceId --- wled00/fcn_declare.h | 3 +- wled00/json.cpp | 1 + wled00/util.cpp | 99 +++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 101 insertions(+), 2 deletions(-) diff --git a/wled00/fcn_declare.h b/wled00/fcn_declare.h index 1a9247a2..17a950ac 100644 --- a/wled00/fcn_declare.h +++ b/wled00/fcn_declare.h @@ -400,7 +400,8 @@ uint8_t extractModeSlider(uint8_t mode, uint8_t slider, char *dest, uint8_t maxL int16_t extractModeDefaults(uint8_t mode, const char *segVar); void checkSettingsPIN(const char *pin); uint16_t __attribute__((pure)) crc16(const unsigned char* data_p, size_t length); // WLEDMM: added attribute pure - +String computeSHA1(const String& input); +String getDeviceId(); uint16_t beatsin88_t(accum88 beats_per_minute_88, uint16_t lowest = 0, uint16_t highest = 65535, uint32_t timebase = 0, uint16_t phase_offset = 0); uint16_t beatsin16_t(accum88 beats_per_minute, uint16_t lowest = 0, uint16_t highest = 65535, uint32_t timebase = 0, uint16_t phase_offset = 0); uint8_t beatsin8_t(accum88 beats_per_minute, uint8_t lowest = 0, uint8_t highest = 255, uint32_t timebase = 0, uint8_t phase_offset = 0); diff --git a/wled00/json.cpp b/wled00/json.cpp index c51deefa..45c15837 100644 --- a/wled00/json.cpp +++ b/wled00/json.cpp @@ -913,6 +913,7 @@ void serializeInfo(JsonObject root) //root[F("cn")] = F(WLED_CODENAME); //WLEDMM removed root[F("release")] = FPSTR(releaseString); root[F("rel")] = FPSTR(releaseString); //WLEDMM to add bin name + root[F("deviceId")] = getDeviceId(); JsonObject leds = root.createNestedObject("leds"); leds[F("count")] = strip.getLengthTotal(); diff --git a/wled00/util.cpp b/wled00/util.cpp index c31b20b6..9bd7c6a2 100644 --- a/wled00/util.cpp +++ b/wled00/util.cpp @@ -1,7 +1,13 @@ #include "wled.h" #include "fcn_declare.h" #include "const.h" - +#ifdef ESP8266 +#include "user_interface.h" // for bootloop detection +#include // for SHA1 on ESP8266 +#else +#include "mbedtls/sha1.h" // for SHA1 on ESP32 +#include "esp_efuse.h" +#endif //helper to get int value at a position in string int getNumVal(const String* req, uint16_t pos) @@ -668,3 +674,94 @@ int32_t hw_random(int32_t lowerlimit, int32_t upperlimit) { uint32_t diff = upperlimit - lowerlimit; return hw_random(diff) + lowerlimit; } + +// Platform-agnostic SHA1 computation from String input +String computeSHA1(const String& input) { + #ifdef ESP8266 + return sha1(input); // ESP8266 has built-in sha1() function + #else + // ESP32: Compute SHA1 hash using mbedtls + unsigned char shaResult[20]; // SHA1 produces 20 bytes + mbedtls_sha1_context ctx; + + mbedtls_sha1_init(&ctx); + mbedtls_sha1_starts_ret(&ctx); + mbedtls_sha1_update_ret(&ctx, (const unsigned char*)input.c_str(), input.length()); + mbedtls_sha1_finish_ret(&ctx, shaResult); + mbedtls_sha1_free(&ctx); + + // Convert to hexadecimal string + char hexString[41]; + for (int i = 0; i < 20; i++) { + sprintf(&hexString[i*2], "%02x", shaResult[i]); + } + hexString[40] = '\0'; + + return String(hexString); + #endif +} + +#ifdef ESP32 +static String dump_raw_block(esp_efuse_block_t block) +{ + const int WORDS = 8; // ESP32: 8×32-bit words per block i.e. 256bits + uint32_t buf[WORDS] = {0}; + + const esp_efuse_desc_t d = { + .efuse_block = block, + .bit_start = 0, + .bit_count = WORDS * 32 + }; + const esp_efuse_desc_t* field[2] = { &d, NULL }; + + esp_err_t err = esp_efuse_read_field_blob(field, buf, WORDS * 32); + if (err != ESP_OK) { + return ""; + } + + String result = ""; + for (const unsigned int i : buf) { + char line[32]; + sprintf(line, "0x%08X", i); + result += line; + } + return result; +} +#endif + + +// Generate a device ID based on SHA1 hash of MAC address salted with "WLED" +// Returns: original SHA1 + last 2 chars of double-hashed SHA1 (42 chars total) +String getDeviceId() { + static String cachedDeviceId = ""; + if (cachedDeviceId.length() > 0) return cachedDeviceId; + + uint8_t mac[6]; + WiFi.macAddress(mac); + char macStr[18]; + sprintf(macStr, "%02x:%02x:%02x:%02x:%02x:%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + + // The device string is deterministic as it needs to be consistent for the same device, even after a full flash erase + // MAC is salted with other consistent device info to avoid rainbow table attacks. + // If the MAC address is known by malicious actors, they could precompute SHA1 hashes to impersonate devices, + // but as WLED developers are just looking at statistics and not authenticating devices, this is acceptable. + // If the usage data was exfiltrated, you could not easily determine the MAC from the device ID without brute forcing SHA1 +#ifdef ESP8266 + String deviceString = String(macStr) + "WLED" + ESP.getFlashChipId(); +#else + String deviceString = String(macStr) + "WLED" + ESP.getChipModel() + ESP.getChipRevision(); + deviceString += dump_raw_block(EFUSE_BLK0); + deviceString += dump_raw_block(EFUSE_BLK1); + deviceString += dump_raw_block(EFUSE_BLK2); + deviceString += dump_raw_block(EFUSE_BLK3); +#endif + String firstHash = computeSHA1(deviceString); + + // Second hash: SHA1 of the first hash + String secondHash = computeSHA1(firstHash); + + // Concatenate first hash + last 2 chars of second hash + cachedDeviceId = firstHash + secondHash.substring(38); + + return cachedDeviceId; +} \ No newline at end of file From 213cd185b51c97f9550436d11eabd5abe5e55881 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Fri, 21 Nov 2025 13:48:38 +0100 Subject: [PATCH 128/170] explanations for CP437 translations, some cleanups, bugfix for drawString * explanation for CP437 glyph groups * translation for MonnModules symbol * "smiley" replacement for 4-bytes and overlong unicode codes * always compile unicodetool.cpp (codepage translation still depends on WLED_ENABLE_UNICODE) * bugfix: DrawString now skips over glyphs that would be rejected by DrawCharacter * minor cleanup --- wled00/FX_2Dfcn.cpp | 10 +++--- wled00/src/font/codepage437.cpp | 56 +++++++++++++++++++++++---------- wled00/src/font/codepages.h | 8 +++-- wled00/src/font/unicodetool.cpp | 19 ++++++----- 4 files changed, 63 insertions(+), 30 deletions(-) diff --git a/wled00/FX_2Dfcn.cpp b/wled00/FX_2Dfcn.cpp index 3bb6dd51..b1f48980 100644 --- a/wled00/FX_2Dfcn.cpp +++ b/wled00/FX_2Dfcn.cpp @@ -897,19 +897,21 @@ void Segment::drawText(const unsigned char* text, size_t maxLen, int maxLetters, if (utf16_index < WLED_MAX_SEGNAME_LEN) { decoded_text[utf16_index] = unicodeToWchar16(now, maxLen); // UTF-8 decode into decoded_text decoded_text[utf16_index] = wchar16ToCodepage437(decoded_text[utf16_index]); // decoded_text to CP437 (in-place conversion) - // toDo: ensure that decoded_text[i] is between console_font_YxZ_first and console_font_YxZ_last - // if (chr < 32 || chr > 126) --> clamp chr - // chr -= 32; // align with font table entries - utf16_index++; + if ((decoded_text[utf16_index] >= 1) && ((decoded_text[utf16_index] <= 254))) utf16_index++; // don't advance on NUL or codes not suppoted in DrawCharacter } } decoded_text[utf16_index] = 0; // NUL terminate string size_t textLength = min(utf16_index, size_t(maxLetters)); + #else const unsigned char* decoded_text = text; // fallback size_t textLength = min(strnlen((char*)text, maxLen), size_t(maxLetters)); #endif + // toDo: ensure that decoded_text[i] is between console_font_YxZ_first and console_font_YxZ_last + // if (chr < 32 || chr > 126) --> clamp chr + // chr -= 32; // align with font table entries + // pass characters to drawCharacter() for (int i = 0; i < textLength; i++) { SEGMENT.drawCharacter((unsigned char) decoded_text[i], x + w*i, y, w, h, color, col2, drawShadow); diff --git a/wled00/src/font/codepage437.cpp b/wled00/src/font/codepage437.cpp index 99ef6b0e..767c992a 100644 --- a/wled00/src/font/codepage437.cpp +++ b/wled00/src/font/codepage437.cpp @@ -1,5 +1,12 @@ #if defined(WLED_ENABLE_FULL_FONTS) +/* + @title WLED(-MM) - unicode to CP437 conversion + @repo https://github.com/MoonModules/WLED-MM, https://github.com/wled/WLED + @Copyright © 2025 Github WLED and WLED-MM Commit Authors (see "git blame" for details) + @license Licensed under the EUPL-1.2 or later +*/ + #include "codepages.h" #include @@ -9,11 +16,18 @@ constexpr uint8_t CP437_UNKNOWN = 250; // small middle dot · // not sure if we // based on a table from https://en.wikipedia.org/wiki/Code_page_437#Character_set uint16_t wchar16ToCodepage437(uint16_t wideChar) { - // codes up to 126 are same as ASCII - if (wideChar < 127) return wideChar; + // unicode codes 0 up to 127 are same as ASCII -> pass through + if ((wideChar < 0x7F) && (wideChar != 0x08)) return wideChar; // excludes 127 = DEL and 8 = BS, so we can map them switch (wideChar) { - // characters 1 - 31 + // original IBM PC would interpret codes 0x07, 0x08, 0x0A, and 0x0D as BEL, BS, LF, and CR, respectively. + // we don't implement any special handling at the moment + case 0x0008: return 0x08; break; // Backspace: pass through (could be handled differently in future) + + // unicode codes mapped to characters 1 - 31 + // unicode 0 = C string terminator -> already passed through, never map it !! + // 1 to 31 (0x01 to 0x1F) are "assorted dingbats" (complementary and decorative characters). + // The isolated character 127 (7Fhex) also belongs to this group. case 0x263A: return 0x01; break; // ☺︎ case 0x263B: return 0x02; break; // ☻ case 0x2665: return 0x03; break; // ♥︎ @@ -46,8 +60,13 @@ uint16_t wchar16ToCodepage437(uint16_t wideChar) { case 0x25B2: return 0x1E; break; // ▲ case 0x25BC: return 0x1F; break; // ▼ - // characters 127 - 254 - case 0x2302: return 0x7F; break; // ⌂ (aka DEL) + // unicode codes 32 to 126 (0x20 to 0x7E) are the standard ASCII printable characters -> already passed through + + // unicode codes mapped to characters 127 - 254 + // code 127 DEL -> small arrow back. We don't implement legacy "rubout" or "backspace" for composing letters or for bold printing + case 0x007F: return 0x1B; break; // ← + case 0x2302: return 0x7F; break; // ⌂ + // 128 to 175 (0x80 to 0xAF) are a selection of international text characters case 0x00C7: return 0x80; break; // Ç case 0x00FC: return 0x81; break; // ü case 0x00E9: return 0x82; break; // é @@ -96,6 +115,7 @@ uint16_t wchar16ToCodepage437(uint16_t wideChar) { case 0x00A1: return 0xAD; break; // ¡ case 0x00AB: return 0xAE; break; // « case 0x00BB: return 0xAF; break; // » + // 176 to 223 (0xB0 to 0xDF) are box drawing and block characters case 0x2591: return 0xB0; break; // ░ case 0x2592: return 0xB1; break; // ▒ case 0x2593: return 0xB2; break; // ▓ @@ -144,6 +164,7 @@ uint16_t wchar16ToCodepage437(uint16_t wideChar) { case 0x258C: return 0xDD; break; // ▌ case 0x2590: return 0xDE; break; // ▐ case 0x2580: return 0xDF; break; // ▀ + // 224 to 235 (0xE0 to 0xEB) are math symbols part 1 - Greek letters commonly used in physics case 0x03B1: return 0xE0; break; // α case 0x00DF: return 0xE1; break; // ß case 0x0393: return 0xE2; break; // Γ @@ -156,6 +177,7 @@ uint16_t wchar16ToCodepage437(uint16_t wideChar) { case 0x0398: return 0xE9; break; // Θ case 0x03A9: return 0xEA; break; // Ω case 0x03B4: return 0xEB; break; // δ + // 236 to 254 (0xEC to 0xFE) are other common physics and math symbols case 0x221E: return 0xEC; break; // ∞ case 0x03C6: return 0xED; break; // φ case 0x03B5: return 0xEE; break; // ε @@ -174,14 +196,16 @@ uint16_t wchar16ToCodepage437(uint16_t wideChar) { case 0x221A: return 0xFB; break; // √ case 0x207F: return 0xFC; break; // ⁿ case 0x00B2: return 0xFD; break; // ² - case 0x25A0: return 0xFE; break; // ■ + case 0x25A0: return 0xFE; break; // ■ geometric shapes + // 255 (0xFF) is "non breakable space" (NBSP) + case 0x00A0: return 32; break; // NBSP -> normal "space" - // special mappings for very similar characters - case 0x00A6: return 0x7C; break; // broken bar -> bar - case 0x266C: return 14; break; // musical notes - case 0x0394: return 127; break; // greek capital delta Δ + // special mappings for very similar unicode characters + case 0x00A6: return 0x7C; break; // ¦ broken bar -> | bar + case 0x266C: return 14; break; // musical note ♬ -> ♫ + case 0x0394: return 127; break; // greek capital delta Δ -> ⌂ case 0x23AE: return 179; break; // integral extension ⎮ - case 0x03B2: return 225; break; // greek small beta β => sz umlaut ß + case 0x03B2: return 225; break; // greek small beta β -> sz umlaut ß case 0x03A0: return 227; break; // greek capital PI Π case 0x220F: return 227; break; // math product ∏ case 0x2211: return 228; break; // math sum ∑ @@ -194,13 +218,13 @@ uint16_t wchar16ToCodepage437(uint16_t wideChar) { case 0x2300: return 237; break; // diameter ⌀ case 0x00D8: return 237; break; // 0 strikethrough Ø case 0x00F8: return 237; break; // 0 strikethrough small ø - case 0x02DA: return 0xF8; break; // small circle (up) ˚ - case 0x2208: return 238; break; // element-of ∈ case 0x017F: return 244; break; // long S ſ + case 0x02DA: return 0xF8; break; // small circle (up) ˚ - case 0x00A0: return 32; break; // NBSP => blank - case 0x20AC: return 238; break; // Euro € - case 0x2713: return 251; break; // check mark ✓ + case 0x2208: return 238; break; // element-of ∈ -> ε + case 0x20AC: return 238; break; // Euro € -> ε + case 0x2713: return 251; break; // check mark ✓ -> √ + case 0x263E: return 0x01; break; // ☾ last quarter moon (Moonmodules) -> ☺︎ face // everything else: unknown //default: return 32; // blank diff --git a/wled00/src/font/codepages.h b/wled00/src/font/codepages.h index bc0c7538..dbb9e4eb 100644 --- a/wled00/src/font/codepages.h +++ b/wled00/src/font/codepages.h @@ -8,9 +8,11 @@ #undef WLED_ENABLE_FULL_FONTS #endif -//constexpr uint16_t UNKNOWN_CODE = 0x2219; // ∙ multiplication dot -constexpr uint16_t UNKNOWN_CODE = 0x00B7; // · middle dot -constexpr uint16_t BAD_CODE = 0x2022; // • bigger dot +// visual replacements when decoding fails +//constexpr uint16_t UNKNOWN_CODE = 0x2219; // ∙ multiplication dot (try this if you don't like the middle dot) +constexpr uint16_t UNKNOWN_CODE = 0x00B7; // · middle dot = unknown code (generic error) +constexpr uint16_t BAD_CODE = 0x2022; // • bigger dot = cannot decode (unicode malformed) +constexpr uint16_t EXT_CODE = 0x263B; // ☻ smiling face = extended code (unicode not supported) // UTF‑8 → reduced UTF‑16 decoding // translates the next unicode UTF-8 item into a 2-byte "code point" diff --git a/wled00/src/font/unicodetool.cpp b/wled00/src/font/unicodetool.cpp index 80312bfa..ff96ab99 100644 --- a/wled00/src/font/unicodetool.cpp +++ b/wled00/src/font/unicodetool.cpp @@ -1,4 +1,9 @@ -#if defined(WLED_ENABLE_FULL_FONTS) +/* + @title WLED(-MM) - unicode helper functions + @repo https://github.com/MoonModules/WLED-MM, https://github.com/wled/WLED + @Copyright © 2025 Github WLED and WLED-MM Commit Authors (see "git blame" for details) + @license Licensed under the EUPL-1.2 or later +*/ #include "codepages.h" #include @@ -35,13 +40,15 @@ uint16_t unicodeToWchar16(const unsigned char* utf8, size_t maxLen) { if (length < 3 || !isValidContinuation(utf8[1]) || !isValidContinuation(utf8[2])) return BAD_CODE; // malformed codepoint = ((ch0 & 0b00001111) << 12) | ((utf8[1] & 0b00111111) << 6) | (utf8[2] & 0b00111111); if (codepoint < 0x800) return UNKNOWN_CODE; // Reject overlong encodings (must be >= 0x800) - if (codepoint >= 0xD800 && codepoint <= 0xDFFF) return UNKNOWN_CODE; // Reject UTF-16 surrogate pairs (U+D800..U+DFFF) - if (codepoint >= 0x010000) codepoint = UNKNOWN_CODE; // result exceeds uint16_t => "unknown" + if (codepoint >= 0xD800 && codepoint <= 0xDFFF) return EXT_CODE; // Reject UTF-16 surrogate pairs (U+D800..U+DFFF) + if (codepoint >= 0x010000) codepoint = EXT_CODE; // result exceeds uint16_t (should not happen with well-formed UTF-8) return uint16_t(codepoint); } } - // 4-byte sequence or invalid lead byte - since we only support up to 0xFFFF, return error marker - return BAD_CODE; // unsupported/invalid + + // since we only support up to 0xFFFF, return error marker + if ((ch0 & 0b11111000) == 0b11110000) return EXT_CODE; // unsupported 4-byte sequence + else return BAD_CODE; // other unsupported/invalid } // returns a pointer to the next unicode item - can be used to "advance" conversion after unicodeToWchar16() @@ -99,5 +106,3 @@ size_t cutUnicodeAt(const unsigned char* utf8, size_t where) { if (utf8[where] > 127) where = max(0, int(where)-1); return where; } - -#endif From e6676372d80eb6068bad42aaa1652dfe80913c9b Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Fri, 21 Nov 2025 17:04:08 +0100 Subject: [PATCH 129/170] refactor / cleanup font selection logic * centralize font selection logic into getFontInfo() * removed unneeded parameter "numberOfChars" from drawText() * new file: wled_fonts.hpp to centralize font management logic (inline) * only compile wchar16ToCodepage437 when WLED_ENABLE_FULL_FONTS * minor cleanup --- wled00/FX.cpp | 18 +++---- wled00/FX.h | 2 +- wled00/FX_2Dfcn.cpp | 58 ++++++++++------------ wled00/src/font/codepage437.cpp | 4 +- wled00/src/font/codepages.h | 20 ++++++-- wled00/wled_fonts.hpp | 87 +++++++++++++++++++++++++++++++++ 6 files changed, 142 insertions(+), 47 deletions(-) create mode 100644 wled00/wled_fonts.hpp diff --git a/wled00/FX.cpp b/wled00/FX.cpp index 564f2bd7..5a543b6c 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -6817,7 +6817,7 @@ uint16_t mode_2Dscrollingtext(void) { char text[WLED_MAX_SEGNAME_LEN+1] = {'\0'}; unsigned maxLen = (SEGMENT.name) ? min(WLED_MAX_SEGNAME_LEN, (int)strlen(SEGMENT.name)) : 0; // WLEDMM make it robust against too long segment names -#if !defined(WLED_ENABLE_FULL_FONTS) +#if !defined(WLED_ENABLE_FULL_FONTS) || defined(ESP8266) if (SEGMENT.name) for (size_t i=0,j=0; i31 && SEGMENT.name[i]<128) text[j++] = SEGMENT.name[i]; // unicode killer #else if (SEGMENT.name) for (size_t i=0,j=0; i drawText() will fall back to just forwarding each char to drawCharacter() void wu_pixel(uint32_t x, uint32_t y, CRGB c); diff --git a/wled00/FX_2Dfcn.cpp b/wled00/FX_2Dfcn.cpp index b1f48980..5a6146ac 100644 --- a/wled00/FX_2Dfcn.cpp +++ b/wled00/FX_2Dfcn.cpp @@ -877,41 +877,35 @@ bool Segment::jsonToPixels(char * name, uint8_t fileNr) { return true; } -#include "src/font/console_font_4x6.h" -#include "src/font/console_font_5x8.h" -#include "src/font/console_font_5x12.h" -#include "src/font/console_font_6x8.h" -#include "src/font/console_font_7x9.h" +#include "wled_fonts.hpp" #if defined(WLED_ENABLE_FULL_FONTS) #include "src/font/codepages.h" #endif // unicode-aware wrapper for drawCharacter(), to be called from mode_2Dscrollingtext() -void Segment::drawText(const unsigned char* text, size_t maxLen, int maxLetters, int16_t x, int16_t y, uint8_t w, uint8_t h, uint32_t color, uint32_t col2, bool drawShadow) { +void Segment::drawText(const unsigned char* text, size_t maxLen, int16_t x, int16_t y, uint8_t w, uint8_t h, uint32_t color, uint32_t col2, bool drawShadow) { if (!isActive()) return; // not active - // ToDO: find font _first/_last, based on width / height + //size_t maxLetters = WLED_MAX_SEGNAME_LEN; + const size_t numberOfChars = strlen((const char *) text); // size in bytes // toDo check if this is duplicate -> maxLen + #if defined(WLED_ENABLE_FULL_FONTS) + FontInfo_t font = getFontInfo(w, h); // use central font selection legic uint16_t decoded_text[WLED_MAX_SEGNAME_LEN+1] = { 0 }; // UTF-16 converted text. Cannot be longer than WLED_MAX_SEGNAME_LEN size_t utf16_index = 0; for(const unsigned char* now = text; now != nullptr && now[0] != '\0'; now = nextUnicode(now, maxLen)) { if (utf16_index < WLED_MAX_SEGNAME_LEN) { decoded_text[utf16_index] = unicodeToWchar16(now, maxLen); // UTF-8 decode into decoded_text decoded_text[utf16_index] = wchar16ToCodepage437(decoded_text[utf16_index]); // decoded_text to CP437 (in-place conversion) - if ((decoded_text[utf16_index] >= 1) && ((decoded_text[utf16_index] <= 254))) utf16_index++; // don't advance on NUL or codes not suppoted in DrawCharacter + if ((decoded_text[utf16_index] >= font.firstChar) && ((decoded_text[utf16_index] <= font.lastChar))) // don't advance on NUL, or on codes not suppoted in DrawCharacter + utf16_index++; } } decoded_text[utf16_index] = 0; // NUL terminate string - size_t textLength = min(utf16_index, size_t(maxLetters)); - + size_t textLength = min(utf16_index, numberOfChars); #else const unsigned char* decoded_text = text; // fallback - size_t textLength = min(strnlen((char*)text, maxLen), size_t(maxLetters)); + size_t textLength = min(strnlen((char*)text, maxLen), numberOfChars); #endif - - // toDo: ensure that decoded_text[i] is between console_font_YxZ_first and console_font_YxZ_last - // if (chr < 32 || chr > 126) --> clamp chr - // chr -= 32; // align with font table entries - // pass characters to drawCharacter() for (int i = 0; i < textLength; i++) { SEGMENT.drawCharacter((unsigned char) decoded_text[i], x + w*i, y, w, h, color, col2, drawShadow); @@ -922,18 +916,12 @@ void Segment::drawText(const unsigned char* text, size_t maxLen, int maxLetters, // only supports: 4x6=24, 5x8=40, 5x12=60, 6x8=48 and 7x9=63 fonts ATM void Segment::drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, uint8_t h, uint32_t color, uint32_t col2, bool drawShadow) { if (!isActive()) return; // not active -#if !defined(WLED_ENABLE_FULL_FONTS) - if (chr < 32 || chr > 126) return; // legacy mode - only ASCII 32-126 supported - chr -= 32; // align with font table entries -#else - // ToDO: clamp to actual font limits - if (chr < 1 || chr > 254) return; // sanity check // ToDO needs improvements - chr = chr -1; // all fonts start at 1 // ToDO needs improvements -#endif - const uint16_t cols = virtualWidth(); const uint16_t rows = virtualHeight(); - const int font = w*h; + FontInfo_t font = getFontInfo(w, h); // use central font selection logic + if (!font.isProgMem || font.width_bytes > 1) return; // do nothing for not (yet) supported font features: width_bytes > 1, !isProgMem + if (chr < font.firstChar || chr > font.lastChar) return; // do nothing when out of limits + chr = chr - font.firstChar; // adjust chr to point to the first allowed character byte CRGB col = CRGB(color); CRGBPalette16 grad = CRGBPalette16(col, (col2 != BLACK) ? CRGB(col2) : col); @@ -941,16 +929,21 @@ void Segment::drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, //if (w<5 || w>6 || h!=8) return; if (drawShadow) w++; // one more column for shadow on right side - for (int i = 0; i= rows) break; // drawing off-screen uint8_t bits = 0; uint8_t bits_up = 0; // WLEDMM this is the previous line: font[(chr * h) + i -1] - // ToDO: move font selection logic into separate function - - switch (font) { // font = w * h +#if 1 + // new code - experimental + bits = pgm_read_byte_near(&font.raw[(chr * h) + i]); + if ((i>0) && drawShadow) bits_up = pgm_read_byte_near(&font.raw[(chr * h) + i -1]); +#else + // legacy code, will be deleted after some tests + int pixels = w*h; + switch (pixels) { // font = w * h case 24: bits = pgm_read_byte_near(&console_font_4x6[(chr * h) + i]); if ((i>0) && drawShadow) bits_up = pgm_read_byte_near(&console_font_4x6[(chr * h) + i -1]); break; // 4x6 font @@ -968,17 +961,18 @@ void Segment::drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, break; // 5x12 font default: return; } +#endif if (col2 != BLACK) col = ColorFromPalette(grad, (i+1)*255/h, 255, NOBLEND); uint32_t fgCol = uint32_t(col) & 0x00FFFFFF; // WLEDMM cache color value - for (int j = 0; j 0 && x0 < cols" if ((bits>>(j+(8-w))) & 0x01) { // bit set & drawing on-screen setPixelColorXY(x0, y0, fgCol); } else { if (drawShadow) { - // WLEDMM + // WLEDMM if ((j < (w-1)) && (bits>>(j+(8-w) +1)) & 0x01) setPixelColorXY(x0, y0, bgCol); // blank when pixel to the right is set else if ((j > 0) && (bits>>(j+(8-w) -1)) & 0x01) setPixelColorXY(x0, y0, bgCol);// blank when pixel to the left is set else if ((bits_up>>(j+(8-w))) & 0x01) setPixelColorXY(x0, y0, bgCol); // blank when pixel above is set diff --git a/wled00/src/font/codepage437.cpp b/wled00/src/font/codepage437.cpp index 767c992a..ebdb8891 100644 --- a/wled00/src/font/codepage437.cpp +++ b/wled00/src/font/codepage437.cpp @@ -1,5 +1,3 @@ -#if defined(WLED_ENABLE_FULL_FONTS) - /* @title WLED(-MM) - unicode to CP437 conversion @repo https://github.com/MoonModules/WLED-MM, https://github.com/wled/WLED @@ -7,6 +5,8 @@ @license Licensed under the EUPL-1.2 or later */ +#if defined(WLED_ENABLE_FULL_FONTS) + #include "codepages.h" #include diff --git a/wled00/src/font/codepages.h b/wled00/src/font/codepages.h index dbb9e4eb..04317050 100644 --- a/wled00/src/font/codepages.h +++ b/wled00/src/font/codepages.h @@ -8,7 +8,7 @@ #undef WLED_ENABLE_FULL_FONTS #endif -// visual replacements when decoding fails +// UTF-16 visual replacements when decoding fails //constexpr uint16_t UNKNOWN_CODE = 0x2219; // ∙ multiplication dot (try this if you don't like the middle dot) constexpr uint16_t UNKNOWN_CODE = 0x00B7; // · middle dot = unknown code (generic error) constexpr uint16_t BAD_CODE = 0x2022; // • bigger dot = cannot decode (unicode malformed) @@ -19,6 +19,11 @@ constexpr uint16_t EXT_CODE = 0x263B; // ☻ smiling face = extended cod // return "•" in case of input errors, and for unsupported/invalid UTF-8 uint16_t unicodeToWchar16(const unsigned char* utf8, size_t maxLen); // unicodetool.cpp +#if defined(WLED_ENABLE_FULL_FONTS) +// translates unicode 2-byte (UTF-16) "code point" into corresponding character in codepage 437 (IBM PC aka PC-8) +uint16_t wchar16ToCodepage437(uint16_t wideChar); // codepage437.cpp +#endif + // returns a pointer to the next unicode item - can be used to "advance" conversion after unicodeToWchar16() // return nullptr at end of input const unsigned char* nextUnicode(const unsigned char* utf8, size_t maxLen); // unicodetool.cpp @@ -30,7 +35,16 @@ size_t strlenUC(const unsigned char* utf8); // Important: calling code is responsible to provide a string with at least _where_ chars size_t cutUnicodeAt(const unsigned char* utf8, size_t where); -// translates unicode 2-byte (UTF-16) "code point" into corresponding character in codepage 437 (IBM PC aka PC-8) -uint16_t wchar16ToCodepage437(uint16_t wideChar); // codepage437.cpp + +// special utility function for @troyhacks ;-) +// removes all unicode letter from a C style char[] - conversion is in-place, to avoid heap fragging +// doesn't work on PROGMEM strings, unless you strdup() them into RAM before calling this function +inline void killUnicode(unsigned char* utf8) { + if (utf8 == nullptr) return; + size_t clean_index = 0; + for (size_t i=0; utf8[i] != '\0'; i++) + if ((utf8[i] > 0) && (utf8[i] < 128)) utf8[clean_index++] = utf8[i]; // only keep pure ASCII; unicode extended chars start at 128 + utf8[clean_index] = '\0'; // ensure proper string termination +} #endif diff --git a/wled00/wled_fonts.hpp b/wled00/wled_fonts.hpp new file mode 100644 index 00000000..909e1e65 --- /dev/null +++ b/wled00/wled_fonts.hpp @@ -0,0 +1,87 @@ +#pragma once +#ifndef WLED_FONTS_H +#define WLED_FONTS_H +#include // needed to get uint16_t definition +#include // helps for code analysis with clang + +// always disable unicode for 8266 builds - not enough program space +#if !defined(ARDUINO_ARCH_ESP32) && defined(WLED_ENABLE_FULL_FONTS) +#undef WLED_ENABLE_FULL_FONTS +#endif + + +// pull in all fonts +#include "src/font/console_font_4x6.h" +#include "src/font/console_font_5x8.h" +#include "src/font/console_font_5x12.h" +#include "src/font/console_font_6x8.h" +#include "src/font/console_font_7x9.h" + + +// fontInfo struct returned by getFontInfo +typedef struct { + unsigned firstChar; // first supported glyph (32 for standard "reduced" fonts) + unsigned lastChar; // last supported glyph (126 for standard "reduced" fonts) + unsigned width_bytes; // single letter width in bytes (default:1) + // unsigned height_bytes; // future support + bool isProgMem; // raw data points into ProgMem => 8266 needs pgm_read_byte_near() + const unsigned char* raw; // array of bytes with raw pixeldata (typicially lives in PROGMEM) + // note: we only support monospaced fonts +} FontInfo_t; + +// logic for font selection based on width and height +inline FontInfo_t getFontInfo(unsigned width, unsigned height) { + static FontInfo_t font = {0}; // not sure if this needs to be static - just wanted to be sure that the function return value is not in the stack area (use-after-free). + + unsigned pixels = width * height; + switch (pixels) { + // WLED standard fonts (PROGMEM) + case 24: // 4x6 font + font.raw = console_font_4x6; + font.isProgMem = true; + font.firstChar = console_font_4x6_first; + font.lastChar = console_font_4x6_last; + font.width_bytes= 1; + break; + case 40: // 5x8 font + font.raw = console_font_5x8; + font.isProgMem = true; + font.firstChar = console_font_5x8_first; + font.lastChar = console_font_5x8_last; + font.width_bytes= 1; + break; + case 48: // 6x8 font + font.raw = console_font_6x8; + font.isProgMem = true; + font.firstChar = console_font_6x8_first; + font.lastChar = console_font_6x8_last; + font.width_bytes= 1; + break; + case 63: // 7x9 font + font.raw = console_font_7x9; + font.isProgMem = true; + font.firstChar = console_font_7x9_first; + font.lastChar = console_font_7x9_last; + font.width_bytes= 1; + break; + case 60: // 5x12 font + font.raw = console_font_5x12; + font.isProgMem = true; + font.firstChar = console_font_5x12_first; + font.lastChar = console_font_5x12_last; + font.width_bytes= 1; + break; + + // you can add any custom fonts here + + default: // no font + font.raw = nullptr; + font.isProgMem = false; + font.firstChar = 1; + font.lastChar = 1; + font.width_bytes= 1; + } + return font; +} + +#endif From e38c2b32c83de11b0640b363da90d59d1024c8a9 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Fri, 21 Nov 2025 17:26:04 +0100 Subject: [PATCH 130/170] finishing touches * replace strlen with strnlen * avoid static variable in getFontInfo * remove legacy code in drawCharacter (new code works well) it works for me, let's ship it ;-) --- wled00/FX_2Dfcn.cpp | 30 +++++------------------------- wled00/wled_fonts.hpp | 2 +- 2 files changed, 6 insertions(+), 26 deletions(-) diff --git a/wled00/FX_2Dfcn.cpp b/wled00/FX_2Dfcn.cpp index 5a6146ac..f58ba016 100644 --- a/wled00/FX_2Dfcn.cpp +++ b/wled00/FX_2Dfcn.cpp @@ -886,7 +886,7 @@ bool Segment::jsonToPixels(char * name, uint8_t fileNr) { void Segment::drawText(const unsigned char* text, size_t maxLen, int16_t x, int16_t y, uint8_t w, uint8_t h, uint32_t color, uint32_t col2, bool drawShadow) { if (!isActive()) return; // not active //size_t maxLetters = WLED_MAX_SEGNAME_LEN; - const size_t numberOfChars = strlen((const char *) text); // size in bytes // toDo check if this is duplicate -> maxLen + const size_t numberOfChars = strnlen((const char *) text, maxLen); // size in bytes // toDo check if this is needed - duplicate of maxLen? #if defined(WLED_ENABLE_FULL_FONTS) FontInfo_t font = getFontInfo(w, h); // use central font selection legic @@ -936,32 +936,12 @@ void Segment::drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, uint8_t bits = 0; uint8_t bits_up = 0; // WLEDMM this is the previous line: font[(chr * h) + i -1] -#if 1 - // new code - experimental + // for wide fonts, we can add a loop here :for(offset=0, offset < font.width_bytes; offset++) {} + + // get 8 pixels (byte) from raw font data bits = pgm_read_byte_near(&font.raw[(chr * h) + i]); if ((i>0) && drawShadow) bits_up = pgm_read_byte_near(&font.raw[(chr * h) + i -1]); -#else - // legacy code, will be deleted after some tests - int pixels = w*h; - switch (pixels) { // font = w * h - case 24: bits = pgm_read_byte_near(&console_font_4x6[(chr * h) + i]); - if ((i>0) && drawShadow) bits_up = pgm_read_byte_near(&console_font_4x6[(chr * h) + i -1]); - break; // 4x6 font - case 40: bits = pgm_read_byte_near(&console_font_5x8[(chr * h) + i]); - if ((i>0) && drawShadow) bits_up = pgm_read_byte_near(&console_font_5x8[(chr * h) + i -1]); - break; // 5x8 font - case 48: bits = pgm_read_byte_near(&console_font_6x8[(chr * h) + i]); - if ((i>0) && drawShadow) bits_up = pgm_read_byte_near(&console_font_6x8[(chr * h) + i -1]); - break; // 6x8 font - case 63: bits = pgm_read_byte_near(&console_font_7x9[(chr * h) + i]); - if ((i>0) && drawShadow) bits_up = pgm_read_byte_near(&console_font_7x9[(chr * h) + i -1]); - break; // 7x9 font - case 60: bits = pgm_read_byte_near(&console_font_5x12[(chr * h) + i]); - if ((i>0) && drawShadow) bits_up = pgm_read_byte_near(&console_font_5x12[(chr * h) + i -1]); - break; // 5x12 font - default: return; - } -#endif + if (col2 != BLACK) col = ColorFromPalette(grad, (i+1)*255/h, 255, NOBLEND); uint32_t fgCol = uint32_t(col) & 0x00FFFFFF; // WLEDMM cache color value diff --git a/wled00/wled_fonts.hpp b/wled00/wled_fonts.hpp index 909e1e65..f1ffa8d3 100644 --- a/wled00/wled_fonts.hpp +++ b/wled00/wled_fonts.hpp @@ -31,7 +31,7 @@ typedef struct { // logic for font selection based on width and height inline FontInfo_t getFontInfo(unsigned width, unsigned height) { - static FontInfo_t font = {0}; // not sure if this needs to be static - just wanted to be sure that the function return value is not in the stack area (use-after-free). + FontInfo_t font = {0}; // will be returned by value unsigned pixels = width * height; switch (pixels) { From ec97f4903f580961c2347eb45394dc6342a51128 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sat, 22 Nov 2025 16:30:16 +0100 Subject: [PATCH 131/170] don't include any font when building with WLED_DISABLE_2D saves up to 12Kb program space in flash --- wled00/wled_fonts.hpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/wled00/wled_fonts.hpp b/wled00/wled_fonts.hpp index f1ffa8d3..13d9059d 100644 --- a/wled00/wled_fonts.hpp +++ b/wled00/wled_fonts.hpp @@ -9,6 +9,7 @@ #undef WLED_ENABLE_FULL_FONTS #endif +#if !defined(WLED_DISABLE_2D) // don't include any font in 1D-only builds - saves up to 12Kb of flash // pull in all fonts #include "src/font/console_font_4x6.h" @@ -17,6 +18,7 @@ #include "src/font/console_font_6x8.h" #include "src/font/console_font_7x9.h" +#endif // fontInfo struct returned by getFontInfo typedef struct { @@ -35,6 +37,7 @@ inline FontInfo_t getFontInfo(unsigned width, unsigned height) { unsigned pixels = width * height; switch (pixels) { +#if !defined(WLED_DISABLE_2D) // no fonts in 1D-only builds // WLED standard fonts (PROGMEM) case 24: // 4x6 font font.raw = console_font_4x6; @@ -74,6 +77,7 @@ inline FontInfo_t getFontInfo(unsigned width, unsigned height) { // you can add any custom fonts here +#endif default: // no font font.raw = nullptr; font.isProgMem = false; From d8e07d160997919259c150072a4a1f1868d55cd3 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sat, 22 Nov 2025 18:06:02 +0100 Subject: [PATCH 132/170] partition files for use with ADAFRUIT boards these partition files preserve the special "UF2" bootloader that is necessary for adafruit -S2 and -S3 boards. --- tools/partitions-16MB_spiffs-tinyuf2.csv | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 tools/partitions-16MB_spiffs-tinyuf2.csv diff --git a/tools/partitions-16MB_spiffs-tinyuf2.csv b/tools/partitions-16MB_spiffs-tinyuf2.csv new file mode 100644 index 00000000..238710e9 --- /dev/null +++ b/tools/partitions-16MB_spiffs-tinyuf2.csv @@ -0,0 +1,10 @@ +# ESP-IDF Partition Table +# Name, Type, SubType, Offset, Size, Flags +# bootloader.bin,, 0x1000, 32K +# partition table,, 0x8000, 4K +nvs, data, nvs, 0x9000, 20K, +otadata, data, ota, 0xe000, 8K, +ota_0, app, ota_0, 0x10000, 2048K, +ota_1, app, ota_1, 0x210000, 2048K, +uf2, app, factory,0x410000, 256K, +spiffs, data, spiffs, 0x450000, 11968K, From f4d890c584d60fce30a2e781b0db71da7dcd41f3 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sun, 23 Nov 2025 00:53:38 +0100 Subject: [PATCH 133/170] adding "-D SR_DMTYPE=254" to classic esp32 builds with HUB75 support on classic esp32, the HUB75 driver uses the I2S unit. Set AR default to "receive only", to prevent driver conflicts. --- platformio.ini | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index e6f61d37..ec1e44fe 100644 --- a/platformio.ini +++ b/platformio.ini @@ -1618,6 +1618,7 @@ build_flags = ${esp32_4MB_V4_S_base.esp32_build_flags} ; -D SR_DEBUG ; -D MIC_LOGGER ${common_mm.HUB75_build_flags} + -D SR_DMTYPE=254 ;; HUB75 driver needs the I2S unit - set AR default mode to 'Network Receive Only' to prevent driver conflicts. -D WLED_DISABLE_PARTICLESYSTEM1D ;; exceeds flash size limit lib_deps = ${esp32_4MB_V4_S_base.esp32_lib_deps} ${common_mm.HUB75_lib_deps} @@ -1642,6 +1643,7 @@ build_flags = ${esp32_4MB_V4_S_base.esp32_build_flags} ; -D SR_DEBUG ; -D MIC_LOGGER ${common_mm.HUB75_build_flags} + -D SR_DMTYPE=254 ;; HUB75 driver needs the I2S unit - set AR default mode to 'Network Receive Only' to prevent driver conflicts. -D WLED_USE_ETHERNET -D WLED_DISABLE_ESPNOW ;; ESP-NOW requires wifi, may crash with ethernet only lib_deps = ${esp32_4MB_V4_S_base.esp32_lib_deps} @@ -1684,7 +1686,8 @@ build_flags = ${esp32_4MB_V4_S_base.esp32_build_flags} ;; -D SR_DEBUG -D WLED_BOOTUPDELAY=350 ${common_mm.HUB75_build_flags} - -DESP32_FORUM_PINOUT + -DESP32_FORUM_PINOUT + -D SR_DMTYPE=254 ;; HUB75 driver needs the I2S unit - set AR default mode to 'Network Receive Only' to prevent driver conflicts. ${common_mm.animartrix_build_flags} ;;-DARDUINO_EVENT_RUNNING_CORE=0 ;; assign Wifi to core0, to have more CPU on core#1 (arduino loop) ;;-DARDUINO_RUNNING_CORE=1 ;; should be default, but does not hurt @@ -1747,6 +1750,7 @@ build_flags = ${esp32_4MB_V4_S_base.esp32_build_flags} -D JSON_BUFFER_SIZE=18432 -D MIN_HEAP_SIZE=6144 -D MAX_SEGMENT_DATA=40960 ;; default 32767 ${common_mm.HUB75_build_flags} + -D SR_DMTYPE=254 ;; HUB75 driver needs the I2S unit - set AR default mode to 'Network Receive Only' to prevent driver conflicts. ${common_mm.animartrix_build_flags} lib_deps = ${esp32_4MB_V4_S_base.esp32_lib_deps} ${common_mm.HUB75_lib_deps} @@ -1773,6 +1777,7 @@ build_flags = ${esp32_4MB_V4_M_base.esp32_build_flags} -D FLD_PIN_SCL=-1 -D FLD_PIN_SDA=-1 ; use global! -D HW_PIN_SCL=22 -D HW_PIN_SDA=21 ${common_mm.HUB75_build_flags} + -D SR_DMTYPE=254 ;; HUB75 driver needs the I2S unit - set AR default mode to 'Network Receive Only' to prevent driver conflicts. ${common_mm.animartrix_build_flags} lib_deps = ${esp32_4MB_V4_M_base.esp32_lib_deps} ${common_mm.HUB75_lib_deps} @@ -1835,6 +1840,7 @@ build_flags = ${esp32_4MB_V4_S_base.esp32_build_flags} ; -D SR_DEBUG ; -D MIC_LOGGER ${common_mm.HUB75_build_flags} + -D SR_DMTYPE=254 ;; HUB75 driver needs the I2S unit - set AR default mode to 'Network Receive Only' to prevent driver conflicts. lib_deps = ${esp32_4MB_V4_S_base.esp32_lib_deps} ${common_mm.HUB75_lib_deps} lib_ignore = @@ -1886,6 +1892,7 @@ build_flags = ${esp32_4MB_V4_S_base.esp32_build_flags} ; -D SR_DEBUG ; -D MIC_LOGGER ${common_mm.HUB75_build_flags} + -D SR_DMTYPE=254 ;; HUB75 driver needs the I2S unit - set AR default mode to 'Network Receive Only' to prevent driver conflicts. lib_deps = ${esp32_4MB_V4_S_base.esp32_lib_deps} ${common_mm.HUB75_lib_deps} lib_ignore = From 086ae216c86fe14c5fadba4311c5ace63ba9ff3e Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sun, 23 Nov 2025 01:09:52 +0100 Subject: [PATCH 134/170] partitions file for boards with 32MB flash, buildenv for WROOM-2 32MB --- platformio.ini | 15 ++++++++++++++- tools/WLED_ESP32_32MB.csv | 7 +++++++ 2 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 tools/WLED_ESP32_32MB.csv diff --git a/platformio.ini b/platformio.ini index ec1e44fe..2b4ebd8b 100644 --- a/platformio.ini +++ b/platformio.ini @@ -2127,7 +2127,7 @@ board_upload.maximum_size =16777216 ;; MM for ESP32-S3 WROOM-2, a.k.a. ESP32-S3 DevKitC-1 v1.1 -;; with >= 16MB FLASH and >= 8MB PSRAM (memory_type: opi_opi) +;; with 16MB FLASH and >= 8MB PSRAM (memory_type: opi_opi) ;; includes HUB75 and AnimArtix [env:esp32S3_WROOM-2_M] extends = env:esp32S3_8MB_PSRAM_M @@ -2161,6 +2161,19 @@ lib_deps = ${esp32s3.lib_deps} ${common_mm.lib_deps_S} ${common_mm.lib_deps_V4_ ${common_mm.HUB75_lib_deps} ${common_mm.animartrix_lib_deps} +;; MM for ESP32-S3 WROOM-2 with 32MB flash and PSRAM +[env:esp32S3_WROOM-2_M_32MB] +extends = env:esp32S3_WROOM-2_M +board_build.partitions = tools/WLED_ESP32_32MB.csv +board_upload.flash_size = 32MB +board_upload.maximum_size = 33554432 +;; replace WLED_RELEASE_NAME, keep everything else +build_unflags = ${env:esp32S3_WROOM-2_M.build_unflags} + -D WLED_RELEASE_NAME=esp32S3_WROOM-2_M +build_flags = ${env:esp32S3_WROOM-2_M.build_flags} + -D WLED_RELEASE_NAME=esp32S3_WROOM-2_M_32MB + + ;; MM for esp32-s3 zero/supermini and lolin S3 mini boards - fastpath, optimize for speed [env:esp32S3_4MB_PSRAM_S] extends = env:esp32S3_8MB_S diff --git a/tools/WLED_ESP32_32MB.csv b/tools/WLED_ESP32_32MB.csv new file mode 100644 index 00000000..2aa06e6f --- /dev/null +++ b/tools/WLED_ESP32_32MB.csv @@ -0,0 +1,7 @@ +# Name, Type, SubType, Offset, Size, Flags +nvs, data, nvs, 0x9000, 0x5000, +otadata, data, ota, 0xe000, 0x2000, +app0, app, ota_0, 0x10000, 0x300000, +app1, app, ota_1, 0x310000,0x300000, +spiffs, data, spiffs, 0x610000,0x19E0000, +coredump, data, coredump,,64K From 424416d51a92e4c80dd11191e81957cecf896787 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sun, 23 Nov 2025 02:28:47 +0100 Subject: [PATCH 135/170] hotfix: Disable deviceId retrieval to avoid crashes Temporarily disable deviceID retrieval to prevent crashes on some ESP32 boards. This prevents the DeviceID from being added to /json/info, until we find a solution that does not crash my esp32. --- wled00/json.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/wled00/json.cpp b/wled00/json.cpp index 8b40f9e9..fae351f0 100644 --- a/wled00/json.cpp +++ b/wled00/json.cpp @@ -938,7 +938,8 @@ void serializeInfo(JsonObject root) //root[F("cn")] = F(WLED_CODENAME); //WLEDMM removed root[F("release")] = FPSTR(releaseString); root[F("rel")] = FPSTR(releaseString); //WLEDMM to add bin name - root[F("deviceId")] = getDeviceId(); + + // root[F("deviceId")] = getDeviceId(); // temporarily disabled, as getDeviceId() causes a crash on some esp32 boards. JsonObject leds = root.createNestedObject("leds"); leds[F("count")] = strip.getLengthTotal(); From e0c7d254bbfea1a7679aed0a10d135ba373f0bd2 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sun, 23 Nov 2025 17:18:10 +0100 Subject: [PATCH 136/170] fix outdated URLs Aircoookie Wiki => mm.kno.wled.ge MoonModules/WLED => MoonModules/WLED-MM Aircoookie/WLED => wled/WLED 2024 => 2025 --- CHANGELOG.md | 2 +- package.json | 6 +++--- tools/cdata.js | 3 +++ usermods/audioreactive/audio_reactive.h | 6 +++--- usermods/audioreactive/audio_source.h | 6 +++--- .../usermod_v2_auto_playlist.h | 6 +++--- wled00/FX.cpp | 8 ++++---- wled00/data/index.js | 2 +- wled00/data/settings_dmx.htm | 2 +- wled00/data/settings_sec.htm | 10 +++++----- wled00/data/settings_um.htm | 2 +- wled00/data/simple.js | 2 +- wled00/data/update.htm | 4 ++-- 13 files changed, 31 insertions(+), 28 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6369804d..fc4d034d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -## [WLED upstream](https://github.com/Aircoookie/WLED/tree/0_14_1) changelog +## [WLED upstream](https://github.com/wled/WLED/tree/0_14_1) changelog #### Build 2403290 - WLED 0.14.3 release diff --git a/package.json b/package.json index 0e0d78d7..9487b088 100644 --- a/package.json +++ b/package.json @@ -13,14 +13,14 @@ }, "repository": { "type": "git", - "url": "git+https://github.com/MoonModules/WLED.git" + "url": "git+https://github.com/MoonModules/WLED-MM.git" }, "author": "", "license": "EUPL-1.2", "bugs": { - "url": "https://github.com/MoonModules/WLED/issues" + "url": "https://github.com/MoonModules/WLED-MM/issues" }, - "homepage": "https://github.com/MoonModules/WLED#readme", + "homepage": "https://github.com/MoonModules/WLED-MM#readme", "dependencies": { "clean-css": "^4.2.3", "html-minifier-terser": "^5.1.1", diff --git a/tools/cdata.js b/tools/cdata.js index 561d390e..f8bd7610 100644 --- a/tools/cdata.js +++ b/tools/cdata.js @@ -63,7 +63,10 @@ function adoptVersionAndRepo(html) { // Replace we html = strReplace(html, "https://github.com/atuline/WLED", repoUrl); html = strReplace(html, "https://github.com/Aircoookie/WLED", repoUrl); + html = strReplace(html, "https://github.com/wled-dev/WLED", repoUrl); + html = strReplace(html, "https://github.com/wled/WLED", repoUrl); html = strReplace(html, "https://github.com/MoonModules/WLED", repoUrl); //WLEDMM + html = strReplace(html, "https://github.com/MoonModules/WLED-MM", repoUrl); //WLEDMM } let version = packageJson.version; if (version) { diff --git a/usermods/audioreactive/audio_reactive.h b/usermods/audioreactive/audio_reactive.h index 9a9a4e7d..731f96c5 100644 --- a/usermods/audioreactive/audio_reactive.h +++ b/usermods/audioreactive/audio_reactive.h @@ -3,9 +3,9 @@ /* @title MoonModules WLED - audioreactive usermod @file audio_reactive.h - @repo https://github.com/MoonModules/WLED, submit changes to this file as PRs to MoonModules/WLED - @Authors https://github.com/MoonModules/WLED/commits/mdev/ - @Copyright © 2024 Github MoonModules Commit Authors (contact moonmodules@icloud.com for details) + @repo https://github.com/MoonModules/WLED-MM, submit changes to this file as PRs to MoonModules/WLED-MM + @Authors https://github.com/MoonModules/WLED-MM/commits/mdev/ + @Copyright © 2024,2025 Github MoonModules Commit Authors (contact moonmodules@icloud.com for details) @license Licensed under the EUPL-1.2 or later */ diff --git a/usermods/audioreactive/audio_source.h b/usermods/audioreactive/audio_source.h index c4de4e33..6d31e029 100644 --- a/usermods/audioreactive/audio_source.h +++ b/usermods/audioreactive/audio_source.h @@ -3,9 +3,9 @@ /* @title MoonModules WLED - audioreactive usermod @file audio_source.h - @repo https://github.com/MoonModules/WLED, submit changes to this file as PRs to MoonModules/WLED - @Authors https://github.com/MoonModules/WLED/commits/mdev/ - @Copyright © 2024 Github MoonModules Commit Authors (contact moonmodules@icloud.com for details) + @repo https://github.com/MoonModules/WLED-MM, submit changes to this file as PRs to MoonModules/WLED-MM + @Authors https://github.com/MoonModules/WLED-MM/commits/mdev/ + @Copyright © 2024,2025 Github MoonModules Commit Authors (contact moonmodules@icloud.com for details) @license Licensed under the EUPL-1.2 or later */ diff --git a/usermods/usermod_v2_auto_playlist/usermod_v2_auto_playlist.h b/usermods/usermod_v2_auto_playlist/usermod_v2_auto_playlist.h index 15a55e27..1e608ad3 100644 --- a/usermods/usermod_v2_auto_playlist/usermod_v2_auto_playlist.h +++ b/usermods/usermod_v2_auto_playlist/usermod_v2_auto_playlist.h @@ -3,9 +3,9 @@ /* @title MoonModules WLED - auto-playlist usermod @file usermod_v2_auto_playlist.h - @repo https://github.com/MoonModules/WLED, submit changes to this file as PRs to MoonModules/WLED - @Authors https://github.com/MoonModules/WLED/commits/mdev/ - @Copyright © 2024 Github MoonModules Commit Authors (contact moonmodules@icloud.com for details) + @repo https://github.com/MoonModules/WLED-MM, submit changes to this file as PRs to MoonModules/WLED-MM + @Authors https://github.com/MoonModules/WLED-MM/commits/mdev/ + @Copyright © 2024,2025 Github MoonModules Commit Authors (contact moonmodules@icloud.com for details) @license Licensed under the EUPL-1.2 or later */ diff --git a/wled00/FX.cpp b/wled00/FX.cpp index 5a543b6c..a900eb1a 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -8854,8 +8854,8 @@ static const char _data_FX_MODE_2DWAVINGCELL[] PROGMEM = "Waving Cell@!,,Amplitu /* @title MoonModules WLED - GEQ 3D Effect @file included in FX.cpp - @repo https://github.com/MoonModules/WLED, submit changes to this file as PRs to MoonModules/WLED - @Authors https://github.com/MoonModules/WLED/commits/mdev/ + @repo https://github.com/MoonModules/WLED-MM, submit changes to this file as PRs to MoonModules/WLED-MM + @Authors https://github.com/MoonModules/WLED-MM/commits/mdev/ @Copyright © 2024 Github MoonModules Commit Authors (contact moonmodules@icloud.com for details) @license Licensed under the EUPL-1.2 or later */ @@ -9001,8 +9001,8 @@ static const char _data_FX_MODE_GEQLASER[] PROGMEM = "GEQ 3D ☾@Speed,Front Fil /* @title MoonModules WLED - Painbrush Effect @file included in FX.cpp - @repo https://github.com/MoonModules/WLED, submit changes to this file as PRs to MoonModules/WLED - @Authors https://github.com/MoonModules/WLED/commits/mdev/ + @repo https://github.com/MoonModules/WLED-MM, submit changes to this file as PRs to MoonModules/WLED-MM + @Authors https://github.com/MoonModules/WLED-MM/commits/mdev/ @Copyright © 2024 Github MoonModules Commit Authors (contact moonmodules@icloud.com for details) @license GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 diff --git a/wled00/data/index.js b/wled00/data/index.js index a1b564ec..15ee1a91 100644 --- a/wled00/data/index.js +++ b/wled00/data/index.js @@ -3224,7 +3224,7 @@ setInterval(()=>{ gId('heartMM').style.color = `hsl(${hc}, 100%, 50%)`; }, 910); -function openGH() { window.open("https://github.com/Aircoookie/WLED/wiki"); } +function openGH() { window.open("https://mm.kno.wled.ge/"); } var cnfr = false; function cnfReset() diff --git a/wled00/data/settings_dmx.htm b/wled00/data/settings_dmx.htm index 30a62fe5..17fba354 100644 --- a/wled00/data/settings_dmx.htm +++ b/wled00/data/settings_dmx.htm @@ -7,7 +7,7 @@
${isMSeg?'Start X':'Start LED'}