diff --git a/buildroot-external/board/amlogic/patches/linux/000_amlogic.patch b/buildroot-external/board/amlogic/patches/linux/000_amlogic.patch new file mode 100644 index 000000000..1091e0ba3 --- /dev/null +++ b/buildroot-external/board/amlogic/patches/linux/000_amlogic.patch @@ -0,0 +1,16503 @@ +diff -ruN main/arch/arm64/boot/dts/amlogic/Makefile mod/arch/arm64/boot/dts/amlogic/Makefile +--- main/arch/arm64/boot/dts/amlogic/Makefile 2023-03-07 09:42:01.821535615 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/Makefile 2023-03-07 09:42:03.221546473 +0100 +@@ -5,18 +5,38 @@ + dtb-$(CONFIG_ARCH_MESON) += meson-axg-jethome-jethub-j110-rev-3.dtb + dtb-$(CONFIG_ARCH_MESON) += meson-axg-s400.dtb + dtb-$(CONFIG_ARCH_MESON) += meson-g12a-radxa-zero.dtb ++dtb-$(CONFIG_ARCH_MESON) += meson-g12a-s905l3a-cm311.dtb ++dtb-$(CONFIG_ARCH_MESON) += meson-g12a-s905l3a-e900v22c.dtb ++dtb-$(CONFIG_ARCH_MESON) += meson-g12a-s905l3a-m401a.dtb + dtb-$(CONFIG_ARCH_MESON) += meson-g12a-sei510.dtb ++dtb-$(CONFIG_ARCH_MESON) += meson-g12a-tanix-tx5max.dtb + dtb-$(CONFIG_ARCH_MESON) += meson-g12a-u200.dtb + dtb-$(CONFIG_ARCH_MESON) += meson-g12a-x96-max.dtb ++dtb-$(CONFIG_ARCH_MESON) += meson-g12a-x96-max-rmii.dtb + dtb-$(CONFIG_ARCH_MESON) += meson-g12b-a311d-khadas-vim3.dtb ++dtb-$(CONFIG_ARCH_MESON) += meson-g12b-dreambox-one.dtb ++dtb-$(CONFIG_ARCH_MESON) += meson-g12b-dreambox-two.dtb + dtb-$(CONFIG_ARCH_MESON) += meson-g12b-gsking-x.dtb + dtb-$(CONFIG_ARCH_MESON) += meson-g12b-gtking-pro.dtb + dtb-$(CONFIG_ARCH_MESON) += meson-g12b-gtking.dtb ++dtb-$(CONFIG_ARCH_MESON) += meson-g12b-gtking-oc.dtb ++dtb-$(CONFIG_ARCH_MESON) += meson-g12b-gtking-pro-h.dtb ++dtb-$(CONFIG_ARCH_MESON) += meson-g12b-gtking-pro-h-oc.dtb ++dtb-$(CONFIG_ARCH_MESON) += meson-g12b-gtking-pro-rev_a.dtb ++dtb-$(CONFIG_ARCH_MESON) += meson-g12b-gtking-pro-rev_a-oc.dtb + dtb-$(CONFIG_ARCH_MESON) += meson-g12b-odroid-n2-plus.dtb + dtb-$(CONFIG_ARCH_MESON) += meson-g12b-odroid-n2.dtb ++dtb-$(CONFIG_ARCH_MESON) += meson-g12b-radxa-zero2.dtb + dtb-$(CONFIG_ARCH_MESON) += meson-g12b-s922x-khadas-vim3.dtb + dtb-$(CONFIG_ARCH_MESON) += meson-g12b-ugoos-am6.dtb ++dtb-$(CONFIG_ARCH_MESON) += meson-g12b-ugoos-am6-plus.dtb ++dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-beelink-mini-mx.dtb ++dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-beelink-mini-mxiii.dtb + dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-kii-pro.dtb ++dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-mecool-kii-pro.dtb ++dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-mecool-ki-plus.dtb ++dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-minix-neo-u1.dtb ++dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-mxq-pro-plus.dtb + dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-nanopi-k2.dtb + dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-nexbox-a95x.dtb + dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-odroidc2.dtb +@@ -31,39 +51,83 @@ + dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s805x-p241.dtb + dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905d-libretech-pc.dtb + dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905d-mecool-kii-pro.dtb ++dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905d-mecool-ki-plus.dtb ++dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905d-mecool-ki-pro.dtb ++dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905d-mecool-m8s-plus.dtb + dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905d-p230.dtb + dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905d-p231.dtb + dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905d-phicomm-n1.dtb ++dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905d-phicomm-n1-thresh.dtb + dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905d-sml5442tw.dtb + dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905d-vero4k-plus.dtb ++dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905l2-ipbs9505.dtb ++dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905l2-x7-5g.dtb ++dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905l3b-e900v22e.dtb ++dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905l3b-m302a.dtb ++dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905l-venz-v10.dtb + dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905w-jethome-jethub-j80.dtb + dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905w-p281.dtb + dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905w-tx3-mini.dtb ++dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905w-x96-mini.dtb ++dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905w-x96w.dtb ++dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905x-b860h.dtb + dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905x-hwacom-amazetv.dtb + dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905x-khadas-vim.dtb + dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905x-libretech-cc-v2.dtb + dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905x-libretech-cc.dtb + dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905x-nexbox-a95x.dtb + dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905x-p212.dtb ++dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905x-tbee.dtb ++dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905x-vero4k.dtb ++dtb-$(CONFIG_ARCH_MESON) += meson-gxm-fake-octopus-planet.dtb ++dtb-$(CONFIG_ARCH_MESON) += meson-gxm-gt1.dtb + dtb-$(CONFIG_ARCH_MESON) += meson-gxm-gt1-ultimate.dtb + dtb-$(CONFIG_ARCH_MESON) += meson-gxm-khadas-vim2.dtb + dtb-$(CONFIG_ARCH_MESON) += meson-gxm-mecool-kiii-pro.dtb + dtb-$(CONFIG_ARCH_MESON) += meson-gxm-minix-neo-u9h.dtb + dtb-$(CONFIG_ARCH_MESON) += meson-gxm-nexbox-a1.dtb ++dtb-$(CONFIG_ARCH_MESON) += meson-gxm-nexbox-a2.dtb ++dtb-$(CONFIG_ARCH_MESON) += meson-gxm-octopus-planet.dtb ++dtb-$(CONFIG_ARCH_MESON) += meson-gxm-phicomm-t1.dtb + dtb-$(CONFIG_ARCH_MESON) += meson-gxm-q200.dtb + dtb-$(CONFIG_ARCH_MESON) += meson-gxm-q201.dtb + dtb-$(CONFIG_ARCH_MESON) += meson-gxm-rbox-pro.dtb + dtb-$(CONFIG_ARCH_MESON) += meson-gxm-s912-libretech-pc.dtb ++dtb-$(CONFIG_ARCH_MESON) += meson-gxm-t95z-plus.dtb ++dtb-$(CONFIG_ARCH_MESON) += meson-gxm-tx8-max.dtb ++dtb-$(CONFIG_ARCH_MESON) += meson-gxm-tx9-pro.dtb + dtb-$(CONFIG_ARCH_MESON) += meson-gxm-vega-s96.dtb + dtb-$(CONFIG_ARCH_MESON) += meson-gxm-wetek-core2.dtb ++dtb-$(CONFIG_ARCH_MESON) += meson-gxm-x92.dtb + dtb-$(CONFIG_ARCH_MESON) += meson-s4-s805x2-aq222.dtb + dtb-$(CONFIG_ARCH_MESON) += meson-sm1-a95xf3-air-gbit.dtb + dtb-$(CONFIG_ARCH_MESON) += meson-sm1-a95xf3-air.dtb + dtb-$(CONFIG_ARCH_MESON) += meson-sm1-bananapi-m5.dtb + dtb-$(CONFIG_ARCH_MESON) += meson-sm1-h96-max.dtb ++dtb-$(CONFIG_ARCH_MESON) += meson-sm1-h96-max-x3.dtb ++dtb-$(CONFIG_ARCH_MESON) += meson-sm1-h96-max-x3-oc.dtb ++dtb-$(CONFIG_ARCH_MESON) += meson-sm1-hk1box-vontar-x3.dtb ++dtb-$(CONFIG_ARCH_MESON) += meson-sm1-hk1box-vontar-x3-oc.dtb + dtb-$(CONFIG_ARCH_MESON) += meson-sm1-khadas-vim3l.dtb + dtb-$(CONFIG_ARCH_MESON) += meson-sm1-odroid-c4.dtb + dtb-$(CONFIG_ARCH_MESON) += meson-sm1-odroid-hc4.dtb + dtb-$(CONFIG_ARCH_MESON) += meson-sm1-sei610.dtb ++dtb-$(CONFIG_ARCH_MESON) += meson-sm1-skyworth-lb2004-a4091.dtb ++dtb-$(CONFIG_ARCH_MESON) += meson-sm1-tx3-bz.dtb ++dtb-$(CONFIG_ARCH_MESON) += meson-sm1-tx3-bz-oc.dtb ++dtb-$(CONFIG_ARCH_MESON) += meson-sm1-tx3-qz.dtb ++dtb-$(CONFIG_ARCH_MESON) += meson-sm1-tx3-qz-oc.dtb ++dtb-$(CONFIG_ARCH_MESON) += meson-sm1-ugoos-x3.dtb ++dtb-$(CONFIG_ARCH_MESON) += meson-sm1-ugoos-x3-oc.dtb + dtb-$(CONFIG_ARCH_MESON) += meson-sm1-x96-air-gbit.dtb + dtb-$(CONFIG_ARCH_MESON) += meson-sm1-x96-air.dtb ++dtb-$(CONFIG_ARCH_MESON) += meson-sm1-x96-max-plus-100m.dtb ++dtb-$(CONFIG_ARCH_MESON) += meson-sm1-x96-max-plus.dtb ++dtb-$(CONFIG_ARCH_MESON) += meson-sm1-x96-max-plus-ip1001m-2.dtb ++dtb-$(CONFIG_ARCH_MESON) += meson-sm1-x96-max-plus-ip1001m.dtb ++dtb-$(CONFIG_ARCH_MESON) += meson-sm1-x96-max-plus-oc.dtb ++dtb-$(CONFIG_ARCH_MESON) += meson-sm1-x96-max-plus-q1.dtb ++dtb-$(CONFIG_ARCH_MESON) += meson-sm1-x96-max-plus-q2.dtb ++dtb-$(CONFIG_ARCH_MESON) += meson-sm1-x96-max-plus-2101.dtb ++ ++subdir-y := $(dts-dirs) overlay +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-axg.dtsi mod/arch/arm64/boot/dts/amlogic/meson-axg.dtsi +--- main/arch/arm64/boot/dts/amlogic/meson-axg.dtsi 2023-03-07 09:42:01.949536609 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-axg.dtsi 2023-03-07 09:42:03.357547528 +0100 +@@ -1885,7 +1885,7 @@ + sd_emmc_b: sd@5000 { + compatible = "amlogic,meson-axg-mmc"; + reg = <0x0 0x5000 0x0 0x800>; +- interrupts = ; ++ interrupts = ; + status = "disabled"; + clocks = <&clkc CLKID_SD_EMMC_B>, + <&clkc CLKID_SD_EMMC_B_CLK0>, +@@ -1897,7 +1897,7 @@ + sd_emmc_c: mmc@7000 { + compatible = "amlogic,meson-axg-mmc"; + reg = <0x0 0x7000 0x0 0x800>; +- interrupts = ; ++ interrupts = ; + status = "disabled"; + clocks = <&clkc CLKID_SD_EMMC_C>, + <&clkc CLKID_SD_EMMC_C_CLK0>, +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-g12a.dtsi mod/arch/arm64/boot/dts/amlogic/meson-g12a.dtsi +--- main/arch/arm64/boot/dts/amlogic/meson-g12a.dtsi 2023-03-07 09:42:02.021537166 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-g12a.dtsi 2023-03-07 09:42:03.477548460 +0100 +@@ -57,26 +57,6 @@ + compatible = "operating-points-v2"; + opp-shared; + +- opp-100000000 { +- opp-hz = /bits/ 64 <100000000>; +- opp-microvolt = <731000>; +- }; +- +- opp-250000000 { +- opp-hz = /bits/ 64 <250000000>; +- opp-microvolt = <731000>; +- }; +- +- opp-500000000 { +- opp-hz = /bits/ 64 <500000000>; +- opp-microvolt = <731000>; +- }; +- +- opp-667000000 { +- opp-hz = /bits/ 64 <666666666>; +- opp-microvolt = <731000>; +- }; +- + opp-1000000000 { + opp-hz = /bits/ 64 <1000000000>; + opp-microvolt = <731000>; +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-g12a-radxa-zero.dts mod/arch/arm64/boot/dts/amlogic/meson-g12a-radxa-zero.dts +--- main/arch/arm64/boot/dts/amlogic/meson-g12a-radxa-zero.dts 2023-03-07 09:42:01.981536856 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-g12a-radxa-zero.dts 2023-03-07 09:42:03.381547716 +0100 +@@ -60,6 +60,14 @@ + clock-names = "ext_clock"; + }; + ++ typec2_vbus: regulator-typec2_vbus { ++ compatible = "regulator-fixed"; ++ regulator-name = "TYPEC2_VBUS"; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ vin-supply = <&ao_5v>; ++ }; ++ + ao_5v: regulator-ao_5v { + compatible = "regulator-fixed"; + regulator-name = "AO_5V"; +@@ -191,6 +199,18 @@ + }; + }; + ++&ao_pinctrl { ++ /* Ensure the TYPE C controller irq pin is not driven by the SoC */ ++ fusb302_irq_pins: fusb302_irq { ++ mux { ++ groups = "GPIOAO_5"; ++ function = "gpio_aobus"; ++ bias-pull-up; ++ output-disable; ++ }; ++ }; ++}; ++ + &arb { + status = "okay"; + }; +@@ -278,6 +298,22 @@ + pinctrl-names = "default"; + }; + ++&i2c_AO { ++ fusb302@22 { ++ compatible = "fcs,fusb302"; ++ reg = <0x22>; ++ ++ pinctrl-0 = <&fusb302_irq_pins>; ++ pinctrl-names = "default"; ++ interrupt-parent = <&gpio_intc>; ++ interrupts = <59 IRQ_TYPE_LEVEL_LOW>; ++ ++ vbus-supply = <&typec2_vbus>; ++ ++ status = "okay"; ++ }; ++}; ++ + &pwm_AO_cd { + pinctrl-0 = <&pwm_ao_d_e_pins>; + pinctrl-names = "default"; +@@ -403,3 +439,11 @@ + status = "okay"; + dr_mode = "host"; + }; ++ ++&usb2_phy0 { ++ phy-supply = <&typec2_vbus>; ++}; ++ ++&usb3_pcie_phy { ++ phy-supply = <&typec2_vbus>; ++}; +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-g12a-s905l3a-cm311.dts mod/arch/arm64/boot/dts/amlogic/meson-g12a-s905l3a-cm311.dts +--- main/arch/arm64/boot/dts/amlogic/meson-g12a-s905l3a-cm311.dts 1970-01-01 01:00:00.000000000 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-g12a-s905l3a-cm311.dts 2023-03-07 09:42:03.393547808 +0100 +@@ -0,0 +1,173 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++/* ++ * Copyright (c) 2018 Amlogic, Inc. All rights reserved. ++ * Create by flippy ++ */ ++ ++/dts-v1/; ++ ++#include "meson-g12a-u200.dts" ++ ++/ { ++ compatible = "cm311,m401a,e900v22c", "amlogic,g12a"; ++ model = "CM311-1a-YST"; ++ ++ aliases { ++ serial1 = &uart_A; ++ }; ++ ++ vddgpu: regulator-vddgpu { ++ compatible = "regulator-fixed"; ++ regulator-name = "mali"; ++ regulator-min-microvolt = <800000>; ++ regulator-max-microvolt = <800000>; ++ vin-supply = <&main_12v>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ wifi32k: wifi32k { ++ compatible = "pwm-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <32768>; ++ pwms = <&pwm_ef 0 30518 0>; /* PWM_E at 32.768KHz */ ++ }; ++ ++ sdio_pwrseq: sdio-pwrseq { ++ compatible = "mmc-pwrseq-simple"; ++ reset-gpios = <&gpio GPIOX_6 GPIO_ACTIVE_LOW>; ++ clocks = <&wifi32k>; ++ clock-names = "ext_clock"; ++ }; ++ ++ leds { ++ compatible = "gpio-leds"; ++ ++ power_led { ++ led_name = "power_led"; ++ gpios = <&gpio_ao GPIOAO_11 GPIO_ACTIVE_LOW>; ++ default-state = "on"; ++ }; ++ ++ net_led { ++ led_name = "net_led"; ++ gpios = <&gpio_ao GPIOAO_9 GPIO_ACTIVE_LOW>; ++ default-state = "off"; ++ linux,default-trigger = "0.0:00:link"; ++ }; ++ ++ remote_led { ++ led_name = "remote_led"; ++ gpios = <&gpio_ao GPIOAO_10 GPIO_ACTIVE_LOW>; ++ default-state = "off"; ++ linux,default-trigger = "rc-feedback"; ++ }; ++ }; ++ ++ memory@0 { ++ device_type = "memory"; ++ reg = <0x0 0x0 0x0 0x80000000>; ++ }; ++}; ++ ++&uart_A { ++ status = "okay"; ++ pinctrl-0 = <&uart_a_pins>, <&uart_a_cts_rts_pins>; ++ uart-has-rtscts; ++ pinctrl-names = "default"; ++}; ++ ++&mali { ++ mali-supply=<&vddgpu>; ++}; ++ ++/* SDIO */ ++&sd_emmc_a { ++ status = "okay"; ++ pinctrl-0 = <&sdio_pins>; ++ pinctrl-1 = <&sdio_clk_gate_pins>; ++ pinctrl-names = "default", "clk-gate"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ bus-width = <4>; ++ cap-sd-highspeed; ++ sd-uhs-sdr50; ++ max-frequency = <100000000>; ++ ++ non-removable; ++ disable-wp; ++ ++ /* WiFi firmware requires power to be kept while in suspend */ ++ keep-power-in-suspend; ++ ++ mmc-pwrseq = <&sdio_pwrseq>; ++ ++ vmmc-supply = <&vddao_3v3>; ++ vqmmc-supply = <&vddao_1v8>; ++ ++ wifi: wifi@1 { ++ reg = <1>; ++ compatible = "sprd,unisoc-wifi"; ++ }; ++}; ++ ++/* SD card */ ++&sd_emmc_b { ++ status = "okay"; ++ bus-width = <4>; ++ cap-sd-highspeed; ++ max-frequency = <50000000>; ++}; ++ ++/* eMMC */ ++&sd_emmc_c { ++ status = "okay"; ++ bus-width = <8>; ++ cap-mmc-highspeed; ++ mmc-ddr-1_8v; ++ mmc-hs200-1_8v; ++ max-frequency = <200000000>; ++}; ++ ++/* CPU Overclock */ ++&cpu_opp_table { ++ opp-100000000 { ++ status = "disabled"; ++ }; ++ ++ opp-250000000 { ++ status = "disabled"; ++ }; ++ ++ opp-500000000 { ++ status = "disabled"; ++ }; ++ ++ opp-667000000 { ++ status = "disabled"; ++ }; ++ ++ opp-1908000000 { ++ opp-hz = /bits/ 64 <1908000000>; ++ opp-microvolt = <1001000>; ++ }; ++ ++ /* 2016mhz : not test */ ++ //opp-2016000000 { ++ // opp-hz = /bits/ 64 <2016000000>; ++ // opp-microvolt = <1021000>; ++ //}; ++}; ++ ++&internal_ephy { ++ max-speed = <100>; ++}; ++ ++ðmac { ++ /delete-property/ resets; ++ /delete-property/ reset-names; ++ phy-handle = <&internal_ephy>; ++ phy-mode = "rmii"; ++ status = "okay"; ++}; +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-g12a-s905l3a-e900v22c.dts mod/arch/arm64/boot/dts/amlogic/meson-g12a-s905l3a-e900v22c.dts +--- main/arch/arm64/boot/dts/amlogic/meson-g12a-s905l3a-e900v22c.dts 1970-01-01 01:00:00.000000000 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-g12a-s905l3a-e900v22c.dts 2023-03-07 09:42:03.405547902 +0100 +@@ -0,0 +1,159 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++/* ++ * Copyright (c) 2018 Amlogic, Inc. All rights reserved. ++ * Create by flippy ++ */ ++ ++/dts-v1/; ++ ++#include "meson-g12a-u200.dts" ++ ++/ { ++ compatible = "skyworth,e900v22c", "amlogic,g12a"; ++ model = "SKYWORTH E900V22C"; ++ ++ vddgpu: regulator-vddgpu { ++ compatible = "regulator-fixed"; ++ regulator-name = "mali"; ++ regulator-min-microvolt = <800000>; ++ regulator-max-microvolt = <800000>; ++ vin-supply = <&main_12v>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ wifi32k: wifi32k { ++ compatible = "pwm-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <32768>; ++ pwms = <&pwm_ef 0 30518 0>; /* PWM_E at 32.768KHz */ ++ }; ++ ++ sdio_pwrseq: sdio-pwrseq { ++ compatible = "mmc-pwrseq-simple"; ++ reset-gpios = <&gpio GPIOX_6 GPIO_ACTIVE_LOW>; ++ clocks = <&wifi32k>; ++ clock-names = "ext_clock"; ++ }; ++ ++ leds { ++ compatible = "gpio-leds"; ++ ++ power_led { ++ led_name = "power_led"; ++ gpios = <&gpio_ao GPIOAO_11 GPIO_ACTIVE_LOW>; ++ default-state = "on"; ++ }; ++ ++ net_led { ++ led_name = "net_led"; ++ gpios = <&gpio_ao GPIOAO_9 GPIO_ACTIVE_LOW>; ++ default-state = "off"; ++ linux,default-trigger = "0.0:00:link"; ++ }; ++ ++ remote_led { ++ led_name = "remote_led"; ++ gpios = <&gpio_ao GPIOAO_10 GPIO_ACTIVE_LOW>; ++ default-state = "off"; ++ linux,default-trigger = "rc-feedback"; ++ }; ++ ++ }; ++ ++ memory@0 { ++ device_type = "memory"; ++ reg = <0x0 0x0 0x0 0x80000000>; ++ }; ++}; ++ ++&mali { ++ mali-supply=<&vddgpu>; ++}; ++ ++/* SDIO */ ++&sd_emmc_a { ++ status = "okay"; ++ pinctrl-0 = <&sdio_pins>; ++ pinctrl-1 = <&sdio_clk_gate_pins>; ++ pinctrl-names = "default", "clk-gate"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ bus-width = <4>; ++ cap-sd-highspeed; ++ sd-uhs-sdr50; ++ max-frequency = <100000000>; ++ ++ non-removable; ++ disable-wp; ++ ++ /* WiFi firmware requires power to be kept while in suspend */ ++ keep-power-in-suspend; ++ ++ mmc-pwrseq = <&sdio_pwrseq>; ++ ++ vmmc-supply = <&vddao_3v3>; ++ vqmmc-supply = <&vddao_1v8>; ++ ++ //wifi: wifi@1 { ++ // reg = <1>; ++ // compatible = "unisoc,uwe5622"; ++ //}; ++}; ++ ++/* SD card */ ++&sd_emmc_b { ++ status = "okay"; ++ bus-width = <4>; ++ cap-sd-highspeed; ++ max-frequency = <50000000>; ++}; ++ ++/* eMMC */ ++&sd_emmc_c { ++ status = "okay"; ++ bus-width = <8>; ++ cap-mmc-highspeed; ++ mmc-ddr-1_8v; ++ mmc-hs200-1_8v; ++ max-frequency = <200000000>; ++}; ++ ++/* CPU Overclock */ ++&cpu_opp_table { ++ opp-100000000 { ++ status = "disabled"; ++ }; ++ ++ opp-250000000 { ++ status = "disabled"; ++ }; ++ ++ opp-500000000 { ++ status = "disabled"; ++ }; ++ ++ opp-667000000 { ++ status = "disabled"; ++ }; ++ ++ opp-1908000000 { ++ opp-hz = /bits/ 64 <1908000000>; ++ opp-microvolt = <1001000>; ++ }; ++ ++ /* 2016mhz : not test */ ++ //opp-2016000000 { ++ // opp-hz = /bits/ 64 <2016000000>; ++ // opp-microvolt = <1021000>; ++ //}; ++}; ++ ++ðmac { ++ /delete-property/ resets; ++ /delete-property/ reset-names; ++ phy-handle = <&internal_ephy>; ++ phy-mode = "rmii"; ++ status = "okay"; ++}; +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-g12a-s905l3a-m401a.dts mod/arch/arm64/boot/dts/amlogic/meson-g12a-s905l3a-m401a.dts +--- main/arch/arm64/boot/dts/amlogic/meson-g12a-s905l3a-m401a.dts 1970-01-01 01:00:00.000000000 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-g12a-s905l3a-m401a.dts 2023-03-07 09:42:03.417547994 +0100 +@@ -0,0 +1,165 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++/* ++ * Copyright (c) 2018 Amlogic, Inc. All rights reserved. ++ * Create by janko888 2022/11/27 ++ */ ++ ++/dts-v1/; ++ ++#include "meson-g12a-u200.dts" ++ ++/ { ++ compatible = "m401a", "amlogic,g12a"; ++ model = "M401A"; ++ ++ aliases { ++ serial1 = &uart_A; ++ }; ++ ++ vddgpu: regulator-vddgpu { ++ compatible = "regulator-fixed"; ++ regulator-name = "mali"; ++ regulator-min-microvolt = <800000>; ++ regulator-max-microvolt = <800000>; ++ vin-supply = <&main_12v>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ leds { ++ compatible = "gpio-leds"; ++ ++ power_led { ++ led_name = "power_led"; ++ gpios = <&gpio_ao GPIOAO_11 GPIO_ACTIVE_LOW>; ++ default-state = "on"; ++ }; ++ ++ net_led { ++ led_name = "net_led"; ++ gpios = <&gpio_ao GPIOAO_9 GPIO_ACTIVE_LOW>; ++ default-state = "off"; ++ linux,default-trigger = "0.0:00:link"; ++ }; ++ ++ remote_led { ++ led_name = "remote_led"; ++ gpios = <&gpio_ao GPIOAO_10 GPIO_ACTIVE_LOW>; ++ default-state = "off"; ++ linux,default-trigger = "rc-feedback"; ++ }; ++ }; ++ ++ memory@0 { ++ device_type = "memory"; ++ reg = <0x0 0x0 0x0 0x80000000>; ++ }; ++}; ++ ++&uart_A { ++ status = "okay"; ++ pinctrl-0 = <&uart_a_pins>, <&uart_a_cts_rts_pins>; ++ uart-has-rtscts; ++ pinctrl-names = "default"; ++}; ++ ++&mali { ++ mali-supply=<&vddgpu>; ++}; ++ ++/* SD card */ ++/* No SD card in M401A */ ++&sd_emmc_b { ++ status = "disabled"; ++ bus-width = <4>; ++ cap-sd-highspeed; ++ max-frequency = <50000000>; ++}; ++ ++/* eMMC */ ++&sd_emmc_c { ++ status = "okay"; ++ bus-width = <8>; ++ cap-mmc-highspeed; ++ mmc-ddr-1_8v; ++ mmc-hs200-1_8v; ++ max-frequency = <100000000>; ++}; ++ ++/* CPU Overclock */ ++&cpu_opp_table { ++ opp-100000000 { ++ opp-hz = /bits/ 64 <100000000>; ++ opp-microvolt = <731000>; ++ }; ++ ++ opp-250000000 { ++ opp-hz = /bits/ 64 <250000000>; ++ opp-microvolt = <731000>; ++ }; ++ ++ opp-500000000 { ++ opp-hz = /bits/ 64 <500000000>; ++ opp-microvolt = <731000>; ++ }; ++ ++ opp-667000000 { ++ opp-hz = /bits/ 64 <667000000>; ++ opp-microvolt = <731000>; ++ }; ++ ++ opp-1000000000 { ++ opp-hz = /bits/ 64 <1000000000>; ++ opp-microvolt = <731000>; ++ }; ++ ++ opp-1200000000 { ++ opp-hz = /bits/ 64 <1200000000>; ++ //opp-microvolt = <731000>; ++ opp-microvolt = <761000>; ++ }; ++ ++ opp-1398000000 { ++ opp-hz = /bits/ 64 <1398000000>; ++ //opp-microvolt = <761000>; ++ opp-microvolt = <791000>; ++ }; ++ ++ opp-1512000000 { ++ opp-hz = /bits/ 64 <1512000000>; ++ //opp-microvolt = <791000>; ++ opp-microvolt = <831000>; ++ }; ++ ++ opp-1608000000 { ++ opp-hz = /bits/ 64 <1608000000>; ++ //opp-microvolt = <831000>; ++ opp-microvolt = <871000>; ++ }; ++ ++ opp-1704000000 { ++ opp-hz = /bits/ 64 <1704000000>; ++ //opp-microvolt = <861000>; ++ opp-microvolt = <921000>; ++ }; ++ ++ /* some soc has crash under 1800 */ ++ opp-1800000000 { ++ opp-hz = /bits/ 64 <1800000000>; ++ opp-microvolt = <981000>; ++ status = "disabled"; ++ }; ++ ++}; ++ ++&internal_ephy { ++ max-speed = <100>; ++}; ++ ++ðmac { ++ /delete-property/ resets; ++ /delete-property/ reset-names; ++ phy-handle = <&internal_ephy>; ++ phy-mode = "rmii"; ++ status = "okay"; ++}; +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-g12a-tanix-tx5max.dts mod/arch/arm64/boot/dts/amlogic/meson-g12a-tanix-tx5max.dts +--- main/arch/arm64/boot/dts/amlogic/meson-g12a-tanix-tx5max.dts 1970-01-01 01:00:00.000000000 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-g12a-tanix-tx5max.dts 2023-03-07 09:42:03.437548150 +0100 +@@ -0,0 +1,481 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++/* ++ * Copyright (c) 2018 BayLibre SAS. All rights reserved. ++ */ ++ ++/dts-v1/; ++ ++#include "meson-g12a.dtsi" ++#include ++#include ++#include ++ ++/ { ++ compatible = "oranth,tx5-max", "amlogic,g12a"; ++ model = "Tanix TX5 Max"; ++ ++ aliases { ++ serial0 = &uart_AO; ++ ethernet0 = ðmac; ++ }; ++ ++ spdif_dit: audio-codec-1 { ++ #sound-dai-cells = <0>; ++ compatible = "linux,spdif-dit"; ++ status = "okay"; ++ sound-name-prefix = "DIT"; ++ }; ++ ++ chosen { ++ stdout-path = "serial0:115200n8"; ++ }; ++ memory@0 { ++ device_type = "memory"; ++ reg = <0x0 0x0 0x0 0x40000000>; ++ }; ++ ++ cvbs-connector { ++ compatible = "composite-video-connector"; ++ ++ port { ++ cvbs_connector_in: endpoint { ++ remote-endpoint = <&cvbs_vdac_out>; ++ }; ++ }; ++ }; ++ ++ hdmi-connector { ++ compatible = "hdmi-connector"; ++ type = "a"; ++ ++ port { ++ hdmi_connector_in: endpoint { ++ remote-endpoint = <&hdmi_tx_tmds_out>; ++ }; ++ }; ++ }; ++ ++ emmc_pwrseq: emmc-pwrseq { ++ compatible = "mmc-pwrseq-emmc"; ++ reset-gpios = <&gpio BOOT_12 GPIO_ACTIVE_LOW>; ++ }; ++ ++ sdio_pwrseq: sdio-pwrseq { ++ compatible = "mmc-pwrseq-simple"; ++ reset-gpios = <&gpio GPIOX_6 GPIO_ACTIVE_LOW>; ++ clocks = <&wifi32k>; ++ clock-names = "ext_clock"; ++ }; ++ ++ flash_1v8: regulator-flash_1v8 { ++ compatible = "regulator-fixed"; ++ regulator-name = "FLASH_1V8"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ vin-supply = <&vcc_3v3>; ++ regulator-always-on; ++ }; ++ ++ dc_in: regulator-dc_in { ++ compatible = "regulator-fixed"; ++ regulator-name = "DC_IN"; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ regulator-always-on; ++ }; ++ ++ vcc_1v8: regulator-vcc_1v8 { ++ compatible = "regulator-fixed"; ++ regulator-name = "VCC_1V8"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ vin-supply = <&vcc_3v3>; ++ regulator-always-on; ++ }; ++ ++ vcc_3v3: regulator-vcc_3v3 { ++ compatible = "regulator-fixed"; ++ regulator-name = "VCC_3V3"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ vin-supply = <&vddao_3v3>; ++ regulator-always-on; ++ /* FIXME: actually controlled by VDDCPU_B_EN */ ++ }; ++ ++ vcc_5v: regulator-vcc_5v { ++ compatible = "regulator-fixed"; ++ regulator-name = "VCC_5V"; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ vin-supply = <&dc_in>; ++ ++ gpio = <&gpio GPIOH_8 GPIO_OPEN_DRAIN>; ++ enable-active-low; ++ }; ++ ++ vddao_1v8: regulator-vddao_1v8 { ++ compatible = "regulator-fixed"; ++ regulator-name = "VDDAO_1V8"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ vin-supply = <&vddao_3v3>; ++ regulator-always-on; ++ }; ++ ++ vddao_3v3: regulator-vddao_3v3 { ++ compatible = "regulator-fixed"; ++ regulator-name = "VDDAO_3V3"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ vin-supply = <&dc_in>; ++ regulator-always-on; ++ }; ++ ++ vddcpu: regulator-vddcpu { ++ compatible = "pwm-regulator"; ++ ++ regulator-name = "VDDCPU"; ++ regulator-min-microvolt = <721000>; ++ regulator-max-microvolt = <1022000>; ++ ++ vin-supply = <&dc_in>; ++ ++ pwms = <&pwm_AO_cd 1 1250 0>; ++ pwm-dutycycle-range = <100 0>; ++ ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ wifi32k: wifi32k { ++ compatible = "pwm-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <32768>; ++ pwms = <&pwm_ef 0 30518 0>; /* PWM_E at 32.768KHz */ ++ }; ++ ++ sound { ++ compatible = "amlogic,axg-sound-card"; ++ model = "TANIX-TX5MAX"; ++ audio-aux-devs = <&tdmout_b>; ++ audio-routing = "TDMOUT_B IN 0", "FRDDR_A OUT 1", ++ "TDMOUT_B IN 1", "FRDDR_B OUT 1", ++ "TDMOUT_B IN 2", "FRDDR_C OUT 1", ++ "TDM_B Playback", "TDMOUT_B OUT", ++ "SPDIFOUT IN 0", "FRDDR_A OUT 3", ++ "SPDIFOUT IN 1", "FRDDR_B OUT 3", ++ "SPDIFOUT IN 2", "FRDDR_C OUT 3"; ++ ++ assigned-clocks = <&clkc CLKID_MPLL2>, ++ <&clkc CLKID_MPLL0>, ++ <&clkc CLKID_MPLL1>; ++ assigned-clock-parents = <0>, <0>, <0>; ++ assigned-clock-rates = <294912000>, ++ <270950400>, ++ <393216000>; ++ status = "okay"; ++ ++ dai-link-0 { ++ sound-dai = <&frddr_a>; ++ }; ++ ++ dai-link-1 { ++ sound-dai = <&frddr_b>; ++ }; ++ ++ dai-link-2 { ++ sound-dai = <&frddr_c>; ++ }; ++ ++ /* 8ch hdmi interface */ ++ dai-link-3 { ++ sound-dai = <&tdmif_b>; ++ dai-format = "i2s"; ++ dai-tdm-slot-tx-mask-0 = <1 1>; ++ dai-tdm-slot-tx-mask-1 = <1 1>; ++ dai-tdm-slot-tx-mask-2 = <1 1>; ++ dai-tdm-slot-tx-mask-3 = <1 1>; ++ mclk-fs = <256>; ++ ++ codec { ++ sound-dai = <&tohdmitx TOHDMITX_I2S_IN_B>; ++ }; ++ }; ++ ++ /* spdif hdmi or toslink interface */ ++ dai-link-4 { ++ sound-dai = <&spdifout>; ++ ++ codec-0 { ++ sound-dai = <&spdif_dit>; ++ }; ++ ++ codec-1 { ++ sound-dai = <&tohdmitx TOHDMITX_SPDIF_IN_A>; ++ }; ++ }; ++ ++ /* spdif hdmi interface */ ++ dai-link-5 { ++ sound-dai = <&spdifout_b>; ++ ++ codec { ++ sound-dai = <&tohdmitx TOHDMITX_SPDIF_IN_B>; ++ }; ++ }; ++ ++ /* hdmi glue */ ++ dai-link-6 { ++ sound-dai = <&tohdmitx TOHDMITX_I2S_OUT>; ++ ++ codec { ++ sound-dai = <&hdmi_tx>; ++ }; ++ }; ++ }; ++}; ++ ++&arb { ++ status = "okay"; ++}; ++ ++&cec_AO { ++ pinctrl-0 = <&cec_ao_a_h_pins>; ++ pinctrl-names = "default"; ++ status = "disabled"; ++ hdmi-phandle = <&hdmi_tx>; ++}; ++ ++&cecb_AO { ++ pinctrl-0 = <&cec_ao_b_h_pins>; ++ pinctrl-names = "default"; ++ status = "okay"; ++ hdmi-phandle = <&hdmi_tx>; ++}; ++ ++&clkc_audio { ++ status = "okay"; ++}; ++ ++&cpu0 { ++ cpu-supply = <&vddcpu>; ++ operating-points-v2 = <&cpu_opp_table>; ++ clocks = <&clkc CLKID_CPU_CLK>; ++ clock-latency = <50000>; ++}; ++ ++&cpu1 { ++ cpu-supply = <&vddcpu>; ++ operating-points-v2 = <&cpu_opp_table>; ++ clocks = <&clkc CLKID_CPU_CLK>; ++ clock-latency = <50000>; ++}; ++ ++&cpu2 { ++ cpu-supply = <&vddcpu>; ++ operating-points-v2 = <&cpu_opp_table>; ++ clocks = <&clkc CLKID_CPU_CLK>; ++ clock-latency = <50000>; ++}; ++ ++&cpu3 { ++ cpu-supply = <&vddcpu>; ++ operating-points-v2 = <&cpu_opp_table>; ++ clocks = <&clkc CLKID_CPU_CLK>; ++ clock-latency = <50000>; ++}; ++ ++&cvbs_vdac_port { ++ cvbs_vdac_out: endpoint { ++ remote-endpoint = <&cvbs_connector_in>; ++ }; ++}; ++ ++&frddr_a { ++ status = "okay"; ++}; ++ ++&frddr_b { ++ status = "okay"; ++}; ++ ++&frddr_c { ++ status = "okay"; ++}; ++ ++&hdmi_tx { ++ status = "okay"; ++ pinctrl-0 = <&hdmitx_hpd_pins>, <&hdmitx_ddc_pins>; ++ pinctrl-names = "default"; ++ hdmi-supply = <&vcc_5v>; ++}; ++ ++&hdmi_tx_tmds_port { ++ hdmi_tx_tmds_out: endpoint { ++ remote-endpoint = <&hdmi_connector_in>; ++ }; ++}; ++ ++&ir { ++ status = "okay"; ++ pinctrl-0 = <&remote_input_ao_pins>; ++ pinctrl-names = "default"; ++ linux,rc-map-name = "rc-tx5max"; ++}; ++ ++&pwm_AO_cd { ++ pinctrl-0 = <&pwm_ao_d_e_pins>; ++ pinctrl-names = "default"; ++ clocks = <&xtal>; ++ clock-names = "clkin1"; ++ status = "okay"; ++}; ++ ++&ext_mdio { ++ external_phy: ethernet-phy@0 { ++ /* Realtek RTL8211F (0x001cc916) */ ++ reg = <0>; ++ max-speed = <1000>; ++ eee-broken-1000t; ++ ++ reset-assert-us = <10000>; ++ reset-deassert-us = <80000>; ++ reset-gpios = <&gpio GPIOZ_15 (GPIO_ACTIVE_LOW | GPIO_OPEN_DRAIN)>; ++ ++ interrupt-parent = <&gpio_intc>; ++ /* MAC_INTR on GPIOZ_14 */ ++ interrupts = <26 IRQ_TYPE_LEVEL_LOW>; ++ }; ++}; ++ ++ðmac { ++ pinctrl-0 = <ð_pins>, <ð_rgmii_pins>; ++ pinctrl-names = "default"; ++ status = "okay"; ++ phy-mode = "rgmii"; ++ phy-handle = <&external_phy>; ++ amlogic,tx-delay-ns = <2>; ++}; ++ ++&pwm_ef { ++ status = "okay"; ++ pinctrl-0 = <&pwm_e_pins>; ++ pinctrl-names = "default"; ++ clocks = <&xtal>; ++ clock-names = "clkin0"; ++}; ++ ++&uart_A { ++ status = "okay"; ++ pinctrl-0 = <&uart_a_pins>, <&uart_a_cts_rts_pins>; ++ pinctrl-names = "default"; ++ uart-has-rtscts; ++ ++ bluetooth { ++ compatible = "brcm,bcm43438-bt"; ++ shutdown-gpios = <&gpio GPIOX_17 GPIO_ACTIVE_HIGH>; ++ max-speed = <2000000>; ++ clocks = <&wifi32k>; ++ clock-names = "lpo"; ++ }; ++}; ++ ++&uart_AO { ++ status = "okay"; ++ pinctrl-0 = <&uart_ao_a_pins>; ++ pinctrl-names = "default"; ++}; ++ ++&usb { ++ status = "okay"; ++ dr_mode = "host"; ++}; ++ ++/* SDIO */ ++&sd_emmc_a { ++ status = "okay"; ++ pinctrl-0 = <&sdio_pins>; ++ pinctrl-1 = <&sdio_clk_gate_pins>; ++ pinctrl-names = "default", "clk-gate"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ bus-width = <4>; ++ cap-sd-highspeed; ++ sd-uhs-sdr50; ++ max-frequency = <100000000>; ++ ++ non-removable; ++ disable-wp; ++ ++ /* WiFi firmware requires power to be kept while in suspend */ ++ keep-power-in-suspend; ++ ++ mmc-pwrseq = <&sdio_pwrseq>; ++ ++ vmmc-supply = <&vddao_3v3>; ++ vqmmc-supply = <&vddao_1v8>; ++ ++ brcmf: wifi@1 { ++ reg = <1>; ++ compatible = "brcm,bcm4329-fmac"; ++ }; ++}; ++ ++/* SD card */ ++&sd_emmc_b { ++ status = "okay"; ++ pinctrl-0 = <&sdcard_c_pins>; ++ pinctrl-1 = <&sdcard_clk_gate_c_pins>; ++ pinctrl-names = "default", "clk-gate"; ++ ++ bus-width = <4>; ++ cap-sd-highspeed; ++ max-frequency = <100000000>; ++ disable-wp; ++ ++ cd-gpios = <&gpio GPIOC_6 GPIO_ACTIVE_LOW>; ++ vmmc-supply = <&vddao_3v3>; ++ vqmmc-supply = <&vddao_3v3>; ++}; ++ ++/* eMMC */ ++&sd_emmc_c { ++ status = "okay"; ++ pinctrl-0 = <&emmc_ctrl_pins>, <&emmc_data_8b_pins>, <&emmc_ds_pins>; ++ pinctrl-1 = <&emmc_clk_gate_pins>; ++ pinctrl-names = "default", "clk-gate"; ++ ++ bus-width = <8>; ++ cap-mmc-highspeed; ++ max-frequency = <100000000>; ++ non-removable; ++ disable-wp; ++ ++ mmc-pwrseq = <&emmc_pwrseq>; ++ vmmc-supply = <&vcc_3v3>; ++ vqmmc-supply = <&flash_1v8>; ++}; ++ ++&spdifout { ++ pinctrl-0 = <&spdif_out_h_pins>; ++ pinctrl-names = "default"; ++ status = "okay"; ++}; ++ ++&spdifout_b { ++ status = "okay"; ++}; ++ ++&tdmif_b { ++ status = "okay"; ++}; ++ ++&tdmout_b { ++ status = "okay"; ++}; ++ ++&tohdmitx { ++ status = "okay"; ++}; +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-g12a-u200.dts mod/arch/arm64/boot/dts/amlogic/meson-g12a-u200.dts +--- main/arch/arm64/boot/dts/amlogic/meson-g12a-u200.dts 2023-03-07 09:42:02.001537013 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-g12a-u200.dts 2023-03-07 09:42:03.449548242 +0100 +@@ -8,6 +8,7 @@ + #include "meson-g12a.dtsi" + #include + #include ++#include + + / { + compatible = "amlogic,u200", "amlogic,g12a"; +@@ -18,6 +19,13 @@ + ethernet0 = ðmac; + }; + ++ spdif_dit: audio-codec-1 { ++ #sound-dai-cells = <0>; ++ compatible = "linux,spdif-dit"; ++ status = "okay"; ++ sound-name-prefix = "DIT"; ++ }; ++ + chosen { + stdout-path = "serial0:115200n8"; + }; +@@ -147,6 +155,90 @@ + regulator-boot-on; + regulator-always-on; + }; ++ ++ sound { ++ compatible = "amlogic,axg-sound-card"; ++ model = "U200"; ++ audio-aux-devs = <&tdmout_b>; ++ audio-routing = "TDMOUT_B IN 0", "FRDDR_A OUT 1", ++ "TDMOUT_B IN 1", "FRDDR_B OUT 1", ++ "TDMOUT_B IN 2", "FRDDR_C OUT 1", ++ "TDM_B Playback", "TDMOUT_B OUT", ++ "SPDIFOUT IN 0", "FRDDR_A OUT 3", ++ "SPDIFOUT IN 1", "FRDDR_B OUT 3", ++ "SPDIFOUT IN 2", "FRDDR_C OUT 3"; ++ ++ assigned-clocks = <&clkc CLKID_MPLL2>, ++ <&clkc CLKID_MPLL0>, ++ <&clkc CLKID_MPLL1>; ++ assigned-clock-parents = <0>, <0>, <0>; ++ assigned-clock-rates = <294912000>, ++ <270950400>, ++ <393216000>; ++ status = "okay"; ++ ++ dai-link-0 { ++ sound-dai = <&frddr_a>; ++ }; ++ ++ dai-link-1 { ++ sound-dai = <&frddr_b>; ++ }; ++ ++ dai-link-2 { ++ sound-dai = <&frddr_c>; ++ }; ++ ++ /* 8ch hdmi interface */ ++ dai-link-3 { ++ sound-dai = <&tdmif_b>; ++ dai-format = "i2s"; ++ dai-tdm-slot-tx-mask-0 = <1 1>; ++ dai-tdm-slot-tx-mask-1 = <1 1>; ++ dai-tdm-slot-tx-mask-2 = <1 1>; ++ dai-tdm-slot-tx-mask-3 = <1 1>; ++ mclk-fs = <256>; ++ ++ codec { ++ sound-dai = <&tohdmitx TOHDMITX_I2S_IN_B>; ++ }; ++ }; ++ ++ /* spdif hdmi or toslink interface */ ++ dai-link-4 { ++ sound-dai = <&spdifout>; ++ ++ codec-0 { ++ sound-dai = <&spdif_dit>; ++ }; ++ ++ codec-1 { ++ sound-dai = <&tohdmitx TOHDMITX_SPDIF_IN_A>; ++ }; ++ }; ++ ++ /* spdif hdmi interface */ ++ dai-link-5 { ++ sound-dai = <&spdifout_b>; ++ ++ codec { ++ sound-dai = <&tohdmitx TOHDMITX_SPDIF_IN_B>; ++ }; ++ }; ++ ++ /* hdmi glue */ ++ dai-link-6 { ++ sound-dai = <&tohdmitx TOHDMITX_I2S_OUT>; ++ ++ codec { ++ sound-dai = <&hdmi_tx>; ++ }; ++ }; ++ }; ++}; ++ ++&arb { ++ status = "okay"; + }; + + &cec_AO { +@@ -163,6 +255,10 @@ + hdmi-phandle = <&hdmi_tx>; + }; + ++&clkc_audio { ++ status = "okay"; ++}; ++ + &cpu0 { + cpu-supply = <&vddcpu>; + operating-points-v2 = <&cpu_opp_table>; +@@ -203,6 +299,18 @@ + phy-mode = "rmii"; + }; + ++&frddr_a { ++ status = "okay"; ++}; ++ ++&frddr_b { ++ status = "okay"; ++}; ++ ++&frddr_c { ++ status = "okay"; ++}; ++ + &hdmi_tx { + status = "okay"; + pinctrl-0 = <&hdmitx_hpd_pins>, <&hdmitx_ddc_pins>; +@@ -288,6 +396,28 @@ + vqmmc-supply = <&flash_1v8>; + }; + ++&spdifout { ++ pinctrl-0 = <&spdif_out_h_pins>; ++ pinctrl-names = "default"; ++ status = "okay"; ++}; ++ ++&spdifout_b { ++ status = "okay"; ++}; ++ ++&tdmif_b { ++ status = "okay"; ++}; ++ ++&tdmout_b { ++ status = "okay"; ++}; ++ ++&tohdmitx { ++ status = "okay"; ++}; ++ + &uart_AO { + status = "okay"; + pinctrl-0 = <&uart_ao_a_pins>; +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-g12a-x96-max.dts mod/arch/arm64/boot/dts/amlogic/meson-g12a-x96-max.dts +--- main/arch/arm64/boot/dts/amlogic/meson-g12a-x96-max.dts 2023-03-07 09:42:02.009537075 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-g12a-x96-max.dts 2023-03-07 09:42:03.469548398 +0100 +@@ -12,7 +12,8 @@ + + / { + compatible = "amediatech,x96-max", "amlogic,g12a"; +- model = "Shenzhen Amediatech Technology Co., Ltd X96 Max"; ++ //model = "Shenzhen Amediatech Technology Co., Ltd X96 Max"; ++ model = "AMedia X96 Max"; + + aliases { + serial0 = &uart_AO; +@@ -29,9 +30,10 @@ + chosen { + stdout-path = "serial0:115200n8"; + }; ++ + memory@0 { + device_type = "memory"; +- reg = <0x0 0x0 0x0 0x40000000>; ++ reg = <0x0 0x0 0x0 0xFFFFFFFF>; + }; + + cvbs-connector { +@@ -147,6 +149,16 @@ + regulator-always-on; + }; + ++ vddgpu: regulator-vddgpu { ++ compatible = "regulator-fixed"; ++ regulator-name = "mali"; ++ regulator-min-microvolt = <800000>; ++ regulator-max-microvolt = <800000>; ++ vin-supply = <&dc_in>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ + sound { + compatible = "amlogic,axg-sound-card"; + model = "X96-MAX"; +@@ -233,6 +245,12 @@ + clock-frequency = <32768>; + pwms = <&pwm_ef 0 30518 0>; /* PWM_E at 32.768KHz */ + }; ++ ++ openvfd { ++ compatible = "open,vfd"; ++ dev_name = "openvfd"; ++ status = "okay"; ++ }; + }; + + &arb { +@@ -285,6 +303,10 @@ + clock-latency = <50000>; + }; + ++&mali { ++ mali-supply=<&vddgpu>; ++}; ++ + &cvbs_vdac_port { + cvbs_vdac_out: endpoint { + remote-endpoint = <&cvbs_connector_in>; +@@ -354,7 +376,18 @@ + status = "okay"; + phy-mode = "rgmii"; + phy-handle = <&external_phy>; ++ + amlogic,tx-delay-ns = <2>; ++ ++ snps,aal; ++ snps,rxpbl = <0x8>; ++ snps,txpbl = <0x8>; ++ ++ rx-fifo-depth = <4096>; ++ tx-fifo-depth = <4096>; ++ ++ nvmem-cells = <ð_mac>; ++ nvmem-cell-names = "eth_mac"; + }; + + &pwm_ef { +@@ -431,7 +464,7 @@ + + bus-width = <4>; + cap-sd-highspeed; +- max-frequency = <100000000>; ++ max-frequency = <50000000>; + disable-wp; + + cd-gpios = <&gpio GPIOC_6 GPIO_ACTIVE_LOW>; +@@ -448,7 +481,9 @@ + + bus-width = <8>; + cap-mmc-highspeed; +- max-frequency = <100000000>; ++ mmc-ddr-1_8v; ++ mmc-hs200-1_8v; ++ max-frequency = <200000000>; + non-removable; + disable-wp; + +@@ -478,3 +513,28 @@ + &tohdmitx { + status = "okay"; + }; ++ ++&cpu_opp_table { ++ opp-1908000000 { ++ opp-hz = /bits/ 64 <1908000000>; ++ opp-microvolt = <1021000>; ++ }; ++}; ++ ++&efuse { ++ eth_mac: eth_mac@0 { ++ reg = <0x0 0x06>; ++ }; ++ ++ bt_mac: bt_mac@6 { ++ reg = <0x6 0x06>; ++ }; ++ ++ wifi_mac: wifi_mac@12 { ++ reg = <0x0c 0x06>; ++ }; ++ ++ usid: usid@18 { ++ reg = <0x12 0x10>; ++ }; ++}; +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-g12a-x96-max-rmii.dts mod/arch/arm64/boot/dts/amlogic/meson-g12a-x96-max-rmii.dts +--- main/arch/arm64/boot/dts/amlogic/meson-g12a-x96-max-rmii.dts 1970-01-01 01:00:00.000000000 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-g12a-x96-max-rmii.dts 2023-03-07 09:42:03.457548304 +0100 +@@ -0,0 +1,36 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++/* ++ * Copyright (c) 2018 BayLibre SAS. All rights reserved. ++ */ ++ ++/dts-v1/; ++ ++#include "meson-g12a-x96-max.dts" ++ ++/ { ++ compatible = "amediatech,x96-max-rmii", "amlogic,u200", "amlogic,g12a"; ++ //model = "Shenzhen Amediatech Technology Co., Ltd X96 Max"; ++ model = "X96 Max (RMII)"; ++ ++ memory@0 { ++ device_type = "memory"; ++ reg = <0x0 0x0 0x0 0x80000000>; ++ }; ++}; ++ ++&ext_mdio { ++ external_phy: ethernet-phy@0 { ++ compatible = "ethernet-phy-id001c.c916", "ethernet-phy-ieee802.3-c22"; ++ reg = <0>; ++ max-speed = <1000>; ++ eee-broken-1000t; ++ }; ++}; ++ ++ðmac { ++ pinctrl-0 = <ð_pins>; ++ pinctrl-names = "default"; ++ status = "okay"; ++ phy-mode = "rmii"; ++ phy-handle = <&internal_ephy>; ++}; +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-g12b-a311d-khadas-vim3.dts mod/arch/arm64/boot/dts/amlogic/meson-g12b-a311d-khadas-vim3.dts +--- main/arch/arm64/boot/dts/amlogic/meson-g12b-a311d-khadas-vim3.dts 2023-03-07 09:42:02.037537292 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-g12b-a311d-khadas-vim3.dts 2023-03-07 09:42:03.489548551 +0100 +@@ -15,6 +15,10 @@ + compatible = "khadas,vim3", "amlogic,a311d", "amlogic,g12b"; + }; + ++&npu { ++ status = "okay"; ++}; ++ + /* + * The VIM3 on-board MCU can mux the PCIe/USB3.0 shared differential + * lines using a FUSB340TMX USB 3.1 SuperSpeed Data Switch between +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-g12b-dreambox.dtsi mod/arch/arm64/boot/dts/amlogic/meson-g12b-dreambox.dtsi +--- main/arch/arm64/boot/dts/amlogic/meson-g12b-dreambox.dtsi 1970-01-01 01:00:00.000000000 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-g12b-dreambox.dtsi 2023-03-07 09:42:03.533548894 +0100 +@@ -0,0 +1,210 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++/* ++ * Copyright (c) 2021 Christian Hewitt ++ */ ++ ++#include "meson-g12b-w400.dtsi" ++#include ++#include ++#include ++ ++/ { ++ cvbs-connector { ++ status = "disabled"; ++ }; ++ ++ adc_keys { ++ compatible = "adc-keys"; ++ io-channels = <&saradc 2>; ++ io-channel-names = "buttons"; ++ keyup-threshold-microvolt = <1800000>; ++ ++ button-up { ++ label = "Volume Up"; ++ linux,code = ; ++ press-threshold-microvolt = <4680352>; ++ }; ++ ++ button-down { ++ label = "Volume Down"; ++ linux,code = ; ++ press-threshold-microvolt = <2516129>; ++ }; ++ ++ button-enter { ++ label = "Enter"; ++ linux,code = ; ++ press-threshold-microvolt = <6844575>; ++ }; ++ }; ++ ++ gpio-keys-polled { ++ compatible = "gpio-keys-polled"; ++ poll-interval = <20>; ++ ++ button { ++ label = "power"; ++ linux,code = ; ++ gpios = <&gpio_ao GPIOAO_3 GPIO_ACTIVE_HIGH>; ++ }; ++ }; ++ ++ leds { ++ compatible = "gpio-leds"; ++ ++ led-system { ++ label = "system-status"; ++ color = ; ++ function = LED_FUNCTION_POWER; ++ gpios = <&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH>; ++ default-state = "on"; ++ panic-indicator; ++ retain-state-suspended; ++ }; ++ }; ++ ++ sdio_pwrseq: sdio-pwrseq { ++ compatible = "mmc-pwrseq-simple"; ++ reset-gpios = <&gpio GPIOA_11 GPIO_ACTIVE_LOW>; ++ clocks = <&wifi32k>; ++ clock-names = "ext_clock"; ++ }; ++ ++ spdif_dit: audio-codec-1 { ++ #sound-dai-cells = <0>; ++ compatible = "linux,spdif-dit"; ++ status = "okay"; ++ sound-name-prefix = "DIT"; ++ }; ++ ++ sound { ++ compatible = "amlogic,axg-sound-card"; ++ model = "DREAMBOX"; ++ audio-aux-devs = <&tdmout_b>; ++ audio-routing = "TDMOUT_B IN 0", "FRDDR_A OUT 1", ++ "TDMOUT_B IN 1", "FRDDR_B OUT 1", ++ "TDMOUT_B IN 2", "FRDDR_C OUT 1", ++ "TDM_B Playback", "TDMOUT_B OUT", ++ "SPDIFOUT IN 0", "FRDDR_A OUT 3", ++ "SPDIFOUT IN 1", "FRDDR_B OUT 3", ++ "SPDIFOUT IN 2", "FRDDR_C OUT 3"; ++ ++ assigned-clocks = <&clkc CLKID_MPLL2>, ++ <&clkc CLKID_MPLL0>, ++ <&clkc CLKID_MPLL1>; ++ assigned-clock-parents = <0>, <0>, <0>; ++ assigned-clock-rates = <294912000>, ++ <270950400>, ++ <393216000>; ++ status = "okay"; ++ ++ dai-link-0 { ++ sound-dai = <&frddr_a>; ++ }; ++ ++ dai-link-1 { ++ sound-dai = <&frddr_b>; ++ }; ++ ++ dai-link-2 { ++ sound-dai = <&frddr_c>; ++ }; ++ ++ /* 8ch hdmi interface */ ++ dai-link-3 { ++ sound-dai = <&tdmif_b>; ++ dai-format = "i2s"; ++ dai-tdm-slot-tx-mask-0 = <1 1>; ++ dai-tdm-slot-tx-mask-1 = <1 1>; ++ dai-tdm-slot-tx-mask-2 = <1 1>; ++ dai-tdm-slot-tx-mask-3 = <1 1>; ++ mclk-fs = <256>; ++ ++ codec { ++ sound-dai = <&tohdmitx TOHDMITX_I2S_IN_B>; ++ }; ++ }; ++ ++ /* spdif hdmi or toslink interface */ ++ dai-link-4 { ++ sound-dai = <&spdifout>; ++ ++ codec-0 { ++ sound-dai = <&spdif_dit>; ++ }; ++ ++ codec-1 { ++ sound-dai = <&tohdmitx TOHDMITX_SPDIF_IN_A>; ++ }; ++ }; ++ ++ /* spdif hdmi interface */ ++ dai-link-5 { ++ sound-dai = <&spdifout_b>; ++ ++ codec { ++ sound-dai = <&tohdmitx TOHDMITX_SPDIF_IN_B>; ++ }; ++ }; ++ ++ /* hdmi glue */ ++ dai-link-6 { ++ sound-dai = <&tohdmitx TOHDMITX_I2S_OUT>; ++ ++ codec { ++ sound-dai = <&hdmi_tx>; ++ }; ++ }; ++ }; ++}; ++ ++&arb { ++ status = "okay"; ++}; ++ ++&clkc_audio { ++ status = "okay"; ++}; ++ ++&frddr_a { ++ status = "okay"; ++}; ++ ++&frddr_b { ++ status = "okay"; ++}; ++ ++&frddr_c { ++ status = "okay"; ++}; ++ ++&ir { ++ linux,rc-map-name = "rc-dreambox"; ++}; ++ ++&saradc { ++ status = "okay"; ++ vref-supply = <&vddao_1v8>; ++}; ++ ++&spdifout { ++ pinctrl-0 = <&spdif_out_h_pins>; ++ pinctrl-names = "default"; ++ status = "okay"; ++}; ++ ++&spdifout_b { ++ status = "okay"; ++}; ++ ++&tdmif_b { ++ status = "okay"; ++}; ++ ++&tdmout_b { ++ status = "okay"; ++}; ++ ++&tohdmitx { ++ status = "okay"; ++}; +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-g12b-dreambox-one.dts mod/arch/arm64/boot/dts/amlogic/meson-g12b-dreambox-one.dts +--- main/arch/arm64/boot/dts/amlogic/meson-g12b-dreambox-one.dts 1970-01-01 01:00:00.000000000 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-g12b-dreambox-one.dts 2023-03-07 09:42:03.509548708 +0100 +@@ -0,0 +1,13 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++/* ++ * Copyright (c) 2019 Christian Hewitt ++ */ ++ ++/dts-v1/; ++ ++#include "meson-g12b-dreambox.dtsi" ++ ++/ { ++ compatible = "dream,dreambox-one", "amlogic,g12b"; ++ model = "Dreambox One"; ++}; +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-g12b-dreambox-two.dts mod/arch/arm64/boot/dts/amlogic/meson-g12b-dreambox-two.dts +--- main/arch/arm64/boot/dts/amlogic/meson-g12b-dreambox-two.dts 1970-01-01 01:00:00.000000000 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-g12b-dreambox-two.dts 2023-03-07 09:42:03.525548832 +0100 +@@ -0,0 +1,13 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++/* ++ * Copyright (c) 2019 Christian Hewitt ++ */ ++ ++/dts-v1/; ++ ++#include "meson-g12b-dreambox.dtsi" ++ ++/ { ++ compatible = "dream,dreambox-two", "amlogic,g12b"; ++ model = "Dreambox Two"; ++}; +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-g12b.dtsi mod/arch/arm64/boot/dts/amlogic/meson-g12b.dtsi +--- main/arch/arm64/boot/dts/amlogic/meson-g12b.dtsi 2023-03-07 09:42:02.165538283 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-g12b.dtsi 2023-03-07 09:42:03.757550630 +0100 +@@ -139,3 +139,41 @@ + &mali { + dma-coherent; + }; ++ ++&npu { ++ power-domains = <&pwrc PWRC_G12A_NNA_ID>; ++}; ++ ++&periphs_pinctrl { ++ pwm_b_h_pins: pwm-b-h { ++ mux { ++ groups = "pwm_b_h"; ++ function = "pwm_b"; ++ bias-disable; ++ }; ++ }; ++ ++ pwm_b_z_pins: pwm-b-z { ++ mux { ++ groups = "pwm_b_z"; ++ function = "pwm_b"; ++ bias-disable; ++ }; ++ }; ++ ++ pwm_c_z_pins: pwm-c-z { ++ mux { ++ groups = "pwm_c_z"; ++ function = "pwm_c"; ++ bias-disable; ++ }; ++ }; ++ ++ pwm_d_z_pins: pwm-d-z { ++ mux { ++ groups = "pwm_d_z"; ++ function = "pwm_d"; ++ bias-disable; ++ }; ++ }; ++}; +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-g12b-gtking.dts mod/arch/arm64/boot/dts/amlogic/meson-g12b-gtking.dts +--- main/arch/arm64/boot/dts/amlogic/meson-g12b-gtking.dts 2023-03-07 09:42:02.077537602 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-g12b-gtking.dts 2023-03-07 09:42:03.613549514 +0100 +@@ -8,6 +8,7 @@ + /dts-v1/; + + #include "meson-g12b-w400.dtsi" ++#include + #include + + / { +@@ -29,14 +30,37 @@ + sound { + compatible = "amlogic,axg-sound-card"; + model = "GTKING"; +- audio-aux-devs = <&tdmout_b>; ++ audio-widgets = "Line", "Lineout"; ++ audio-aux-devs = <&tdmout_b>, <&tdmout_c>, ++ <&tdmin_a>, <&tdmin_b>, <&tdmin_c>; + audio-routing = "TDMOUT_B IN 0", "FRDDR_A OUT 1", + "TDMOUT_B IN 1", "FRDDR_B OUT 1", + "TDMOUT_B IN 2", "FRDDR_C OUT 1", + "TDM_B Playback", "TDMOUT_B OUT", ++ "TDMOUT_C IN 0", "FRDDR_A OUT 2", ++ "TDMOUT_C IN 1", "FRDDR_B OUT 2", ++ "TDMOUT_C IN 2", "FRDDR_C OUT 2", ++ "TDM_C Playback", "TDMOUT_C OUT", ++ "TDMIN_A IN 4", "TDM_B Loopback", ++ "TDMIN_B IN 4", "TDM_B Loopback", ++ "TDMIN_C IN 4", "TDM_B Loopback", ++ "TDMIN_A IN 5", "TDM_C Loopback", ++ "TDMIN_B IN 5", "TDM_C Loopback", ++ "TDMIN_C IN 5", "TDM_C Loopback", ++ "TODDR_A IN 0", "TDMIN_A OUT", ++ "TODDR_B IN 0", "TDMIN_A OUT", ++ "TODDR_C IN 0", "TDMIN_A OUT", ++ "TODDR_A IN 1", "TDMIN_B OUT", ++ "TODDR_B IN 1", "TDMIN_B OUT", ++ "TODDR_C IN 1", "TDMIN_B OUT", ++ "TODDR_A IN 2", "TDMIN_C OUT", ++ "TODDR_B IN 2", "TDMIN_C OUT", ++ "TODDR_C IN 2", "TDMIN_C OUT", + "SPDIFOUT IN 0", "FRDDR_A OUT 3", + "SPDIFOUT IN 1", "FRDDR_B OUT 3", +- "SPDIFOUT IN 2", "FRDDR_C OUT 3"; ++ "SPDIFOUT IN 2", "FRDDR_C OUT 3", ++ "Lineout", "ACODEC LOLP", ++ "Lineout", "ACODEC LORP"; + + assigned-clocks = <&clkc CLKID_MPLL2>, + <&clkc CLKID_MPLL0>, +@@ -59,8 +83,20 @@ + sound-dai = <&frddr_c>; + }; + +- /* 8ch hdmi interface */ + dai-link-3 { ++ sound-dai = <&toddr_a>; ++ }; ++ ++ dai-link-4 { ++ sound-dai = <&toddr_b>; ++ }; ++ ++ dai-link-5 { ++ sound-dai = <&toddr_c>; ++ }; ++ ++ /* 8ch hdmi interface */ ++ dai-link-6 { + sound-dai = <&tdmif_b>; + dai-format = "i2s"; + dai-tdm-slot-tx-mask-0 = <1 1>; +@@ -69,13 +105,17 @@ + dai-tdm-slot-tx-mask-3 = <1 1>; + mclk-fs = <256>; + +- codec { ++ codec-0 { + sound-dai = <&tohdmitx TOHDMITX_I2S_IN_B>; + }; ++ ++ codec-1 { ++ sound-dai = <&toacodec TOACODEC_IN_B>; ++ }; + }; + + /* spdif hdmi or toslink interface */ +- dai-link-4 { ++ dai-link-7 { + sound-dai = <&spdifout>; + + codec-0 { +@@ -88,7 +128,7 @@ + }; + + /* spdif hdmi interface */ +- dai-link-5 { ++ dai-link-8 { + sound-dai = <&spdifout_b>; + + codec { +@@ -96,15 +136,59 @@ + }; + }; + ++ /* i2s jack output interface */ ++ dai-link-9 { ++ sound-dai = <&tdmif_c>; ++ dai-format = "i2s"; ++ dai-tdm-slot-tx-mask-0 = <1 1>; ++ mclk-fs = <256>; ++ ++ codec-0 { ++ sound-dai = <&tohdmitx TOHDMITX_I2S_IN_C>; ++ }; ++ ++ codec-1 { ++ sound-dai = <&toacodec TOACODEC_IN_C>; ++ }; ++ }; ++ + /* hdmi glue */ +- dai-link-6 { ++ dai-link-10 { + sound-dai = <&tohdmitx TOHDMITX_I2S_OUT>; + + codec { + sound-dai = <&hdmi_tx>; + }; + }; ++ ++ /* acodec glue */ ++ dai-link-11 { ++ sound-dai = <&toacodec TOACODEC_OUT>; ++ ++ codec { ++ sound-dai = <&acodec>; ++ }; ++ }; + }; ++ ++ vddgpu: regulator-vddgpu { ++ compatible = "regulator-fixed"; ++ regulator-name = "mali"; ++ regulator-min-microvolt = <800000>; ++ regulator-max-microvolt = <800000>; ++ vin-supply = <&vcc_5v>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++}; ++ ++&mali { ++ mali-supply=<&vddgpu>; ++}; ++ ++&acodec { ++ AVDD-supply = <&vddao_1v8>; ++ status = "okay"; + }; + + &arb { +@@ -154,10 +238,77 @@ + status = "okay"; + }; + ++&tdmif_c { ++ status = "okay"; ++}; ++ ++&tdmin_a { ++ status = "okay"; ++}; ++ ++&tdmin_b { ++ status = "okay"; ++}; ++ ++&tdmin_c { ++ status = "okay"; ++}; ++ + &tdmout_b { + status = "okay"; + }; + ++&tdmout_c { ++ status = "okay"; ++}; ++ ++&toacodec { ++ status = "okay"; ++}; ++ ++&toddr_a { ++ status = "okay"; ++}; ++ ++&toddr_b { ++ status = "okay"; ++}; ++ ++&toddr_c { ++ status = "okay"; ++}; ++ + &tohdmitx { + status = "okay"; + }; ++ ++/* SDIO */ ++&sd_emmc_a { ++ //max-frequency = <200000000>; ++ //sd-uhs-sdr104; ++ max-frequency = <50000000>; ++ sd-uhs-ddr50; ++ //sd-uhs-sdr50; ++ //max-frequency = <100000000>; ++}; ++ ++/* SD CARD */ ++&sd_emmc_b { ++ cap-sd-highspeed; ++ max-frequency = <50000000>; ++}; ++ ++/* EMMC */ ++&sd_emmc_c { ++ mmc-hs200-1_8v; ++ max-frequency = <200000000>; ++}; ++ ++ðmac { ++ snps,aal; ++ snps,rxpbl = <0x8>; ++ snps,txpbl = <0x8>; ++ ++ rx-fifo-depth = <4096>; ++ tx-fifo-depth = <4096>; ++}; +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-g12b-gtking-oc.dts mod/arch/arm64/boot/dts/amlogic/meson-g12b-gtking-oc.dts +--- main/arch/arm64/boot/dts/amlogic/meson-g12b-gtking-oc.dts 1970-01-01 01:00:00.000000000 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-g12b-gtking-oc.dts 2023-03-07 09:42:03.553549047 +0100 +@@ -0,0 +1,11 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++/* ++ * Copyright (c) 2019 BayLibre, SAS ++ * Author: Neil Armstrong ++ * Copyright (c) 2019 Christian Hewitt ++ */ ++ ++/dts-v1/; ++ ++#include "meson-g12b-gtking.dts" ++#include "meson-g12b-s922x-oc.dtsi" +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-g12b-gtking-pro.dts mod/arch/arm64/boot/dts/amlogic/meson-g12b-gtking-pro.dts +--- main/arch/arm64/boot/dts/amlogic/meson-g12b-gtking-pro.dts 2023-03-07 09:42:02.069537540 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-g12b-gtking-pro.dts 2023-03-07 09:42:03.601549419 +0100 +@@ -19,8 +19,15 @@ + rtc1 = &vrtc; + }; + ++ memory@0 { ++ device_type = "memory"; ++ reg = <0x0 0x0 0x0 0x80000000>; ++ }; ++ + gpio-keys-polled { + compatible = "gpio-keys-polled"; ++ #address-cells = <1>; ++ #size-cells = <0>; + poll-interval = <100>; + + power-button { +@@ -93,6 +100,20 @@ + }; + }; + }; ++ ++ vddgpu: regulator-vddgpu { ++ compatible = "regulator-fixed"; ++ regulator-name = "mali"; ++ regulator-min-microvolt = <800000>; ++ regulator-max-microvolt = <800000>; ++ vin-supply = <&vcc_5v>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++}; ++ ++&mali { ++ mali-supply=<&vddgpu>; + }; + + &arb { +@@ -138,3 +159,34 @@ + &tohdmitx { + status = "okay"; + }; ++ ++/* SDIO */ ++&sd_emmc_a { ++ //max-frequency = <100000000>; ++ //sd-uhs-sdr50; ++ //max-frequency = <200000000>; ++ //sd-uhs-sdr104; ++ max-frequency = <50000000>; ++ sd-uhs-ddr50; ++}; ++ ++/* SD Card */ ++&sd_emmc_b { ++ cap-sd-highspeed; ++ max-frequency = <50000000>; ++}; ++ ++/* EMMC */ ++&sd_emmc_c { ++ mmc-hs200-1_8v; ++ max-frequency = <200000000>; ++}; ++ ++ðmac { ++ snps,aal; ++ snps,rxpbl = <0x8>; ++ snps,txpbl = <0x8>; ++ ++ rx-fifo-depth = <4096>; ++ tx-fifo-depth = <4096>; ++}; +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-g12b-gtking-pro-h.dts mod/arch/arm64/boot/dts/amlogic/meson-g12b-gtking-pro-h.dts +--- main/arch/arm64/boot/dts/amlogic/meson-g12b-gtking-pro-h.dts 1970-01-01 01:00:00.000000000 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-g12b-gtking-pro-h.dts 2023-03-07 09:42:03.573549204 +0100 +@@ -0,0 +1,11 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++/* ++ * Copyright (c) 2019 BayLibre, SAS ++ * Author: Neil Armstrong ++ * Copyright (c) 2019 Christian Hewitt ++ */ ++ ++/dts-v1/; ++ ++#include "meson-g12b-gtking-pro.dts" ++#include "meson-g12b-s922x-h.dtsi" +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-g12b-gtking-pro-h-oc.dts mod/arch/arm64/boot/dts/amlogic/meson-g12b-gtking-pro-h-oc.dts +--- main/arch/arm64/boot/dts/amlogic/meson-g12b-gtking-pro-h-oc.dts 1970-01-01 01:00:00.000000000 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-g12b-gtking-pro-h-oc.dts 2023-03-07 09:42:03.565549142 +0100 +@@ -0,0 +1,11 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++/* ++ * Copyright (c) 2019 BayLibre, SAS ++ * Author: Neil Armstrong ++ * Copyright (c) 2019 Christian Hewitt ++ */ ++ ++/dts-v1/; ++ ++#include "meson-g12b-gtking-pro.dts" ++#include "meson-g12b-s922x-h-oc.dtsi" +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-g12b-gtking-pro-rev_a.dts mod/arch/arm64/boot/dts/amlogic/meson-g12b-gtking-pro-rev_a.dts +--- main/arch/arm64/boot/dts/amlogic/meson-g12b-gtking-pro-rev_a.dts 1970-01-01 01:00:00.000000000 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-g12b-gtking-pro-rev_a.dts 2023-03-07 09:42:03.593549357 +0100 +@@ -0,0 +1,146 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++/* ++ * Copyright (c) 2019 BayLibre, SAS ++ * Author: Neil Armstrong ++ */ ++ ++/dts-v1/; ++ ++/* ++ * The Beelink GT-King Pro Rev A(HW Version: SA9H) is not base on w400 board, ++ * but it is closer to the circuit design of Hardkernel ODroid N2 ++ */ ++ ++#include "meson-g12b-s922x.dtsi" ++#include "meson-g12b-odroid-n2.dtsi" ++ ++/ { ++ compatible = "azw,gtking", "amlogic,s922x", "amlogic,g12b"; ++ model = "Beelink GT-King Pro (Rev A)"; ++ ++ gpio-keys-polled { ++ compatible = "gpio-keys-polled"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ poll-interval = <100>; ++ ++ power-button { ++ label = "power"; ++ linux,code = ; ++ /* Just for test, because i don't konwn the turely GPIO of the REV A board */ ++ gpios = <&gpio_ao GPIOAO_3 GPIO_ACTIVE_HIGH>; ++ }; ++ }; ++ ++ leds { ++ compatible = "gpio-leds"; ++ ++ /delete-node/ led-blue; ++ led-white { ++ label = "power:white"; ++ gpios = <&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH>; ++ default-state = "on"; ++ }; ++ }; ++ ++ sound { ++ model = "GTKINGPRO"; ++ }; ++ ++ /delete-node/ gpio-regulator-tf_io; ++ ++ sdio_pwrseq: sdio-pwrseq { ++ compatible = "mmc-pwrseq-simple"; ++ reset-gpios = <&gpio GPIOX_6 GPIO_ACTIVE_LOW>; ++ clocks = <&wifi32k>; ++ clock-names = "ext_clock"; ++ }; ++ ++ wifi32k: wifi32k { ++ compatible = "pwm-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <32768>; ++ pwms = <&pwm_ef 0 30518 0>; /* PWM_E at 32.768KHz */ ++ }; ++ ++ vddgpu: regulator-vddgpu { ++ compatible = "regulator-fixed"; ++ regulator-name = "mali"; ++ regulator-min-microvolt = <800000>; ++ regulator-max-microvolt = <800000>; ++ vin-supply = <&vcc_5v>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++}; ++ ++&mali { ++ mali-supply=<&vddgpu>; ++}; ++ ++&pwm_ef { ++ pinctrl-0 = <&pwm_e_pins>; ++ pinctrl-names = "default"; ++ clocks = <&xtal>; ++ clock-names = "clkin0"; ++ status = "okay"; ++}; ++ ++&uart_A { ++ status = "okay"; ++ pinctrl-0 = <&uart_a_pins>, <&uart_a_cts_rts_pins>; ++ pinctrl-names = "default"; ++ uart-has-rtscts; ++ ++ bluetooth { ++ compatible = "brcm,bcm43438-bt"; ++ shutdown-gpios = <&gpio GPIOX_17 GPIO_ACTIVE_HIGH>; ++ max-speed = <2000000>; ++ clocks = <&wifi32k>; ++ clock-names = "lpo"; ++ }; ++}; ++ ++/* SDIO */ ++&sd_emmc_a { ++ status = "okay"; ++ pinctrl-0 = <&sdio_pins>; ++ pinctrl-1 = <&sdio_clk_gate_pins>; ++ pinctrl-names = "default", "clk-gate"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ bus-width = <4>; ++ cap-sd-highspeed; ++ sd-uhs-sdr50; ++ max-frequency = <100000000>; ++ ++ /* WiFi firmware requires power to be kept while in suspend */ ++ keep-power-in-suspend; ++ ++ non-removable; ++ disable-wp; ++ ++ mmc-pwrseq = <&sdio_pwrseq>; ++ ++ vmmc-supply = <&vddao_3v3>; ++ vqmmc-supply = <&vddao_1v8>; ++ ++ brcmf: wifi@1 { ++ reg = <1>; ++ compatible = "brcm,bcm4329-fmac"; ++ }; ++}; ++ ++/* SD card */ ++&sd_emmc_b { ++ max-frequency = <50000000>; ++ cap-sd-highspeed; ++ /delete-property/ sd-uhs-sdr12; ++ /delete-property/ sd-uhs-sdr25; ++ /delete-property/ sd-uhs-sdr50; ++ /delete-property/ sd-uhs-sdr104; ++ ++ vqmmc-supply = <&tflash_vdd>; ++ ++}; +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-g12b-gtking-pro-rev_a-oc.dts mod/arch/arm64/boot/dts/amlogic/meson-g12b-gtking-pro-rev_a-oc.dts +--- main/arch/arm64/boot/dts/amlogic/meson-g12b-gtking-pro-rev_a-oc.dts 1970-01-01 01:00:00.000000000 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-g12b-gtking-pro-rev_a-oc.dts 2023-03-07 09:42:03.585549295 +0100 +@@ -0,0 +1,11 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++/* ++ * Copyright (c) 2019 BayLibre, SAS ++ * Author: Neil Armstrong ++ * Copyright (c) 2019 Christian Hewitt ++ */ ++ ++/dts-v1/; ++ ++#include "meson-g12b-gtking-pro-rev_a.dts" ++#include "meson-g12b-s922x-oc.dtsi" +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-g12b-radxa-zero2.dts mod/arch/arm64/boot/dts/amlogic/meson-g12b-radxa-zero2.dts +--- main/arch/arm64/boot/dts/amlogic/meson-g12b-radxa-zero2.dts 1970-01-01 01:00:00.000000000 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-g12b-radxa-zero2.dts 2023-03-07 09:42:03.669549948 +0100 +@@ -0,0 +1,503 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++/* ++ * Copyright (c) 2019 BayLibre, SAS ++ * Author: Neil Armstrong ++ * Copyright (c) 2019 Christian Hewitt ++ * Copyright (c) 2022 Radxa Limited ++ * Author: Yuntian Zhang ++ */ ++ ++/dts-v1/; ++ ++#include "meson-g12b-a311d.dtsi" ++#include ++#include ++#include ++#include ++ ++/ { ++ compatible = "radxa,zero2", "amlogic,a311d", "amlogic,g12b"; ++ model = "Radxa Zero2"; ++ ++ aliases { ++ serial0 = &uart_AO; ++ serial2 = &uart_A; ++ }; ++ ++ chosen { ++ stdout-path = "serial0:115200n8"; ++ }; ++ ++ memory@0 { ++ device_type = "memory"; ++ reg = <0x0 0x0 0x0 0x80000000>; ++ }; ++ ++ gpio-keys-polled { ++ compatible = "gpio-keys-polled"; ++ poll-interval = <100>; ++ power-button { ++ label = "power"; ++ linux,code = ; ++ gpios = <&gpio_ao GPIOAO_3 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; ++ }; ++ }; ++ ++ leds { ++ compatible = "gpio-leds"; ++ ++ led-green { ++ color = ; ++ function = LED_FUNCTION_STATUS; ++ gpios = <&gpio GPIOA_12 GPIO_ACTIVE_HIGH>; ++ linux,default-trigger = "heartbeat"; ++ }; ++ }; ++ ++ cvbs-connector { ++ status = "disabled"; ++ compatible = "composite-video-connector"; ++ ++ port { ++ cvbs_connector_in: endpoint { ++ remote-endpoint = <&cvbs_vdac_out>; ++ }; ++ }; ++ }; ++ ++ hdmi-connector { ++ compatible = "hdmi-connector"; ++ type = "a"; ++ ++ port { ++ hdmi_connector_in: endpoint { ++ remote-endpoint = <&hdmi_tx_tmds_out>; ++ }; ++ }; ++ }; ++ ++ emmc_pwrseq: emmc-pwrseq { ++ compatible = "mmc-pwrseq-emmc"; ++ reset-gpios = <&gpio BOOT_12 GPIO_ACTIVE_LOW>; ++ }; ++ ++ sdio_pwrseq: sdio-pwrseq { ++ compatible = "mmc-pwrseq-simple"; ++ reset-gpios = <&gpio GPIOX_6 GPIO_ACTIVE_LOW>; ++ clocks = <&wifi32k>; ++ clock-names = "ext_clock"; ++ }; ++ ++ ao_5v: regulator-ao_5v { ++ compatible = "regulator-fixed"; ++ regulator-name = "AO_5V"; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ regulator-always-on; ++ }; ++ ++ vcc_1v8: regulator-vcc_1v8 { ++ compatible = "regulator-fixed"; ++ regulator-name = "VCC_1V8"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ vin-supply = <&vcc_3v3>; ++ regulator-always-on; ++ }; ++ ++ vcc_3v3: regulator-vcc_3v3 { ++ compatible = "regulator-fixed"; ++ regulator-name = "VCC_3V3"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ vin-supply = <&vddao_3v3>; ++ regulator-always-on; ++ /* FIXME: actually controlled by VDDCPU_B_EN */ ++ }; ++ ++ vddao_1v8: regulator-vddao_1v8 { ++ compatible = "regulator-fixed"; ++ regulator-name = "VDDIO_AO1V8"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ vin-supply = <&vddao_3v3>; ++ regulator-always-on; ++ }; ++ ++ vddao_3v3: regulator-vddao_3v3 { ++ compatible = "regulator-fixed"; ++ regulator-name = "VDDAO_3V3"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ vin-supply = <&ao_5v>; ++ regulator-always-on; ++ }; ++ ++ vddcpu_a: regulator-vddcpu-a { ++ /* ++ * MP8756GD Regulator. ++ */ ++ compatible = "pwm-regulator"; ++ ++ regulator-name = "VDDCPU_A"; ++ regulator-min-microvolt = <730000>; ++ regulator-max-microvolt = <1022000>; ++ ++ pwm-supply = <&ao_5v>; ++ ++ pwms = <&pwm_ab 0 1250 0>; ++ pwm-dutycycle-range = <100 0>; ++ ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ vddcpu_b: regulator-vddcpu-b { ++ /* ++ * Silergy SY8120B1ABC Regulator. ++ */ ++ compatible = "pwm-regulator"; ++ ++ regulator-name = "VDDCPU_B"; ++ regulator-min-microvolt = <730000>; ++ regulator-max-microvolt = <1022000>; ++ ++ pwm-supply = <&ao_5v>; ++ ++ pwms = <&pwm_AO_cd 1 1250 0>; ++ pwm-dutycycle-range = <100 0>; ++ ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ sound { ++ compatible = "amlogic,axg-sound-card"; ++ model = "RADXA-ZERO2"; ++ audio-aux-devs = <&tdmout_b>; ++ audio-routing = "TDMOUT_B IN 0", "FRDDR_A OUT 1", ++ "TDMOUT_B IN 1", "FRDDR_B OUT 1", ++ "TDMOUT_B IN 2", "FRDDR_C OUT 1", ++ "TDM_B Playback", "TDMOUT_B OUT"; ++ ++ assigned-clocks = <&clkc CLKID_MPLL2>, ++ <&clkc CLKID_MPLL0>, ++ <&clkc CLKID_MPLL1>; ++ assigned-clock-parents = <0>, <0>, <0>; ++ assigned-clock-rates = <294912000>, ++ <270950400>, ++ <393216000>; ++ status = "okay"; ++ ++ dai-link-0 { ++ sound-dai = <&frddr_a>; ++ }; ++ ++ dai-link-1 { ++ sound-dai = <&frddr_b>; ++ }; ++ ++ dai-link-2 { ++ sound-dai = <&frddr_c>; ++ }; ++ ++ /* 8ch hdmi interface */ ++ dai-link-3 { ++ sound-dai = <&tdmif_b>; ++ dai-format = "i2s"; ++ dai-tdm-slot-tx-mask-0 = <1 1>; ++ dai-tdm-slot-tx-mask-1 = <1 1>; ++ dai-tdm-slot-tx-mask-2 = <1 1>; ++ dai-tdm-slot-tx-mask-3 = <1 1>; ++ mclk-fs = <256>; ++ ++ codec { ++ sound-dai = <&tohdmitx TOHDMITX_I2S_IN_B>; ++ }; ++ }; ++ ++ /* hdmi glue */ ++ dai-link-4 { ++ sound-dai = <&tohdmitx TOHDMITX_I2S_OUT>; ++ ++ codec { ++ sound-dai = <&hdmi_tx>; ++ }; ++ }; ++ }; ++ ++ wifi32k: wifi32k { ++ compatible = "pwm-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <32768>; ++ pwms = <&pwm_ef 0 30518 0>; /* PWM_E at 32.768KHz */ ++ }; ++}; ++ ++&arb { ++ status = "okay"; ++}; ++ ++&cec_AO { ++ pinctrl-0 = <&cec_ao_a_h_pins>; ++ pinctrl-names = "default"; ++ status = "disabled"; ++ hdmi-phandle = <&hdmi_tx>; ++}; ++ ++&cecb_AO { ++ pinctrl-0 = <&cec_ao_b_h_pins>; ++ pinctrl-names = "default"; ++ status = "okay"; ++ hdmi-phandle = <&hdmi_tx>; ++}; ++ ++&clkc_audio { ++ status = "okay"; ++}; ++ ++&cpu0 { ++ cpu-supply = <&vddcpu_b>; ++ operating-points-v2 = <&cpu_opp_table_0>; ++ clocks = <&clkc CLKID_CPU_CLK>; ++ clock-latency = <50000>; ++}; ++ ++&cpu1 { ++ cpu-supply = <&vddcpu_b>; ++ operating-points-v2 = <&cpu_opp_table_0>; ++ clocks = <&clkc CLKID_CPU_CLK>; ++ clock-latency = <50000>; ++}; ++ ++&cpu100 { ++ cpu-supply = <&vddcpu_a>; ++ operating-points-v2 = <&cpub_opp_table_1>; ++ clocks = <&clkc CLKID_CPUB_CLK>; ++ clock-latency = <50000>; ++}; ++ ++&cpu101 { ++ cpu-supply = <&vddcpu_a>; ++ operating-points-v2 = <&cpub_opp_table_1>; ++ clocks = <&clkc CLKID_CPUB_CLK>; ++ clock-latency = <50000>; ++}; ++ ++&cpu102 { ++ cpu-supply = <&vddcpu_a>; ++ operating-points-v2 = <&cpub_opp_table_1>; ++ clocks = <&clkc CLKID_CPUB_CLK>; ++ clock-latency = <50000>; ++}; ++ ++&cpu103 { ++ cpu-supply = <&vddcpu_a>; ++ operating-points-v2 = <&cpub_opp_table_1>; ++ clocks = <&clkc CLKID_CPUB_CLK>; ++ clock-latency = <50000>; ++}; ++ ++&cvbs_vdac_port { ++ cvbs_vdac_out: endpoint { ++ remote-endpoint = <&cvbs_connector_in>; ++ }; ++}; ++ ++&frddr_a { ++ status = "okay"; ++}; ++ ++&frddr_b { ++ status = "okay"; ++}; ++ ++&frddr_c { ++ status = "okay"; ++}; ++ ++&gpio { ++ gpio-line-names = ++ /* GPIOZ */ ++ "PIN_27", "PIN_28", "PIN_7", "PIN_11", "PIN_13", "PIN_15", "PIN_18", "PIN_40", ++ "", "", "", "", "", "", "", "", ++ /* GPIOH */ ++ "", "", "", "", "PIN_19", "PIN_21", "PIN_24", "PIN_23", ++ "", ++ /* BOOT */ ++ "", "", "", "", "", "", "", "", ++ "", "", "", "", "EMMC_PWRSEQ", "", "", "", ++ /* GPIOC */ ++ "", "", "", "", "", "", "SD_CD", "PIN_36", ++ /* GPIOA */ ++ "PIN_32", "PIN_12", "PIN_35", "", "", "PIN_38", "", "", ++ "", "", "", "", "LED_GREEN", "PIN_31", "PIN_3", "PIN_5", ++ /* GPIOX */ ++ "", "", "", "", "", "", "SDIO_PWRSEQ", "", ++ "", "", "", "", "", "", "", "", ++ "", "BT_SHUTDOWN", "", ""; ++}; ++ ++&gpio_ao { ++ gpio-line-names = ++ /* GPIOAO */ ++ "PIN_8", "PIN_10", "", "BTN_POWER", "", "", "", "PIN_29", ++ "PIN_33", "PIN_37", "FAN", "", ++ /* GPIOE */ ++ "", "", ""; ++}; ++ ++&hdmi_tx { ++ status = "okay"; ++ pinctrl-0 = <&hdmitx_hpd_pins>, <&hdmitx_ddc_pins>; ++ pinctrl-names = "default"; ++ hdmi-supply = <&ao_5v>; ++}; ++ ++&hdmi_tx_tmds_port { ++ hdmi_tx_tmds_out: endpoint { ++ remote-endpoint = <&hdmi_connector_in>; ++ }; ++}; ++ ++&ir { ++ status = "disabled"; ++ pinctrl-0 = <&remote_input_ao_pins>; ++ pinctrl-names = "default"; ++}; ++ ++&npu { ++ status = "okay"; ++}; ++ ++&pwm_ab { ++ pinctrl-0 = <&pwm_a_e_pins>; ++ pinctrl-names = "default"; ++ clocks = <&xtal>; ++ clock-names = "clkin0"; ++ status = "okay"; ++}; ++ ++&pwm_ef { ++ pinctrl-0 = <&pwm_e_pins>; ++ pinctrl-names = "default"; ++ clocks = <&xtal>; ++ clock-names = "clkin2"; ++ status = "okay"; ++}; ++ ++&pwm_AO_cd { ++ pinctrl-0 = <&pwm_ao_d_e_pins>; ++ pinctrl-names = "default"; ++ clocks = <&xtal>; ++ clock-names = "clkin4"; ++ status = "okay"; ++}; ++ ++&saradc { ++ status = "okay"; ++ vref-supply = <&vddao_1v8>; ++}; ++ ++/* SDIO */ ++&sd_emmc_a { ++ status = "okay"; ++ pinctrl-0 = <&sdio_pins>; ++ pinctrl-1 = <&sdio_clk_gate_pins>; ++ pinctrl-names = "default", "clk-gate"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ bus-width = <4>; ++ cap-sd-highspeed; ++ max-frequency = <100000000>; ++ ++ non-removable; ++ disable-wp; ++ ++ /* WiFi firmware requires power to be kept while in suspend */ ++ keep-power-in-suspend; ++ ++ mmc-pwrseq = <&sdio_pwrseq>; ++ ++ vmmc-supply = <&vddao_3v3>; ++ vqmmc-supply = <&vddao_1v8>; ++ ++ brcmf: wifi@1 { ++ reg = <1>; ++ compatible = "brcm,bcm4329-fmac"; ++ }; ++}; ++ ++/* SD card */ ++&sd_emmc_b { ++ status = "okay"; ++ pinctrl-0 = <&sdcard_c_pins>; ++ pinctrl-1 = <&sdcard_clk_gate_c_pins>; ++ pinctrl-names = "default", "clk-gate"; ++ ++ bus-width = <4>; ++ cap-sd-highspeed; ++ max-frequency = <50000000>; ++ disable-wp; ++ ++ cd-gpios = <&gpio GPIOC_6 GPIO_ACTIVE_LOW>; ++ vmmc-supply = <&vddao_3v3>; ++ vqmmc-supply = <&vddao_3v3>; ++}; ++ ++/* eMMC */ ++&sd_emmc_c { ++ status = "okay"; ++ pinctrl-0 = <&emmc_ctrl_pins>, <&emmc_data_8b_pins>, <&emmc_ds_pins>; ++ pinctrl-1 = <&emmc_clk_gate_pins>; ++ pinctrl-names = "default", "clk-gate"; ++ ++ bus-width = <8>; ++ cap-mmc-highspeed; ++ mmc-ddr-1_8v; ++ mmc-hs200-1_8v; ++ max-frequency = <200000000>; ++ disable-wp; ++ ++ mmc-pwrseq = <&emmc_pwrseq>; ++ vmmc-supply = <&vcc_3v3>; ++ vqmmc-supply = <&vcc_1v8>; ++}; ++ ++&tdmif_b { ++ status = "okay"; ++}; ++ ++&tdmout_b { ++ status = "okay"; ++}; ++ ++&tohdmitx { ++ status = "okay"; ++}; ++ ++&uart_A { ++ status = "okay"; ++ pinctrl-0 = <&uart_a_pins>, <&uart_a_cts_rts_pins>; ++ pinctrl-names = "default"; ++ uart-has-rtscts; ++ ++ bluetooth { ++ compatible = "brcm,bcm43438-bt"; ++ shutdown-gpios = <&gpio GPIOX_17 GPIO_ACTIVE_HIGH>; ++ max-speed = <2000000>; ++ clocks = <&wifi32k>; ++ clock-names = "lpo"; ++ }; ++}; ++ ++&uart_AO { ++ status = "okay"; ++ pinctrl-0 = <&uart_ao_a_pins>; ++ pinctrl-names = "default"; ++}; ++ ++&usb { ++ status = "okay"; ++}; +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-g12b-s922x-h.dtsi mod/arch/arm64/boot/dts/amlogic/meson-g12b-s922x-h.dtsi +--- main/arch/arm64/boot/dts/amlogic/meson-g12b-s922x-h.dtsi 1970-01-01 01:00:00.000000000 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-g12b-s922x-h.dtsi 2023-03-07 09:42:03.689550102 +0100 +@@ -0,0 +1,106 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++/* ++ * Author: Flippy ++ */ ++ ++/ { ++ cpu_opp_table_0: opp-table-0 { ++ compatible = "operating-points-v2"; ++ opp-shared; ++ ++ opp-1000000000 { ++ opp-hz = /bits/ 64 <1000000000>; ++ opp-microvolt = <761000>; ++ }; ++ ++ opp-1200000000 { ++ opp-hz = /bits/ 64 <1200000000>; ++ opp-microvolt = <781000>; ++ }; ++ ++ opp-1398000000 { ++ opp-hz = /bits/ 64 <1398000000>; ++ opp-microvolt = <811000>; ++ }; ++ ++ opp-1512000000 { ++ opp-hz = /bits/ 64 <1512000000>; ++ opp-microvolt = <861000>; ++ }; ++ ++ opp-1608000000 { ++ opp-hz = /bits/ 64 <1608000000>; ++ opp-microvolt = <901000>; ++ }; ++ ++ opp-1704000000 { ++ opp-hz = /bits/ 64 <1704000000>; ++ opp-microvolt = <951000>; ++ }; ++ ++ opp-1800000000 { ++ opp-hz = /bits/ 64 <1800000000>; ++ opp-microvolt = <1001000>; ++ }; ++ }; ++ ++ cpub_opp_table_1: opp-table-1 { ++ compatible = "operating-points-v2"; ++ opp-shared; ++ ++ opp-1000000000 { ++ opp-hz = /bits/ 64 <1000000000>; ++ opp-microvolt = <731000>; ++ }; ++ ++ opp-1200000000 { ++ opp-hz = /bits/ 64 <1200000000>; ++ opp-microvolt = <751000>; ++ }; ++ ++ opp-1398000000 { ++ opp-hz = /bits/ 64 <1398000000>; ++ opp-microvolt = <771000>; ++ }; ++ ++ opp-1512000000 { ++ opp-hz = /bits/ 64 <1512000000>; ++ opp-microvolt = <771000>; ++ }; ++ ++ opp-1608000000 { ++ opp-hz = /bits/ 64 <1608000000>; ++ opp-microvolt = <781000>; ++ }; ++ ++ opp-1704000000 { ++ opp-hz = /bits/ 64 <1704000000>; ++ opp-microvolt = <791000>; ++ }; ++ ++ opp-1800000000 { ++ opp-hz = /bits/ 64 <1800000000>; ++ opp-microvolt = <831000>; ++ }; ++ ++ opp-1908000000 { ++ opp-hz = /bits/ 64 <1908000000>; ++ opp-microvolt = <861000>; ++ }; ++ ++ opp-2016000000 { ++ opp-hz = /bits/ 64 <2016000000>; ++ opp-microvolt = <911000>; ++ }; ++ ++ opp-2100000000 { ++ opp-hz = /bits/ 64 <2100000000>; ++ opp-microvolt = <951000>; ++ }; ++ ++ opp-2208000000 { ++ opp-hz = /bits/ 64 <2208000000>; ++ opp-microvolt = <1011000>; ++ }; ++ }; ++}; +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-g12b-s922x-h-oc.dtsi mod/arch/arm64/boot/dts/amlogic/meson-g12b-s922x-h-oc.dtsi +--- main/arch/arm64/boot/dts/amlogic/meson-g12b-s922x-h-oc.dtsi 1970-01-01 01:00:00.000000000 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-g12b-s922x-h-oc.dtsi 2023-03-07 09:42:03.681550040 +0100 +@@ -0,0 +1,117 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++/* ++ * Author: Flippy ++ */ ++ ++/ { ++ cpu_opp_table_0: opp-table-0 { ++ compatible = "operating-points-v2"; ++ opp-shared; ++ ++ opp-1000000000 { ++ opp-hz = /bits/ 64 <1000000000>; ++ opp-microvolt = <761000>; ++ }; ++ ++ opp-1200000000 { ++ opp-hz = /bits/ 64 <1200000000>; ++ opp-microvolt = <781000>; ++ }; ++ ++ opp-1398000000 { ++ opp-hz = /bits/ 64 <1398000000>; ++ opp-microvolt = <811000>; ++ }; ++ ++ opp-1512000000 { ++ opp-hz = /bits/ 64 <1512000000>; ++ opp-microvolt = <861000>; ++ }; ++ ++ opp-1608000000 { ++ opp-hz = /bits/ 64 <1608000000>; ++ opp-microvolt = <901000>; ++ }; ++ ++ opp-1704000000 { ++ opp-hz = /bits/ 64 <1704000000>; ++ opp-microvolt = <951000>; ++ }; ++ ++ opp-1800000000 { ++ opp-hz = /bits/ 64 <1800000000>; ++ opp-microvolt = <1001000>; ++ }; ++ ++ opp-1908000000 { ++ opp-hz = /bits/ 64 <1908000000>; ++ opp-microvolt = < 1021000>; ++ }; ++ ++ opp-2016000000 { ++ opp-hz = /bits/ 64 <2016000000>; ++ opp-microvolt = < 1021000>; ++ }; ++ ++ }; ++ ++ cpub_opp_table_1: opp-table-1 { ++ compatible = "operating-points-v2"; ++ opp-shared; ++ ++ opp-1000000000 { ++ opp-hz = /bits/ 64 <1000000000>; ++ opp-microvolt = <731000>; ++ }; ++ ++ opp-1200000000 { ++ opp-hz = /bits/ 64 <1200000000>; ++ opp-microvolt = <751000>; ++ }; ++ ++ opp-1398000000 { ++ opp-hz = /bits/ 64 <1398000000>; ++ opp-microvolt = <771000>; ++ }; ++ ++ opp-1512000000 { ++ opp-hz = /bits/ 64 <1512000000>; ++ opp-microvolt = <771000>; ++ }; ++ ++ opp-1608000000 { ++ opp-hz = /bits/ 64 <1608000000>; ++ opp-microvolt = <781000>; ++ }; ++ ++ opp-1704000000 { ++ opp-hz = /bits/ 64 <1704000000>; ++ opp-microvolt = <791000>; ++ }; ++ ++ opp-1800000000 { ++ opp-hz = /bits/ 64 <1800000000>; ++ opp-microvolt = <831000>; ++ }; ++ ++ opp-1908000000 { ++ opp-hz = /bits/ 64 <1908000000>; ++ opp-microvolt = <861000>; ++ }; ++ ++ opp-2016000000 { ++ opp-hz = /bits/ 64 <2016000000>; ++ opp-microvolt = <911000>; ++ }; ++ ++ opp-2100000000 { ++ opp-hz = /bits/ 64 <2100000000>; ++ opp-microvolt = <951000>; ++ }; ++ ++ opp-2208000000 { ++ opp-hz = /bits/ 64 <2208000000>; ++ opp-microvolt = <1021000>; ++ }; ++ }; ++}; +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-g12b-s922x-oc.dtsi mod/arch/arm64/boot/dts/amlogic/meson-g12b-s922x-oc.dtsi +--- main/arch/arm64/boot/dts/amlogic/meson-g12b-s922x-oc.dtsi 1970-01-01 01:00:00.000000000 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-g12b-s922x-oc.dtsi 2023-03-07 09:42:03.709550258 +0100 +@@ -0,0 +1,106 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++/* ++ * Author: Flippy ++ */ ++ ++/ { ++ cpu_opp_table_0: opp-table-0 { ++ compatible = "operating-points-v2"; ++ opp-shared; ++ ++ opp-1000000000 { ++ opp-hz = /bits/ 64 <1000000000>; ++ opp-microvolt = <731000>; ++ }; ++ ++ opp-1200000000 { ++ opp-hz = /bits/ 64 <1200000000>; ++ opp-microvolt = <731000>; ++ }; ++ ++ opp-1398000000 { ++ opp-hz = /bits/ 64 <1398000000>; ++ opp-microvolt = <761000>; ++ }; ++ ++ opp-1512000000 { ++ opp-hz = /bits/ 64 <1512000000>; ++ opp-microvolt = <791000>; ++ }; ++ ++ opp-1608000000 { ++ opp-hz = /bits/ 64 <1608000000>; ++ opp-microvolt = <831000>; ++ }; ++ ++ opp-1704000000 { ++ opp-hz = /bits/ 64 <1704000000>; ++ opp-microvolt = <861000>; ++ }; ++ ++ opp-1800000000 { ++ opp-hz = /bits/ 64 <1800000000>; ++ opp-microvolt = <981000>; ++ }; ++ ++ opp-1908000000 { ++ opp-hz = /bits/ 64 <1908000000>; ++ opp-microvolt = <1001000>; ++ }; ++ ++ opp-1992000000 { ++ opp-hz = /bits/ 64 <1992000000>; ++ opp-microvolt = <1021000>; ++ }; ++ }; ++ ++ cpub_opp_table_1: opp-table-1 { ++ compatible = "operating-points-v2"; ++ opp-shared; ++ ++ opp-1000000000 { ++ opp-hz = /bits/ 64 <1000000000>; ++ opp-microvolt = <771000>; ++ }; ++ ++ opp-1200000000 { ++ opp-hz = /bits/ 64 <1200000000>; ++ opp-microvolt = <771000>; ++ }; ++ ++ opp-1398000000 { ++ opp-hz = /bits/ 64 <1398000000>; ++ opp-microvolt = <791000>; ++ }; ++ ++ opp-1512000000 { ++ opp-hz = /bits/ 64 <1512000000>; ++ opp-microvolt = <821000>; ++ }; ++ ++ opp-1608000000 { ++ opp-hz = /bits/ 64 <1608000000>; ++ opp-microvolt = <861000>; ++ }; ++ ++ opp-1704000000 { ++ opp-hz = /bits/ 64 <1704000000>; ++ opp-microvolt = <891000>; ++ }; ++ ++ opp-1800000000 { ++ opp-hz = /bits/ 64 <1800000000>; ++ opp-microvolt = <981000>; ++ }; ++ ++ opp-1908000000 { ++ opp-hz = /bits/ 64 <1908000000>; ++ opp-microvolt = <1001000>; ++ }; ++ ++ opp-1992000000 { ++ opp-hz = /bits/ 64 <1992000000>; ++ opp-microvolt = <1021000>; ++ }; ++ }; ++}; +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-g12b-ugoos-am6-plus.dts mod/arch/arm64/boot/dts/amlogic/meson-g12b-ugoos-am6-plus.dts +--- main/arch/arm64/boot/dts/amlogic/meson-g12b-ugoos-am6-plus.dts 1970-01-01 01:00:00.000000000 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-g12b-ugoos-am6-plus.dts 2023-03-07 09:42:03.729550412 +0100 +@@ -0,0 +1,221 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++/* ++ * Copyright (c) 2019 BayLibre, SAS ++ * Author: Neil Armstrong ++ * Copyright (c) 2019 Christian Hewitt ++ */ ++ ++/dts-v1/; ++ ++#include "meson-g12b-w400.dtsi" ++#include ++ ++/ { ++ compatible = "ugoos,am6-plus", "amlogic,s922x", "amlogic,g12b"; ++ model = "Ugoos AM6 Plus"; ++ ++ aliases { ++ rtc0 = &rtc; ++ rtc1 = &vrtc; ++ }; ++ ++ gpio-keys-polled { ++ compatible = "gpio-keys-polled"; ++ poll-interval = <100>; ++ ++ power-button { ++ label = "power"; ++ linux,code = ; ++ gpios = <&gpio_ao GPIOAO_6 GPIO_ACTIVE_HIGH>; ++ }; ++ }; ++ ++ leds { ++ compatible = "gpio-leds"; ++ ++ led-green { ++ label = "power:green"; ++ gpios = <&gpio_ao GPIOAO_7 GPIO_ACTIVE_HIGH>; ++ default-state = "on"; ++ }; ++ }; ++ ++ spdif_dit: audio-codec-1 { ++ #sound-dai-cells = <0>; ++ compatible = "linux,spdif-dit"; ++ status = "okay"; ++ sound-name-prefix = "DIT"; ++ }; ++ ++ sound { ++ compatible = "amlogic,axg-sound-card"; ++ model = "AM6-PLUS"; ++ audio-aux-devs = <&tdmout_b>; ++ audio-routing = "TDMOUT_B IN 0", "FRDDR_A OUT 1", ++ "TDMOUT_B IN 1", "FRDDR_B OUT 1", ++ "TDMOUT_B IN 2", "FRDDR_C OUT 1", ++ "TDM_B Playback", "TDMOUT_B OUT", ++ "SPDIFOUT IN 0", "FRDDR_A OUT 3", ++ "SPDIFOUT IN 1", "FRDDR_B OUT 3", ++ "SPDIFOUT IN 2", "FRDDR_C OUT 3"; ++ ++ assigned-clocks = <&clkc CLKID_MPLL2>, ++ <&clkc CLKID_MPLL0>, ++ <&clkc CLKID_MPLL1>; ++ assigned-clock-parents = <0>, <0>, <0>; ++ assigned-clock-rates = <294912000>, ++ <270950400>, ++ <393216000>; ++ status = "okay"; ++ ++ dai-link-0 { ++ sound-dai = <&frddr_a>; ++ }; ++ ++ dai-link-1 { ++ sound-dai = <&frddr_b>; ++ }; ++ ++ dai-link-2 { ++ sound-dai = <&frddr_c>; ++ }; ++ ++ /* 8ch hdmi interface */ ++ dai-link-3 { ++ sound-dai = <&tdmif_b>; ++ dai-format = "i2s"; ++ dai-tdm-slot-tx-mask-0 = <1 1>; ++ dai-tdm-slot-tx-mask-1 = <1 1>; ++ dai-tdm-slot-tx-mask-2 = <1 1>; ++ dai-tdm-slot-tx-mask-3 = <1 1>; ++ mclk-fs = <256>; ++ ++ codec { ++ sound-dai = <&tohdmitx TOHDMITX_I2S_IN_B>; ++ }; ++ }; ++ ++ /* spdif hdmi or toslink interface */ ++ dai-link-4 { ++ sound-dai = <&spdifout>; ++ ++ codec-0 { ++ sound-dai = <&spdif_dit>; ++ }; ++ ++ codec-1 { ++ sound-dai = <&tohdmitx TOHDMITX_SPDIF_IN_A>; ++ }; ++ }; ++ ++ /* spdif hdmi interface */ ++ dai-link-5 { ++ sound-dai = <&spdifout_b>; ++ ++ codec { ++ sound-dai = <&tohdmitx TOHDMITX_SPDIF_IN_B>; ++ }; ++ }; ++ ++ /* hdmi glue */ ++ dai-link-6 { ++ sound-dai = <&tohdmitx TOHDMITX_I2S_OUT>; ++ ++ codec { ++ sound-dai = <&hdmi_tx>; ++ }; ++ }; ++ }; ++}; ++ ++&arb { ++ status = "okay"; ++}; ++ ++&clkc_audio { ++ status = "okay"; ++}; ++ ++&frddr_a { ++ status = "okay"; ++}; ++ ++&frddr_b { ++ status = "okay"; ++}; ++ ++&frddr_c { ++ status = "okay"; ++}; ++ ++&ir { ++ linux,rc-map-name = "rc-khadas"; ++}; ++ ++&i2c3 { ++ status = "okay"; ++ pinctrl-0 = <&i2c3_sda_a_pins>, <&i2c3_sck_a_pins>; ++ pinctrl-names = "default"; ++ ++ rtc: rtc@51 { ++ compatible = "haoyu,hym8563"; ++ reg = <0x51>; ++ }; ++}; ++ ++&spdifout { ++ pinctrl-0 = <&spdif_out_h_pins>; ++ pinctrl-names = "default"; ++ status = "okay"; ++}; ++ ++&spdifout_b { ++ status = "okay"; ++}; ++ ++&tdmif_b { ++ status = "okay"; ++}; ++ ++&tdmout_b { ++ status = "okay"; ++}; ++ ++&tohdmitx { ++ status = "okay"; ++}; ++ ++&uart_A { ++ status = "okay"; ++ pinctrl-0 = <&uart_a_pins>, <&uart_a_cts_rts_pins>; ++ pinctrl-names = "default"; ++ uart-has-rtscts; ++ ++ bluetooth { ++ compatible = "brcm,bcm43438-bt"; ++ shutdown-gpios = <&gpio GPIOX_17 GPIO_ACTIVE_HIGH>; ++ max-speed = <2000000>; ++ clocks = <&wifi32k>; ++ clock-names = "lpo"; ++ }; ++}; ++ ++&uart_AO { ++ status = "okay"; ++ pinctrl-0 = <&uart_ao_a_pins>; ++ pinctrl-names = "default"; ++}; ++ ++&usb { ++ status = "okay"; ++ dr_mode = "host"; ++ vbus-supply = <&usb_pwr_en>; ++}; ++ ++&usb2_phy0 { ++ phy-supply = <&usb1_pow>; ++}; ++ ++&usb2_phy1 { ++ phy-supply = <&usb1_pow>; ++}; +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi mod/arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi +--- main/arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi 2023-03-07 09:42:01.965536733 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi 2023-03-07 09:42:03.365547592 +0100 +@@ -18,9 +18,9 @@ + #size-cells = <2>; + + aliases { +- mmc0 = &sd_emmc_b; /* SD card */ +- mmc1 = &sd_emmc_c; /* eMMC */ +- mmc2 = &sd_emmc_a; /* SDIO */ ++ mmc0 = &sd_emmc_a; /* SDIO */ ++ mmc1 = &sd_emmc_b; /* SD card */ ++ mmc2 = &sd_emmc_c; /* eMMC */ + }; + + chosen { +@@ -2318,7 +2318,7 @@ + sd_emmc_a: sd@ffe03000 { + compatible = "amlogic,meson-axg-mmc"; + reg = <0x0 0xffe03000 0x0 0x800>; +- interrupts = ; ++ interrupts = ; + status = "disabled"; + clocks = <&clkc CLKID_SD_EMMC_A>, + <&clkc CLKID_SD_EMMC_A_CLK0>, +@@ -2330,7 +2330,7 @@ + sd_emmc_b: sd@ffe05000 { + compatible = "amlogic,meson-axg-mmc"; + reg = <0x0 0xffe05000 0x0 0x800>; +- interrupts = ; ++ interrupts = ; + status = "disabled"; + clocks = <&clkc CLKID_SD_EMMC_B>, + <&clkc CLKID_SD_EMMC_B_CLK0>, +@@ -2342,7 +2342,7 @@ + sd_emmc_c: mmc@ffe07000 { + compatible = "amlogic,meson-axg-mmc"; + reg = <0x0 0xffe07000 0x0 0x800>; +- interrupts = ; ++ interrupts = ; + status = "disabled"; + clocks = <&clkc CLKID_SD_EMMC_C>, + <&clkc CLKID_SD_EMMC_C_CLK0>, +@@ -2484,4 +2484,13 @@ + #clock-cells = <0>; + }; + ++ npu: npu@ff100000 { ++ compatible = "vivante,gc"; ++ reg = <0x0 0xff100000 0x0 0x20000>; ++ interrupts = <0 147 4>; ++ clocks = <&clkc CLKID_NNA_CORE_CLK>, ++ <&clkc CLKID_NNA_AXI_CLK>; ++ clock-names = "core", "bus"; ++ resets = <&reset RESET_NNA>; ++ }; + }; +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-gxbb-beelink-mini-mx.dts mod/arch/arm64/boot/dts/amlogic/meson-gxbb-beelink-mini-mx.dts +--- main/arch/arm64/boot/dts/amlogic/meson-gxbb-beelink-mini-mx.dts 1970-01-01 01:00:00.000000000 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-gxbb-beelink-mini-mx.dts 2023-03-07 09:42:03.809551034 +0100 +@@ -0,0 +1,21 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++/* ++ * meson-gxbb-beelink-mini-mx.dts ++ * Copyright (c) 2022 unifreq ++ */ ++ ++/dts-v1/; ++ ++#include "meson-gxbb-vega-s95.dtsi" ++ ++/ { ++ compatible = "azw,mini-mx", "amlogic,meson-gxbb"; ++ model = "Beelink Mini MX"; ++}; ++ ++ðmac { ++ ++ amlogic,tx-delay-ns = <4>; ++ ++}; ++ +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-gxbb-beelink-mini-mxiii.dts mod/arch/arm64/boot/dts/amlogic/meson-gxbb-beelink-mini-mxiii.dts +--- main/arch/arm64/boot/dts/amlogic/meson-gxbb-beelink-mini-mxiii.dts 1970-01-01 01:00:00.000000000 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-gxbb-beelink-mini-mxiii.dts 2023-03-07 09:42:03.821551126 +0100 +@@ -0,0 +1,172 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++/* ++ * Copyright (c) 2021 Christian Hewitt ++ */ ++ ++/dts-v1/; ++ ++#include "meson-gxbb-p20x.dtsi" ++#include ++#include ++#include ++#include ++ ++/ { ++ compatible = "beelink,mini-mxiii", "amlogic,meson-gxbb"; ++ model = "Beelink Mini MXIII"; ++ ++ spdif_dit: audio-codec-0 { ++ #sound-dai-cells = <0>; ++ compatible = "linux,spdif-dit"; ++ status = "okay"; ++ sound-name-prefix = "DIT"; ++ }; ++ ++ leds { ++ compatible = "gpio-leds"; ++ ++ led-power { ++ /* Red in Standby */ ++ color = ; ++ function = LED_FUNCTION_POWER; ++ gpios = <&gpio_ao GPIOAO_13 GPIO_ACTIVE_HIGH>; ++ default-state = "on"; ++ }; ++ }; ++ ++ gpio-keys-polled { ++ compatible = "gpio-keys-polled"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ poll-interval = <20>; ++ ++ button-reset { ++ label = "reset"; ++ linux,code = ; ++ gpios = <&gpio_ao GPIOAO_3 GPIO_ACTIVE_HIGH>; ++ }; ++ }; ++ ++ avdd18_usb_adc: regulator-avdd18_usb_adc { ++ compatible = "regulator-fixed"; ++ regulator-name = "AVDD18_USB_ADC"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ }; ++ ++ sound { ++ compatible = "amlogic,gx-sound-card"; ++ model = "MINI-MXIII"; ++ assigned-clocks = <&clkc CLKID_MPLL0>, ++ <&clkc CLKID_MPLL1>, ++ <&clkc CLKID_MPLL2>; ++ assigned-clock-parents = <0>, <0>, <0>; ++ assigned-clock-rates = <294912000>, ++ <270950400>, ++ <393216000>; ++ status = "okay"; ++ ++ dai-link-0 { ++ sound-dai = <&aiu AIU_CPU CPU_I2S_FIFO>; ++ }; ++ ++ dai-link-1 { ++ sound-dai = <&aiu AIU_CPU CPU_SPDIF_FIFO>; ++ }; ++ ++ dai-link-2 { ++ sound-dai = <&aiu AIU_CPU CPU_I2S_ENCODER>; ++ dai-format = "i2s"; ++ mclk-fs = <256>; ++ ++ codec-0 { ++ sound-dai = <&aiu AIU_HDMI CTRL_I2S>; ++ }; ++ }; ++ ++ dai-link-3 { ++ sound-dai = <&aiu AIU_CPU CPU_SPDIF_ENCODER>; ++ ++ codec-0 { ++ sound-dai = <&spdif_dit>; ++ }; ++ }; ++ ++ dai-link-4 { ++ sound-dai = <&aiu AIU_HDMI CTRL_OUT>; ++ ++ codec-0 { ++ sound-dai = <&hdmi_tx>; ++ }; ++ }; ++ }; ++}; ++ ++&aiu { ++ status = "okay"; ++ pinctrl-0 = <&spdif_out_y_pins>; ++ pinctrl-names = "default"; ++}; ++ ++ðmac { ++ status = "okay"; ++ pinctrl-0 = <ð_rgmii_pins>; ++ pinctrl-names = "default"; ++ ++ phy-handle = <ð_phy0>; ++ phy-mode = "rgmii"; ++ ++ amlogic,tx-delay-ns = <2>; ++ ++ mdio { ++ compatible = "snps,dwmac-mdio"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ eth_phy0: ethernet-phy@0 { ++ /* Realtek RTL8211F (0x001cc916) */ ++ reg = <0>; ++ ++ reset-assert-us = <10000>; ++ reset-deassert-us = <80000>; ++ reset-gpios = <&gpio GPIOZ_14 GPIO_ACTIVE_LOW>; ++ ++ interrupt-parent = <&gpio_intc>; ++ /* MAC_INTR on GPIOZ_15 */ ++ interrupts = <29 IRQ_TYPE_LEVEL_LOW>; ++ }; ++ }; ++}; ++ ++&ir { ++ linux,rc-map-name = "rc-beelink-mxiii"; ++}; ++ ++&saradc { ++ status = "okay"; ++ vref-supply = <&avdd18_usb_adc>; ++}; ++ ++/* Realtek Wireless SDIO Module */ ++&sd_emmc_a { ++ /delete-node/ brcmf; ++ ++ rtl8723bs: wifi@1 { ++ reg = <1>; ++ compatible = "realtek,rtl8723bs"; ++ }; ++}; ++ ++/* Connected to the Bluetooth module */ ++&uart_A { ++ status = "okay"; ++ pinctrl-0 = <&uart_a_pins>, <&uart_a_cts_rts_pins>; ++ pinctrl-names = "default"; ++ uart-has-rtscts; ++ ++ bluetooth { ++ compatible = "realtek,rtl8723bs-bt"; ++ enable-gpios = <&gpio GPIOX_20 GPIO_ACTIVE_HIGH>; ++ host-wake-gpios = <&gpio GPIOX_21 GPIO_ACTIVE_HIGH>; ++ }; ++}; +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-gxbb-mecool-kii-pro.dts mod/arch/arm64/boot/dts/amlogic/meson-gxbb-mecool-kii-pro.dts +--- main/arch/arm64/boot/dts/amlogic/meson-gxbb-mecool-kii-pro.dts 1970-01-01 01:00:00.000000000 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-gxbb-mecool-kii-pro.dts 2023-03-07 09:42:03.877551561 +0100 +@@ -0,0 +1,34 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++ ++/* ++ * Author: Christian Hewitt ++ */ ++ ++#include "meson-gxbb-p201.dts" ++ ++/ { ++ compatible = "videostrong,gxbb-kii-pro", "amlogic,meson-gxbb"; ++ model = "MeCool KII Pro"; ++ ++ clock: meson_clock { ++ compatible = "amlogic, gxbb-clock"; ++ reg = <0x0 0xc883c000 0x0 0x1000>, ++ <0x0 0xc8100000 0x0 0x1000>; ++ #clock-cells = <1>; ++ #reset-cells = <1>; ++ sys_max = <1536000000>; ++ }; ++ ++ memory@0 { ++ device_type = "memory"; ++ reg = <0x0 0x0 0x0 0x40000000>; ++ }; ++}; ++ ++&ir { ++ linux,rc-map-name = "rc-mecool-kii-pro"; ++}; ++ ++&usb_pwr { ++ gpio = <>; ++}; +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-gxbb-mecool-ki-plus.dts mod/arch/arm64/boot/dts/amlogic/meson-gxbb-mecool-ki-plus.dts +--- main/arch/arm64/boot/dts/amlogic/meson-gxbb-mecool-ki-plus.dts 1970-01-01 01:00:00.000000000 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-gxbb-mecool-ki-plus.dts 2023-03-07 09:42:03.853551374 +0100 +@@ -0,0 +1,34 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++ ++/* ++ * Author: Christian Hewitt ++ */ ++ ++#include "meson-gxbb-p201.dts" ++ ++/ { ++ compatible = "videostrong,gxbb-ki-plus", "amlogic,meson-gxbb"; ++ model = "MeCool KI Plus"; ++ ++ clock: meson_clock { ++ compatible = "amlogic, gxbb-clock"; ++ reg = <0x0 0xc883c000 0x0 0x1000>, ++ <0x0 0xc8100000 0x0 0x1000>; ++ #clock-cells = <1>; ++ #reset-cells = <1>; ++ sys_max = <1536000000>; ++ }; ++ ++ memory@0 { ++ device_type = "memory"; ++ reg = <0x0 0x0 0x0 0x40000000>; ++ }; ++}; ++ ++&ir { ++ linux,rc-map-name = "rc-mecool-ki-plus"; ++}; ++ ++&usb_pwr { ++ gpio = <>; ++}; +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-gxbb-minix-neo-u1.dts mod/arch/arm64/boot/dts/amlogic/meson-gxbb-minix-neo-u1.dts +--- main/arch/arm64/boot/dts/amlogic/meson-gxbb-minix-neo-u1.dts 1970-01-01 01:00:00.000000000 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-gxbb-minix-neo-u1.dts 2023-03-07 09:42:03.885551621 +0100 +@@ -0,0 +1,190 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++/* ++ * Copyright (c) 2021 Christian Hewitt ++ */ ++ ++/dts-v1/; ++ ++#include "meson-gxbb-p20x.dtsi" ++#include ++#include ++#include ++#include ++ ++/ { ++ compatible = "minix,neo-u1", "amlogic,meson-gxbb"; ++ model = "Minix NEO U1"; ++ ++ aliases { ++ rtc0 = &rtc; ++ rtc1 = &vrtc; ++ }; ++ ++ spdif_dit: audio-codec-0 { ++ #sound-dai-cells = <0>; ++ compatible = "linux,spdif-dit"; ++ status = "okay"; ++ sound-name-prefix = "DIT"; ++ }; ++ ++ leds { ++ compatible = "gpio-leds"; ++ ++ led-status { ++ color = ; ++ function = LED_FUNCTION_STATUS; ++ gpios = <&gpio_ao GPIOAO_13 GPIO_ACTIVE_HIGH>; ++ default-state = "on"; ++ }; ++ }; ++ ++ gpio-keys-polled { ++ compatible = "gpio-keys-polled"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ poll-interval = <20>; ++ ++ button-reset { ++ label = "reset"; ++ linux,code = ; ++ gpios = <&gpio_ao GPIOAO_3 GPIO_ACTIVE_HIGH>; ++ }; ++ }; ++ ++ avdd18_usb_adc: regulator-avdd18_usb_adc { ++ compatible = "regulator-fixed"; ++ regulator-name = "AVDD18_USB_ADC"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ }; ++ ++ sound { ++ compatible = "amlogic,gx-sound-card"; ++ model = "MINIX-NEO"; ++ assigned-clocks = <&clkc CLKID_MPLL0>, ++ <&clkc CLKID_MPLL1>, ++ <&clkc CLKID_MPLL2>; ++ assigned-clock-parents = <0>, <0>, <0>; ++ assigned-clock-rates = <294912000>, ++ <270950400>, ++ <393216000>; ++ status = "okay"; ++ ++ dai-link-0 { ++ sound-dai = <&aiu AIU_CPU CPU_I2S_FIFO>; ++ }; ++ ++ dai-link-1 { ++ sound-dai = <&aiu AIU_CPU CPU_SPDIF_FIFO>; ++ }; ++ ++ dai-link-2 { ++ sound-dai = <&aiu AIU_CPU CPU_I2S_ENCODER>; ++ dai-format = "i2s"; ++ mclk-fs = <256>; ++ ++ codec-0 { ++ sound-dai = <&aiu AIU_HDMI CTRL_I2S>; ++ }; ++ }; ++ ++ dai-link-3 { ++ sound-dai = <&aiu AIU_CPU CPU_SPDIF_ENCODER>; ++ ++ codec-0 { ++ sound-dai = <&spdif_dit>; ++ }; ++ }; ++ ++ dai-link-4 { ++ sound-dai = <&aiu AIU_HDMI CTRL_OUT>; ++ ++ codec-0 { ++ sound-dai = <&hdmi_tx>; ++ }; ++ }; ++ }; ++}; ++ ++&aiu { ++ status = "okay"; ++ pinctrl-0 = <&spdif_out_y_pins>; ++ pinctrl-names = "default"; ++}; ++ ++ðmac { ++ status = "okay"; ++ pinctrl-0 = <ð_rgmii_pins>; ++ pinctrl-names = "default"; ++ ++ phy-handle = <ð_phy0>; ++ phy-mode = "rgmii"; ++ ++ amlogic,tx-delay-ns = <2>; ++ ++ mdio { ++ compatible = "snps,dwmac-mdio"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ eth_phy0: ethernet-phy@0 { ++ /* Realtek RTL8211F (0x001cc916) */ ++ reg = <0>; ++ ++ reset-assert-us = <10000>; ++ reset-deassert-us = <80000>; ++ reset-gpios = <&gpio GPIOZ_14 GPIO_ACTIVE_LOW>; ++ ++ interrupt-parent = <&gpio_intc>; ++ /* MAC_INTR on GPIOZ_15 */ ++ interrupts = <29 IRQ_TYPE_LEVEL_LOW>; ++ }; ++ }; ++}; ++ ++&ir { ++ linux,rc-map-name = "rc-minix-neo"; ++}; ++ ++&i2c_A { ++ status = "okay"; ++ pinctrl-0 = <&i2c_a_pins>; ++ pinctrl-names = "default"; ++}; ++ ++&i2c_B { ++ status = "okay"; ++ pinctrl-0 = <&i2c_b_pins>; ++ pinctrl-names = "default"; ++ ++ rtc: rtc@51 { ++ status = "okay"; ++ compatible = "haoyu,hym8563"; ++ reg = <0x51>; ++ #clock-cells = <0>; ++ clock-frequency = <32768>; ++ clock-output-names = "xin32k"; ++ wakeup-source; ++ }; ++}; ++ ++&saradc { ++ status = "okay"; ++ vref-supply = <&avdd18_usb_adc>; ++}; ++ ++/* This is connected to the Bluetooth module: */ ++&uart_A { ++ status = "okay"; ++ pinctrl-0 = <&uart_a_pins>, <&uart_a_cts_rts_pins>; ++ pinctrl-names = "default"; ++ uart-has-rtscts; ++ ++ bluetooth { ++ compatible = "bcm43438-bt"; ++ shutdown-gpios = <&gpio GPIOX_17 GPIO_ACTIVE_HIGH>; ++ max-speed = <2000000>; ++ clocks = <&wifi32k>; ++ clock-names = "lpo"; ++ }; ++}; +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-gxbb-mxq-pro-plus.dts mod/arch/arm64/boot/dts/amlogic/meson-gxbb-mxq-pro-plus.dts +--- main/arch/arm64/boot/dts/amlogic/meson-gxbb-mxq-pro-plus.dts 1970-01-01 01:00:00.000000000 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-gxbb-mxq-pro-plus.dts 2023-03-07 09:42:03.909551807 +0100 +@@ -0,0 +1,57 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++/* ++ * Copyright (c) 2021 Flippy ++ */ ++ ++/dts-v1/; ++ ++#include "meson-gxbb-vega-s95.dtsi" ++ ++/ { ++ compatible = "crocon,mxq-pro-plus", "amlogic,meson-gxbb"; ++ model = "MXQ Pro+ (S905)"; ++ ++ reserved-memory { ++ #address-cells = <2>; ++ #size-cells = <2>; ++ ranges; ++ ++ /* 32 MiB reserved for ARM Trusted Firmware (BL32) */ ++ secmon_reserved_bl32: secmon@5300000 { ++ reg = <0x0 0x05300000 0x0 0x2000000>; ++ no-map; ++ }; ++ ++ /* 2MiB reserved for ARM Trusted Firmware (BL31) */ ++ secmon: secmon { ++ reg = <0x0 0x10000000 0x0 0x200000>; ++ no-map; ++ }; ++ }; ++ ++ memory@0 { ++ device_type = "memory"; ++ /* ++ * The first 16MiB of the DDR memory zone ++ * is reserved to the Hardware ROM Firmware ++ */ ++ linux,usable-memory = <0x0 0x1000000 0x0 0x7f000000>; ++ }; ++}; ++ ++ðmac { ++ amlogic,tx-delay-ns = <4>; ++ snps,aal; ++ snps,txpbl = <0x8>; ++ snps,rxpbl = <0x8>; ++}; ++ ++/* ++ð_phy0 { ++ interrupts = <25 IRQ_TYPE_LEVEL_LOW>; ++}; ++*/ ++ ++&sd_emmc_c { ++ max-frequency = <200000000>; ++}; +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-gxbb-p200.dts mod/arch/arm64/boot/dts/amlogic/meson-gxbb-p200.dts +--- main/arch/arm64/boot/dts/amlogic/meson-gxbb-p200.dts 2023-03-07 09:42:02.257538996 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-gxbb-p200.dts 2023-03-07 09:42:03.965552241 +0100 +@@ -9,11 +9,19 @@ + + #include "meson-gxbb-p20x.dtsi" + #include ++#include + + / { + compatible = "amlogic,p200", "amlogic,meson-gxbb"; + model = "Amlogic Meson GXBB P200 Development Board"; + ++ spdif_dit: audio-codec-0 { ++ #sound-dai-cells = <0>; ++ compatible = "linux,spdif-dit"; ++ status = "okay"; ++ sound-name-prefix = "DIT"; ++ }; ++ + avdd18_usb_adc: regulator-avdd18_usb_adc { + compatible = "regulator-fixed"; + regulator-name = "AVDD18_USB_ADC"; +@@ -57,6 +65,59 @@ + press-threshold-microvolt = <0>; /* 0% */ + }; + }; ++ ++ sound { ++ compatible = "amlogic,gx-sound-card"; ++ model = "P200"; ++ assigned-clocks = <&clkc CLKID_MPLL0>, ++ <&clkc CLKID_MPLL1>, ++ <&clkc CLKID_MPLL2>; ++ assigned-clock-parents = <0>, <0>, <0>; ++ assigned-clock-rates = <294912000>, ++ <270950400>, ++ <393216000>; ++ status = "okay"; ++ ++ dai-link-0 { ++ sound-dai = <&aiu AIU_CPU CPU_I2S_FIFO>; ++ }; ++ ++ dai-link-1 { ++ sound-dai = <&aiu AIU_CPU CPU_SPDIF_FIFO>; ++ }; ++ ++ dai-link-2 { ++ sound-dai = <&aiu AIU_CPU CPU_I2S_ENCODER>; ++ dai-format = "i2s"; ++ mclk-fs = <256>; ++ ++ codec-0 { ++ sound-dai = <&aiu AIU_HDMI CTRL_I2S>; ++ }; ++ }; ++ ++ dai-link-3 { ++ sound-dai = <&aiu AIU_CPU CPU_SPDIF_ENCODER>; ++ ++ codec-0 { ++ sound-dai = <&spdif_dit>; ++ }; ++ }; ++ ++ dai-link-4 { ++ sound-dai = <&aiu AIU_HDMI CTRL_OUT>; ++ ++ codec-0 { ++ sound-dai = <&hdmi_tx>; ++ }; ++ }; ++ }; ++}; ++ ++&aiu { ++ status = "okay"; ++ pinctrl-0 = <&spdif_out_y_pins>; ++ pinctrl-names = "default"; + }; + + ðmac { +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-gxbb-p201.dts mod/arch/arm64/boot/dts/amlogic/meson-gxbb-p201.dts +--- main/arch/arm64/boot/dts/amlogic/meson-gxbb-p201.dts 2023-03-07 09:42:02.269539090 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-gxbb-p201.dts 2023-03-07 09:42:03.973552303 +0100 +@@ -8,10 +8,50 @@ + /dts-v1/; + + #include "meson-gxbb-p20x.dtsi" ++#include + + / { + compatible = "amlogic,p201", "amlogic,meson-gxbb"; + model = "Amlogic Meson GXBB P201 Development Board"; ++ ++ sound { ++ compatible = "amlogic,gx-sound-card"; ++ model = "P201"; ++ assigned-clocks = <&clkc CLKID_MPLL0>, ++ <&clkc CLKID_MPLL1>, ++ <&clkc CLKID_MPLL2>; ++ assigned-clock-parents = <0>, <0>, <0>; ++ assigned-clock-rates = <294912000>, ++ <270950400>, ++ <393216000>; ++ status = "okay"; ++ ++ dai-link-0 { ++ sound-dai = <&aiu AIU_CPU CPU_I2S_FIFO>; ++ }; ++ ++ dai-link-1 { ++ sound-dai = <&aiu AIU_CPU CPU_I2S_ENCODER>; ++ dai-format = "i2s"; ++ mclk-fs = <256>; ++ ++ codec-0 { ++ sound-dai = <&aiu AIU_HDMI CTRL_I2S>; ++ }; ++ }; ++ ++ dai-link-2 { ++ sound-dai = <&aiu AIU_HDMI CTRL_OUT>; ++ ++ codec-0 { ++ sound-dai = <&hdmi_tx>; ++ }; ++ }; ++ }; ++}; ++ ++&aiu { ++ status = "okay"; + }; + + ðmac { +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-gxbb-wetek.dtsi mod/arch/arm64/boot/dts/amlogic/meson-gxbb-wetek.dtsi +--- main/arch/arm64/boot/dts/amlogic/meson-gxbb-wetek.dtsi 2023-03-07 09:42:02.369539865 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-gxbb-wetek.dtsi 2023-03-07 09:42:04.073553077 +0100 +@@ -71,6 +71,13 @@ + regulator-always-on; + }; + ++ vcc_5v: regulator-vcc_5v { ++ compatible = "regulator-fixed"; ++ regulator-name = "VCC_5V"; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ }; ++ + vcc_3v3: regulator-vcc_3v3 { + compatible = "regulator-fixed"; + regulator-name = "VCC_3V3"; +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-gxbb-wetek-hub.dts mod/arch/arm64/boot/dts/amlogic/meson-gxbb-wetek-hub.dts +--- main/arch/arm64/boot/dts/amlogic/meson-gxbb-wetek-hub.dts 2023-03-07 09:42:02.349539710 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-gxbb-wetek-hub.dts 2023-03-07 09:42:04.045552861 +0100 +@@ -13,6 +13,10 @@ + compatible = "wetek,hub", "amlogic,meson-gxbb"; + model = "WeTek Hub"; + ++ cvbs-connector { ++ status = "disabled"; ++ }; ++ + sound { + compatible = "amlogic,gx-sound-card"; + model = "WETEK-HUB"; +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-gxbb-wetek-play2.dts mod/arch/arm64/boot/dts/amlogic/meson-gxbb-wetek-play2.dts +--- main/arch/arm64/boot/dts/amlogic/meson-gxbb-wetek-play2.dts 2023-03-07 09:42:02.357539772 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-gxbb-wetek-play2.dts 2023-03-07 09:42:04.061552986 +0100 +@@ -21,6 +21,13 @@ + sound-name-prefix = "DIT"; + }; + ++ i2s_codec: audio-codec-1 { ++ #sound-dai-cells = <0>; ++ compatible = "everest,es7134"; ++ VDD-supply = <&vcc_5v>; ++ status = "okay"; ++ }; ++ + leds { + led-wifi { + label = "wetek-play:wifi-status"; +@@ -74,6 +81,10 @@ + codec-0 { + sound-dai = <&aiu AIU_HDMI CTRL_I2S>; + }; ++ ++ codec-1 { ++ sound-dai = <&i2s_codec>; ++ }; + }; + + dai-link-3 { +@@ -96,7 +107,9 @@ + + &aiu { + status = "okay"; +- pinctrl-0 = <&spdif_out_y_pins>; ++ pinctrl-0 = <&i2s_am_clk_pins>, <&i2s_out_ao_clk_pins>, ++ <&i2s_out_lr_clk_pins>, <&i2s_out_ch01_ao_pins>, ++ <&spdif_out_y_pins>; + pinctrl-names = "default"; + }; + +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-gx.dtsi mod/arch/arm64/boot/dts/amlogic/meson-gx.dtsi +--- main/arch/arm64/boot/dts/amlogic/meson-gx.dtsi 2023-03-07 09:42:02.205538594 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-gx.dtsi 2023-03-07 09:42:03.801550972 +0100 +@@ -21,9 +21,9 @@ + #size-cells = <2>; + + aliases { +- mmc0 = &sd_emmc_b; /* SD card */ +- mmc1 = &sd_emmc_c; /* eMMC */ +- mmc2 = &sd_emmc_a; /* SDIO */ ++ mmc0 = &sd_emmc_a; /* SDIO */ ++ mmc1 = &sd_emmc_b; /* SD card */ ++ mmc2 = &sd_emmc_c; /* eMMC */ + }; + + reserved-memory { +@@ -137,7 +137,7 @@ + + thermal-zones { + cpu-thermal { +- polling-delay-passive = <250>; /* milliseconds */ ++ polling-delay-passive = <800>; /* milliseconds */ + polling-delay = <1000>; /* milliseconds */ + + thermal-sensors = <&scpi_sensors 0>; +@@ -221,6 +221,10 @@ + }; + }; + ++ system-suspend { ++ compatible = "amlogic,meson-gx-pm"; ++ }; ++ + efuse: efuse { + compatible = "amlogic,meson-gx-efuse", "amlogic,meson-gxbb-efuse"; + #address-cells = <1>; +@@ -459,6 +463,11 @@ + }; + }; + ++ vrtc: rtc@a8 { ++ compatible = "amlogic,meson-vrtc"; ++ reg = <0x0 0x000a8 0x0 0x4>; ++ }; ++ + cec_AO: cec@100 { + compatible = "amlogic,meson-gx-ao-cec"; + reg = <0x0 0x00100 0x0 0x14>; +@@ -602,21 +611,21 @@ + sd_emmc_a: mmc@70000 { + compatible = "amlogic,meson-gx-mmc", "amlogic,meson-gxbb-mmc"; + reg = <0x0 0x70000 0x0 0x800>; +- interrupts = ; ++ interrupts = ; + status = "disabled"; + }; + + sd_emmc_b: mmc@72000 { + compatible = "amlogic,meson-gx-mmc", "amlogic,meson-gxbb-mmc"; + reg = <0x0 0x72000 0x0 0x800>; +- interrupts = ; ++ interrupts = ; + status = "disabled"; + }; + + sd_emmc_c: mmc@74000 { + compatible = "amlogic,meson-gx-mmc", "amlogic,meson-gxbb-mmc"; + reg = <0x0 0x74000 0x0 0x800>; +- interrupts = ; ++ interrupts = ; + status = "disabled"; + }; + }; +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi mod/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi +--- main/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi 2023-03-07 09:42:02.633541913 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi 2023-03-07 09:42:04.633557415 +0100 +@@ -134,6 +134,8 @@ + <&clkc CLKID_MPLL2>, + <&clkc CLKID_FCLK_DIV2>; + clock-names = "stmmaceth", "clkin0", "clkin1", "timing-adjustment"; ++ resets = <&reset RESET_ETHERNET>; ++ reset-names = "stmmaceth"; + + mdio0: mdio { + #address-cells = <1>; +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-gxl-s905d-mecool-kii-pro.dts mod/arch/arm64/boot/dts/amlogic/meson-gxl-s905d-mecool-kii-pro.dts +--- main/arch/arm64/boot/dts/amlogic/meson-gxl-s905d-mecool-kii-pro.dts 2023-03-07 09:42:02.437540394 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-gxl-s905d-mecool-kii-pro.dts 2023-03-07 09:42:04.165553791 +0100 +@@ -30,6 +30,8 @@ + + gpio-keys-polled { + compatible = "gpio-keys-polled"; ++ #address-cells = <1>; ++ #size-cells = <0>; + poll-interval = <100>; + + button { +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-gxl-s905d-mecool-ki-plus.dts mod/arch/arm64/boot/dts/amlogic/meson-gxl-s905d-mecool-ki-plus.dts +--- main/arch/arm64/boot/dts/amlogic/meson-gxl-s905d-mecool-ki-plus.dts 1970-01-01 01:00:00.000000000 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-gxl-s905d-mecool-ki-plus.dts 2023-03-07 09:42:04.145553635 +0100 +@@ -0,0 +1,21 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++ ++/* ++ * Author: Christian Hewitt ++ */ ++ ++#include "meson-gxl-s905d-p231.dts" ++ ++/ { ++ compatible = "videostrong,gxl-ki-plus", "amlogic,s905d", "amlogic,meson-gxl"; ++ model = "MeCool KI Plus"; ++ ++ memory@0 { ++ device_type = "memory"; ++ reg = <0x0 0x0 0x0 0x40000000>; ++ }; ++}; ++ ++&ir { ++ linux,rc-map-name = "rc-mecool-ki-plus"; ++}; +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-gxl-s905d-mecool-ki-pro.dts mod/arch/arm64/boot/dts/amlogic/meson-gxl-s905d-mecool-ki-pro.dts +--- main/arch/arm64/boot/dts/amlogic/meson-gxl-s905d-mecool-ki-pro.dts 1970-01-01 01:00:00.000000000 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-gxl-s905d-mecool-ki-pro.dts 2023-03-07 09:42:04.153553697 +0100 +@@ -0,0 +1,16 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++ ++/* ++ * Author: Christian Hewitt ++ */ ++ ++#include "meson-gxl-s905d-p230.dts" ++ ++/ { ++ compatible = "videostrong,gxl-ki-pro", "amlogic,s905d", "amlogic,meson-gxl"; ++ model = "MeCool KI Pro"; ++}; ++ ++&ir { ++ linux,rc-map-name = "rc-mecool-ki-pro"; ++}; +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-gxl-s905d-mecool-m8s-plus.dts mod/arch/arm64/boot/dts/amlogic/meson-gxl-s905d-mecool-m8s-plus.dts +--- main/arch/arm64/boot/dts/amlogic/meson-gxl-s905d-mecool-m8s-plus.dts 1970-01-01 01:00:00.000000000 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-gxl-s905d-mecool-m8s-plus.dts 2023-03-07 09:42:04.173553853 +0100 +@@ -0,0 +1,16 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++ ++/* ++ * Author: Christian Hewitt ++ */ ++ ++#include "meson-gxl-s905d-p231.dts" ++ ++/ { ++ compatible = "videostrong,gxl-kii-pro", "amlogic,s905d", "amlogic,meson-gxl"; ++ model = "MeCool M8S Plus"; ++}; ++ ++&ir { ++ linux,rc-map-name = "rc-mecool-m8s-plus"; ++}; +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-gxl-s905d-p230.dts mod/arch/arm64/boot/dts/amlogic/meson-gxl-s905d-p230.dts +--- main/arch/arm64/boot/dts/amlogic/meson-gxl-s905d-p230.dts 2023-03-07 09:42:02.449540485 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-gxl-s905d-p230.dts 2023-03-07 09:42:04.185553946 +0100 +@@ -84,7 +84,7 @@ + reset-gpios = <&gpio GPIOZ_14 GPIO_ACTIVE_LOW>; + + interrupt-parent = <&gpio_intc>; +- interrupts = <29 IRQ_TYPE_LEVEL_LOW>; ++ interrupts = <25 IRQ_TYPE_LEVEL_LOW>; + eee-broken-1000t; + }; + }; +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-gxl-s905d-phicomm-n1.dts mod/arch/arm64/boot/dts/amlogic/meson-gxl-s905d-phicomm-n1.dts +--- main/arch/arm64/boot/dts/amlogic/meson-gxl-s905d-phicomm-n1.dts 2023-03-07 09:42:02.473540674 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-gxl-s905d-phicomm-n1.dts 2023-03-07 09:42:04.217554194 +0100 +@@ -24,6 +24,25 @@ + default-state = "on"; + }; + }; ++ ++ dc_in: regulator-vcc_12v { ++ compatible = "regulator-fixed"; ++ regulator-name = "VCC_12V"; ++ regulator-min-microvolt = <12000000>; ++ regulator-max-microvolt = <12000000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ vddgpu: regulator-vddgpu { ++ compatible = "regulator-fixed"; ++ regulator-name = "mali"; ++ regulator-min-microvolt = <950000>; ++ regulator-max-microvolt = <950000>; ++ vin-supply = <&dc_in>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; + }; + + &cvbs_vdac_port { +@@ -33,3 +52,34 @@ + &usb { + dr_mode = "host"; + }; ++ ++&sd_emmc_a { ++ /delete-property/ sd-uhs-sdr104; ++ sd-uhs-sdr50; ++ max-frequency = <100000000>; ++}; ++ ++&sd_emmc_b { ++ status = "disabled"; ++}; ++ ++ðmac { ++ snps,aal; ++ snps,txpbl = <0x8>; ++ snps,rxpbl = <0x8>; ++}; ++ ++&uart_A { ++ status = "okay"; ++ pinctrl-0 = <&uart_a_pins>, <&uart_a_cts_rts_pins>; ++ pinctrl-names = "default"; ++ uart-has-rtscts; ++ ++ bluetooth { ++ compatible = "brcm,bcm43438-bt"; ++ shutdown-gpios = <&gpio GPIOX_17 GPIO_ACTIVE_HIGH>; ++ max-speed = <2000000>; ++ clocks = <&wifi32k>; ++ clock-names = "lpo"; ++ }; ++}; +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-gxl-s905d-phicomm-n1-thresh.dts mod/arch/arm64/boot/dts/amlogic/meson-gxl-s905d-phicomm-n1-thresh.dts +--- main/arch/arm64/boot/dts/amlogic/meson-gxl-s905d-phicomm-n1-thresh.dts 1970-01-01 01:00:00.000000000 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-gxl-s905d-phicomm-n1-thresh.dts 2023-03-07 09:42:04.209554132 +0100 +@@ -0,0 +1,13 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++/* ++ * Copyright (c) 2018 He Yangxuan ++ * Copyright (c) 2020 Flippy ++ */ ++ ++/dts-v1/; ++ ++#include "meson-gxl-s905d-phicomm-n1.dts" ++ ++ðmac { ++ snps,force_thresh_dma_mode; ++}; +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-gxl-s905l2-ipbs9505.dts mod/arch/arm64/boot/dts/amlogic/meson-gxl-s905l2-ipbs9505.dts +--- main/arch/arm64/boot/dts/amlogic/meson-gxl-s905l2-ipbs9505.dts 1970-01-01 01:00:00.000000000 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-gxl-s905l2-ipbs9505.dts 2023-03-07 09:42:04.297554814 +0100 +@@ -0,0 +1,20 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++/* ++ * Copyright (c) 2016 Endless Computers, Inc. ++ * Author: Carlo Caione , flippy ++ */ ++ ++/dts-v1/; ++ ++#include "meson-gxl-s905l2-x7-5g.dts" ++ ++/ { ++ compatible = "amlogic,ipbs9505", "amlogic,s905l2", "amlogic,meson-gxl"; ++ model = "Wojia TV IPBS9505"; ++}; ++ ++/* eMMC */ ++// Reduce the frequency from 200000000 to 100000000 to solve the emmc usage problem ++&sd_emmc_c { ++ max-frequency = <100000000>; ++}; +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-gxl-s905l2-x7-5g.dts mod/arch/arm64/boot/dts/amlogic/meson-gxl-s905l2-x7-5g.dts +--- main/arch/arm64/boot/dts/amlogic/meson-gxl-s905l2-x7-5g.dts 1970-01-01 01:00:00.000000000 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-gxl-s905l2-x7-5g.dts 2023-03-07 09:42:04.337555122 +0100 +@@ -0,0 +1,29 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++/* ++ * Copyright (c) 2016 Endless Computers, Inc. ++ * Author: Carlo Caione ++ */ ++ ++/dts-v1/; ++ ++#include "meson-gxl-s905w-p281.dts" ++ ++/ { ++ compatible = "amlogic,x7-5g", "amlogic,s905l2", "amlogic,meson-gxl"; ++ model = "Amlogic Meson GXL (S905L2) X7 5G Tv Box"; ++}; ++ ++// the gpu in the S905L2 has one pp core less ++// (i.e. only two in total) than the one in the other S905X/W ++&mali { ++ interrupts = , ++ , ++ , ++ , ++ , ++ , ++ , ++ ; ++ interrupt-names = "gp", "gpmmu", "pp", "pmu", ++ "pp0", "ppmmu0", "pp1", "ppmmu1"; ++}; +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-gxl-s905l3b-e900v22e.dts mod/arch/arm64/boot/dts/amlogic/meson-gxl-s905l3b-e900v22e.dts +--- main/arch/arm64/boot/dts/amlogic/meson-gxl-s905l3b-e900v22e.dts 1970-01-01 01:00:00.000000000 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-gxl-s905l3b-e900v22e.dts 2023-03-07 09:42:04.317554969 +0100 +@@ -0,0 +1,21 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++/* ++ * Copyright (c) 2016 Endless Computers, Inc. ++ * Author: Carlo Caione ++ * Copyright (c) flippy ++ */ ++ ++/dts-v1/; ++ ++#include "meson-gxl-s905l2-x7-5g.dts" ++ ++/ { ++ compatible = "amlogic,s905l3b", "amlogic,meson-gxl"; ++ model = "Skyworth E900V22E"; ++}; ++ ++/* eMMC */ ++&sd_emmc_c { ++ status = "okay"; ++ max-frequency = <100000000>; ++}; +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-gxl-s905l3b-m302a.dts mod/arch/arm64/boot/dts/amlogic/meson-gxl-s905l3b-m302a.dts +--- main/arch/arm64/boot/dts/amlogic/meson-gxl-s905l3b-m302a.dts 1970-01-01 01:00:00.000000000 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-gxl-s905l3b-m302a.dts 2023-03-07 09:42:04.357555279 +0100 +@@ -0,0 +1,48 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++/* ++ * Copyright (c) 2016 Endless Computers, Inc. ++ * Author: Carlo Caione ++ */ ++ ++/dts-v1/; ++ ++#include "meson-gxl-s905w-p281.dts" ++ ++/ { ++ compatible = "amlogic,m302a", "amlogic,s905w", "amlogic,meson-gxl"; ++ model = "Amlogic Meson GXL (S905L3b) MBH-M302A Box"; ++ ++ memory@0 { ++ device_type = "memory"; ++ reg = <0x0 0x0 0x0 0x80000000>; ++ }; ++ ++}; ++ ++// the gpu in the S905L2 has one pp core less ++// (i.e. only two in total) than the one in the other S905X/W ++ ++&mali { ++ interrupts = , ++ , ++ , ++ , ++ , ++ , ++ , ++ ; ++ interrupt-names = "gp", "gpmmu", "pp", "pmu","pp0", "ppmmu0", "pp1", "ppmmu1"; ++}; ++ ++&sd_emmc_c { ++ status = "okay"; ++ bus-width = <8>; ++ cap-mmc-highspeed; ++ mmc-ddr-1_8v; ++ /delete-property/ mmc-hs200-1_8v; ++ max-frequency = <52000000>; ++}; ++ ++&internal_phy { ++ max-speed = <100>; ++}; +\ Kein Zeilenumbruch am Dateiende. +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-gxl-s905l-venz-v10.dts mod/arch/arm64/boot/dts/amlogic/meson-gxl-s905l-venz-v10.dts +--- main/arch/arm64/boot/dts/amlogic/meson-gxl-s905l-venz-v10.dts 1970-01-01 01:00:00.000000000 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-gxl-s905l-venz-v10.dts 2023-03-07 09:42:04.273554626 +0100 +@@ -0,0 +1,326 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++/* ++ * Copyright (c) 2016 Endless Computers, Inc. ++ * Author: Carlo Caione ++ */ ++ ++/dts-v1/; ++ ++#include "meson-gxl-s905x.dtsi" ++#include ++#include ++#include ++ ++/ { ++ compatible = "venz,v10", "amlogic,s905l", "amlogic,meson-gxl"; ++ model = "Venz V10"; ++ ++ aliases { ++ serial0 = &uart_AO; ++ ethernet0 = ðmac; ++ wlan0 = &rtl8189; ++ }; ++ ++ chosen { ++ stdout-path = "serial0:115200n8"; ++ }; ++ ++ memory@0 { ++ device_type = "memory"; ++ reg = <0x0 0x0 0x0 0x80000000>; ++ }; ++ ++ dio2133: analog-amplifier { ++ compatible = "simple-audio-amplifier"; ++ sound-name-prefix = "AU2"; ++ VCC-supply = <&hdmi_5v>; ++ enable-gpios = <&gpio GPIOH_5 GPIO_ACTIVE_HIGH>; ++ }; ++ ++ leds { ++ compatible = "gpio-leds"; ++ ++ led-standby { ++ color = ; ++ function = LED_FUNCTION_POWER; ++ gpios = <&gpio GPIODV_24 GPIO_ACTIVE_HIGH>; ++ default-state = "on"; ++ }; ++ }; ++ ++ cvbs-connector { ++ compatible = "composite-video-connector"; ++ ++ port { ++ cvbs_connector_in: endpoint { ++ remote-endpoint = <&cvbs_vdac_out>; ++ }; ++ }; ++ }; ++ ++ hdmi-connector { ++ compatible = "hdmi-connector"; ++ type = "a"; ++ ++ port { ++ hdmi_connector_in: endpoint { ++ remote-endpoint = <&hdmi_tx_tmds_out>; ++ }; ++ }; ++ }; ++ ++ hdmi_5v: regulator-hdmi-5v { ++ compatible = "regulator-fixed"; ++ ++ regulator-name = "HDMI_5V"; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ ++ gpio = <&gpio GPIOH_3 GPIO_ACTIVE_HIGH>; ++ enable-active-high; ++ regulator-always-on; ++ }; ++ ++ vddio_boot: regulator-vddio_boot { ++ compatible = "regulator-fixed"; ++ regulator-name = "VDDIO_BOOT"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ }; ++ ++ vddao_3v3: regulator-vddao_3v3 { ++ compatible = "regulator-fixed"; ++ regulator-name = "VDDAO_3V3"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ }; ++ ++ vddio_ao18: regulator-vddio_ao18 { ++ compatible = "regulator-fixed"; ++ regulator-name = "VDDIO_AO18"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ }; ++ ++ vcc_3v3: regulator-vcc_3v3 { ++ compatible = "regulator-fixed"; ++ regulator-name = "VCC_3V3"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ }; ++ ++ emmc_pwrseq: emmc-pwrseq { ++ compatible = "mmc-pwrseq-emmc"; ++ reset-gpios = <&gpio BOOT_9 GPIO_ACTIVE_LOW>; ++ }; ++ ++ wifi32k: wifi32k { ++ compatible = "pwm-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <32768>; ++ pwms = <&pwm_ef 0 30518 0>; /* PWM_E at 32.768KHz */ ++ }; ++ ++ sdio_pwrseq: sdio-pwrseq { ++ compatible = "mmc-pwrseq-simple"; ++ reset-gpios = <&gpio GPIOX_6 GPIO_ACTIVE_LOW>; ++ clocks = <&wifi32k>; ++ clock-names = "ext_clock"; ++ }; ++ ++ sound { ++ compatible = "amlogic,gx-sound-card"; ++ model = "VENZ-V10"; ++ audio-aux-devs = <&dio2133>; ++ audio-widgets = "Line", "Lineout"; ++ audio-routing = "AU2 INL", "ACODEC LOLN", ++ "AU2 INR", "ACODEC LORN", ++ "Lineout", "AU2 OUTL", ++ "Lineout", "AU2 OUTR"; ++ assigned-clocks = <&clkc CLKID_MPLL0>, ++ <&clkc CLKID_MPLL1>, ++ <&clkc CLKID_MPLL2>; ++ assigned-clock-parents = <0>, <0>, <0>; ++ assigned-clock-rates = <294912000>, ++ <270950400>, ++ <393216000>; ++ status = "okay"; ++ ++ dai-link-0 { ++ sound-dai = <&aiu AIU_CPU CPU_I2S_FIFO>; ++ }; ++ ++ dai-link-1 { ++ sound-dai = <&aiu AIU_CPU CPU_I2S_ENCODER>; ++ dai-format = "i2s"; ++ mclk-fs = <256>; ++ ++ codec-0 { ++ sound-dai = <&aiu AIU_HDMI CTRL_I2S>; ++ }; ++ ++ codec-1 { ++ sound-dai = <&aiu AIU_ACODEC CTRL_I2S>; ++ }; ++ }; ++ ++ dai-link-2 { ++ sound-dai = <&aiu AIU_HDMI CTRL_OUT>; ++ ++ codec-0 { ++ sound-dai = <&hdmi_tx>; ++ }; ++ }; ++ ++ dai-link-3 { ++ sound-dai = <&aiu AIU_ACODEC CTRL_OUT>; ++ ++ codec-0 { ++ sound-dai = <&acodec>; ++ }; ++ }; ++ }; ++}; ++ ++&acodec { ++ AVDD-supply = <&vddio_ao18>; ++ status = "okay"; ++}; ++ ++&aiu { ++ status = "okay"; ++}; ++ ++&cec_AO { ++ status = "okay"; ++ pinctrl-0 = <&ao_cec_pins>; ++ pinctrl-names = "default"; ++ hdmi-phandle = <&hdmi_tx>; ++}; ++ ++&cvbs_vdac_port { ++ cvbs_vdac_out: endpoint { ++ remote-endpoint = <&cvbs_connector_in>; ++ }; ++}; ++ ++ðmac { ++ status = "okay"; ++}; ++ ++&hdmi_tx { ++ status = "okay"; ++ pinctrl-0 = <&hdmi_hpd_pins>, <&hdmi_i2c_pins>; ++ pinctrl-names = "default"; ++ hdmi-supply = <&hdmi_5v>; ++}; ++ ++&hdmi_tx_tmds_port { ++ hdmi_tx_tmds_out: endpoint { ++ remote-endpoint = <&hdmi_connector_in>; ++ }; ++}; ++ ++&ir { ++ status = "okay"; ++ pinctrl-0 = <&remote_input_ao_pins>; ++ pinctrl-names = "default"; ++ linux,rc-map-name = "rc-venz-v10"; ++}; ++ ++&pwm_ef { ++ status = "okay"; ++ pinctrl-0 = <&pwm_e_pins>; ++ pinctrl-names = "default"; ++ clocks = <&clkc CLKID_FCLK_DIV4>; ++ clock-names = "clkin0"; ++}; ++ ++&saradc { ++ status = "okay"; ++ vref-supply = <&vddio_ao18>; ++}; ++ ++/* Wireless SDIO Module */ ++&sd_emmc_a { ++ status = "okay"; ++ pinctrl-0 = <&sdio_pins>; ++ pinctrl-1 = <&sdio_clk_gate_pins>; ++ pinctrl-names = "default", "clk-gate"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ bus-width = <4>; ++ cap-sd-highspeed; ++ max-frequency = <100000000>; ++ ++ non-removable; ++ disable-wp; ++ ++ /* WiFi firmware requires power to be kept while in suspend */ ++ keep-power-in-suspend; ++ ++ mmc-pwrseq = <&sdio_pwrseq>; ++ ++ vmmc-supply = <&vddao_3v3>; ++ vqmmc-supply = <&vddio_boot>; ++ ++ rtl8189: wifi@1 { ++ reg = <1>; ++ }; ++}; ++ ++/* SD card */ ++&sd_emmc_b { ++ status = "okay"; ++ pinctrl-0 = <&sdcard_pins>; ++ pinctrl-1 = <&sdcard_clk_gate_pins>; ++ pinctrl-names = "default", "clk-gate"; ++ ++ bus-width = <4>; ++ cap-sd-highspeed; ++ max-frequency = <50000000>; ++ disable-wp; ++ ++ cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_LOW>; ++ ++ vmmc-supply = <&vddao_3v3>; ++ vqmmc-supply = <&vddio_boot>; ++}; ++ ++/* eMMC */ ++&sd_emmc_c { ++ status = "okay"; ++ pinctrl-0 = <&emmc_pins>, <&emmc_ds_pins>; ++ pinctrl-1 = <&emmc_clk_gate_pins>; ++ pinctrl-names = "default", "clk-gate"; ++ ++ bus-width = <8>; ++ cap-mmc-highspeed; ++ max-frequency = <200000000>; ++ non-removable; ++ disable-wp; ++ mmc-ddr-1_8v; ++ mmc-hs200-1_8v; ++ ++ mmc-pwrseq = <&emmc_pwrseq>; ++ vmmc-supply = <&vcc_3v3>; ++ vqmmc-supply = <&vddio_boot>; ++}; ++ ++/* This UART is brought out to the DB9 connector */ ++&uart_AO { ++ status = "okay"; ++ pinctrl-0 = <&uart_ao_a_pins>; ++ pinctrl-names = "default"; ++}; ++ ++&usb { ++ status = "okay"; ++ dr_mode = "host"; ++}; ++ ++&usb2_phy0 { ++ /* HDMI_5V is the supply for the USB VBUS */ ++ phy-supply = <&hdmi_5v>; ++}; +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-gxl-s905w-mecool-m8s-pro-w.dts mod/arch/arm64/boot/dts/amlogic/meson-gxl-s905w-mecool-m8s-pro-w.dts +--- main/arch/arm64/boot/dts/amlogic/meson-gxl-s905w-mecool-m8s-pro-w.dts 1970-01-01 01:00:00.000000000 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-gxl-s905w-mecool-m8s-pro-w.dts 2023-03-07 09:42:04.377555432 +0100 +@@ -0,0 +1,30 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++/* ++ * Copyright (c) 2018 Martin Blumenstingl . ++ * Based on meson-gxl-s905d-p231.dts: ++ * - Copyright (c) 2016 Endless Computers, Inc. ++ * Author: Carlo Caione ++ */ ++ ++/dts-v1/; ++ ++#include "meson-gxl-s905x.dtsi" ++#include "meson-gx-p23x-q20x.dtsi" ++ ++/ { ++ compatible = "videostrong,gxl-m8s-pro-w", "amlogic,s905w", "amlogic,meson-gxl"; ++ model = "MeCool M8S Pro W"; ++ ++ memory@0 { ++ device_type = "memory"; ++ reg = <0x0 0x0 0x0 0x80000000>; ++ }; ++}; ++ ++&ir { ++ linux,rc-map-name = "rc-mecool-m8s-pro-w"; ++}; ++ ++&usb { ++ dr_mode = "host"; ++}; +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-gxl-s905w-tx3-mini.dts mod/arch/arm64/boot/dts/amlogic/meson-gxl-s905w-tx3-mini.dts +--- main/arch/arm64/boot/dts/amlogic/meson-gxl-s905w-tx3-mini.dts 2023-03-07 09:42:02.537541169 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-gxl-s905w-tx3-mini.dts 2023-03-07 09:42:04.405555650 +0100 +@@ -10,6 +10,7 @@ + + #include "meson-gxl-s905x.dtsi" + #include "meson-gx-p23x-q20x.dtsi" ++#include + + / { + compatible = "oranth,tx3-mini", "amlogic,s905w", "amlogic,meson-gxl"; +@@ -19,6 +20,70 @@ + device_type = "memory"; + reg = <0x0 0x0 0x0 0x40000000>; /* 1 GiB or 2 GiB */ + }; ++ ++ spi { ++ compatible = "spi-gpio"; ++ sck-gpios = <&gpio GPIODV_27 GPIO_ACTIVE_HIGH>; ++ mosi-gpios = <&gpio GPIODV_26 GPIO_ACTIVE_HIGH>; ++ cs-gpios = <&gpio_ao GPIOAO_4 GPIO_ACTIVE_LOW>; ++ num-chipselects = <1>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ tm1628: led-controller@0 { ++ compatible = "titanmec,tm1628"; ++ reg = <0>; ++ spi-3wire; ++ spi-lsb-first; ++ spi-rx-delay-us = <1>; ++ spi-max-frequency = <500000>; ++ #address-cells = <2>; ++ #size-cells = <0>; ++ ++ titanmec,segment-mapping = /bits/ 8 <4 5 6 1 2 3 7>; ++ titanmec,grid = /bits/ 8 <4 3 2 1>; ++ ++ alarm@5,1 { ++ reg = <5 1>; ++ function = LED_FUNCTION_ALARM; ++ }; ++ ++ usb@5,2 { ++ reg = <5 2>; ++ function = LED_FUNCTION_USB; ++ }; ++ play@5,3 { ++ reg = <5 3>; ++ function = "play"; ++ }; ++ ++ pause@5,4 { ++ reg = <5 4>; ++ function = "pause"; ++ }; ++ ++ colon@5,5 { ++ reg = <5 5>; ++ function = "colon"; ++ }; ++ ++ lan@5,6 { ++ reg = <5 6>; ++ function = LED_FUNCTION_LAN; ++ }; ++ ++ wlan@5,7 { ++ reg = <5 7>; ++ function = LED_FUNCTION_WLAN; ++ }; ++ }; ++ }; ++ ++ openvfd { ++ compatible = "open,vfd"; ++ dev_name = "openvfd"; ++ status = "okay"; ++ }; + }; + + &ir { +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-gxl-s905w-x96-mini.dts mod/arch/arm64/boot/dts/amlogic/meson-gxl-s905w-x96-mini.dts +--- main/arch/arm64/boot/dts/amlogic/meson-gxl-s905w-x96-mini.dts 1970-01-01 01:00:00.000000000 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-gxl-s905w-x96-mini.dts 2023-03-07 09:42:04.433555867 +0100 +@@ -0,0 +1,22 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++/* ++ * Copyright (c) 2018 Martin Blumenstingl . ++ * Based on meson-gxl-s905d-p231.dts: ++ * - Copyright (c) 2016 Endless Computers, Inc. ++ * Author: Carlo Caione ++ * github.com/TThanhXuan, github.com/box-automation1, github.com/unifreq ++ */ ++ ++/dts-v1/; ++ ++#include "meson-gxl-s905w-p281.dts" ++ ++/ { ++ compatible = "amlogic,p281", "amlogic,s905w", "amlogic,meson-gxl"; ++ model = "X96 mini"; ++}; ++ ++/* eMMC */ ++&sd_emmc_c { ++ max-frequency = <50000000>; ++}; +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-gxl-s905w-x96w.dts mod/arch/arm64/boot/dts/amlogic/meson-gxl-s905w-x96w.dts +--- main/arch/arm64/boot/dts/amlogic/meson-gxl-s905w-x96w.dts 1970-01-01 01:00:00.000000000 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-gxl-s905w-x96w.dts 2023-03-07 09:42:04.453556020 +0100 +@@ -0,0 +1,83 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++/* ++ * Copyright (c) 2018 Martin Blumenstingl . ++ * Based on meson-gxl-s905d-p231.dts: ++ * - Copyright (c) 2016 Endless Computers, Inc. ++ * - Copyright (c) unifreq ++ */ ++ ++/dts-v1/; ++ ++#include "meson-gxl-s905w-p281.dts" ++ ++/ { ++ compatible = "amlogic,p281", "amlogic,s905w", "amlogic,meson-gxl"; ++ model = "X96W"; ++ ++ aliases { ++ serial0 = &uart_AO; /* Console */ ++ serial1 = &uart_A; /* Bluetooth */ ++ ethernet0 = ðmac; ++ }; ++}; ++ ++/* SDIO wifi: AP6255 */ ++&sd_emmc_a { ++ status = "okay"; ++ ++ brcmf: wifi@1 { ++ reg = <1>; ++ compatible = "brcm,bcm4329-fmac"; ++ }; ++}; ++ ++/* SD card */ ++&sd_emmc_b { ++ status = "okay"; ++ bus-width = <4>; ++ cap-sd-highspeed; ++ max-frequency = <50000000>; ++}; ++ ++/* eMMC */ ++&sd_emmc_c { ++ status = "okay"; ++ max-frequency = <50000000>; ++}; ++ ++/* Console UART */ ++&uart_AO { ++ status = "okay"; ++ pinctrl-0 = <&uart_ao_a_pins>; ++ pinctrl-names = "default"; ++}; ++ ++/* S905W only has access to its internal PHY */ ++ðmac { ++ status = "okay"; ++ phy-mode = "rmii"; ++ phy-handle = <&internal_phy>; ++}; ++ ++&internal_phy { ++ status = "okay"; ++ pinctrl-0 = <ð_link_led_pins>, <ð_act_led_pins>; ++ pinctrl-names = "default"; ++ max-speed = <100>; ++}; ++ ++/* This is connected to the Bluetooth module: AP6255 */ ++&uart_A { ++ status = "okay"; ++ pinctrl-0 = <&uart_a_pins>, <&uart_a_cts_rts_pins>; ++ pinctrl-names = "default"; ++ uart-has-rtscts; ++ ++ bluetooth { ++ compatible = "brcm,bcm4345c5"; ++ shutdown-gpios = <&gpio GPIOX_17 GPIO_ACTIVE_HIGH>; ++ max-speed = <2000000>; ++ clocks = <&wifi32k>; ++ clock-names = "lpo"; ++ }; ++}; +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-b860h.dts mod/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-b860h.dts +--- main/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-b860h.dts 1970-01-01 01:00:00.000000000 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-b860h.dts 2023-03-07 09:42:04.453556020 +0100 +@@ -0,0 +1,19 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++/* ++ * Copyright (c) 2016 Endless Computers, Inc. ++ * Author: Carlo Caione ++ */ ++ ++/dts-v1/; ++ ++#include "meson-gxl-s905x-p212.dts" ++ ++/ { ++ compatible = "zte,b860h", "amlogic,p212"; ++ model = "ZTE B860H"; ++ ++}; ++ ++&sdio_pwrseq { ++ reset-gpios = <&gpio GPIODV_27 GPIO_ACTIVE_LOW>; ++}; +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-khadas-vim.dts mod/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-khadas-vim.dts +--- main/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-khadas-vim.dts 2023-03-07 09:42:02.557541324 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-khadas-vim.dts 2023-03-07 09:42:04.505556425 +0100 +@@ -29,6 +29,8 @@ + aliases { + serial2 = &uart_AO_B; + ethernet0 = ðmac; ++ rtc0 = &rtc; ++ rtc1 = &vrtc; + }; + + gpio-keys-polled { +@@ -217,25 +219,6 @@ + pinctrl-0 = <&pwm_e_pins>, <&pwm_f_clk_pins>; + }; + +-&sd_emmc_a { +- max-frequency = <100000000>; +- +- brcmf: wifi@1 { +- reg = <1>; +- compatible = "brcm,bcm4329-fmac"; +- }; +-}; +- +-&uart_A { +- bluetooth { +- compatible = "brcm,bcm43438-bt"; +- shutdown-gpios = <&gpio GPIOX_17 GPIO_ACTIVE_HIGH>; +- max-speed = <2000000>; +- clocks = <&wifi32k>; +- clock-names = "lpo"; +- }; +-}; +- + /* This is brought out on the Linux_RX (18) and Linux_TX (19) pins: */ + &uart_AO { + status = "okay"; +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-p212.dts mod/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-p212.dts +--- main/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-p212.dts 2023-03-07 09:42:02.597541636 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-p212.dts 2023-03-07 09:42:04.573556952 +0100 +@@ -7,11 +7,19 @@ + /dts-v1/; + + #include "meson-gxl-s905x-p212.dtsi" ++#include + + / { + compatible = "amlogic,p212", "amlogic,s905x", "amlogic,meson-gxl"; + model = "Amlogic Meson GXL (S905X) P212 Development Board"; + ++ dio2133: analog-amplifier { ++ compatible = "simple-audio-amplifier"; ++ sound-name-prefix = "AU2"; ++ VCC-supply = <&hdmi_5v>; ++ enable-gpios = <&gpio GPIOH_5 GPIO_ACTIVE_HIGH>; ++ }; ++ + cvbs-connector { + compatible = "composite-video-connector"; + +@@ -32,6 +40,68 @@ + }; + }; + }; ++ ++ sound { ++ compatible = "amlogic,gx-sound-card"; ++ model = "S905X-P212"; ++ audio-aux-devs = <&dio2133>; ++ audio-widgets = "Line", "Lineout"; ++ audio-routing = "AU2 INL", "ACODEC LOLN", ++ "AU2 INR", "ACODEC LORN", ++ "Lineout", "AU2 OUTL", ++ "Lineout", "AU2 OUTR"; ++ assigned-clocks = <&clkc CLKID_MPLL0>, ++ <&clkc CLKID_MPLL1>, ++ <&clkc CLKID_MPLL2>; ++ assigned-clock-parents = <0>, <0>, <0>; ++ assigned-clock-rates = <294912000>, ++ <270950400>, ++ <393216000>; ++ status = "okay"; ++ ++ dai-link-0 { ++ sound-dai = <&aiu AIU_CPU CPU_I2S_FIFO>; ++ }; ++ ++ dai-link-1 { ++ sound-dai = <&aiu AIU_CPU CPU_I2S_ENCODER>; ++ dai-format = "i2s"; ++ mclk-fs = <256>; ++ ++ codec-0 { ++ sound-dai = <&aiu AIU_HDMI CTRL_I2S>; ++ }; ++ ++ codec-1 { ++ sound-dai = <&aiu AIU_ACODEC CTRL_I2S>; ++ }; ++ }; ++ ++ dai-link-2 { ++ sound-dai = <&aiu AIU_HDMI CTRL_OUT>; ++ ++ codec-0 { ++ sound-dai = <&hdmi_tx>; ++ }; ++ }; ++ ++ dai-link-3 { ++ sound-dai = <&aiu AIU_ACODEC CTRL_OUT>; ++ ++ codec-0 { ++ sound-dai = <&acodec>; ++ }; ++ }; ++ }; ++}; ++ ++&acodec { ++ AVDD-supply = <&vddio_ao18>; ++ status = "okay"; ++}; ++ ++&aiu { ++ status = "okay"; + }; + + &cec_AO { +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-p212.dtsi mod/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-p212.dtsi +--- main/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-p212.dtsi 2023-03-07 09:42:02.609541728 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-p212.dtsi 2023-03-07 09:42:04.593557105 +0100 +@@ -113,7 +113,11 @@ + + bus-width = <4>; + cap-sd-highspeed; +- max-frequency = <50000000>; ++ sd-uhs-sdr12; ++ sd-uhs-sdr25; ++ sd-uhs-sdr50; ++ sd-uhs-sdr104; ++ max-frequency = <100000000>; + + non-removable; + disable-wp; +@@ -125,6 +129,11 @@ + + vmmc-supply = <&vddao_3v3>; + vqmmc-supply = <&vddio_boot>; ++ ++ brcmf: wifi@1 { ++ reg = <1>; ++ compatible = "brcm,bcm4329-fmac"; ++ }; + }; + + /* SD card */ +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-tbee.dts mod/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-tbee.dts +--- main/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-tbee.dts 1970-01-01 01:00:00.000000000 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-tbee.dts 2023-03-07 09:42:04.601557167 +0100 +@@ -0,0 +1,153 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++/* ++ * Copyright (c) 2016 Endless Computers, Inc. ++ * Author: Carlo Caione ++ */ ++ ++/dts-v1/; ++ ++#include "meson-gxl-s905x-p212.dtsi" ++#include ++ ++/ { ++ compatible = "tbee,box", "amlogic,s905x", "amlogic,meson-gxl"; ++ model = "TBee-Box"; ++ ++ dio2133: analog-amplifier { ++ compatible = "simple-audio-amplifier"; ++ sound-name-prefix = "AU2"; ++ VCC-supply = <&hdmi_5v>; ++ enable-gpios = <&gpio GPIOH_5 GPIO_ACTIVE_HIGH>; ++ }; ++ ++ cvbs-connector { ++ compatible = "composite-video-connector"; ++ ++ port { ++ cvbs_connector_in: endpoint { ++ remote-endpoint = <&cvbs_vdac_out>; ++ }; ++ }; ++ }; ++ ++ hdmi-connector { ++ compatible = "hdmi-connector"; ++ type = "a"; ++ ++ port { ++ hdmi_connector_in: endpoint { ++ remote-endpoint = <&hdmi_tx_tmds_out>; ++ }; ++ }; ++ }; ++ ++ sound { ++ compatible = "amlogic,gx-sound-card"; ++ model = "TBEE-BOX"; ++ audio-aux-devs = <&dio2133>; ++ audio-widgets = "Line", "Lineout"; ++ audio-routing = "AU2 INL", "ACODEC LOLN", ++ "AU2 INR", "ACODEC LORN", ++ "Lineout", "AU2 OUTL", ++ "Lineout", "AU2 OUTR"; ++ assigned-clocks = <&clkc CLKID_MPLL0>, ++ <&clkc CLKID_MPLL1>, ++ <&clkc CLKID_MPLL2>; ++ assigned-clock-parents = <0>, <0>, <0>; ++ assigned-clock-rates = <294912000>, ++ <270950400>, ++ <393216000>; ++ status = "okay"; ++ ++ dai-link-0 { ++ sound-dai = <&aiu AIU_CPU CPU_I2S_FIFO>; ++ }; ++ ++ dai-link-1 { ++ sound-dai = <&aiu AIU_CPU CPU_I2S_ENCODER>; ++ dai-format = "i2s"; ++ mclk-fs = <256>; ++ ++ codec-0 { ++ sound-dai = <&aiu AIU_HDMI CTRL_I2S>; ++ }; ++ ++ codec-1 { ++ sound-dai = <&aiu AIU_ACODEC CTRL_I2S>; ++ }; ++ }; ++ ++ dai-link-2 { ++ sound-dai = <&aiu AIU_HDMI CTRL_OUT>; ++ ++ codec-0 { ++ sound-dai = <&hdmi_tx>; ++ }; ++ }; ++ ++ dai-link-3 { ++ sound-dai = <&aiu AIU_ACODEC CTRL_OUT>; ++ ++ codec-0 { ++ sound-dai = <&acodec>; ++ }; ++ }; ++ }; ++}; ++ ++&acodec { ++ AVDD-supply = <&vddio_ao18>; ++ status = "okay"; ++}; ++ ++&aiu { ++ status = "okay"; ++}; ++ ++&cec_AO { ++ status = "okay"; ++ pinctrl-0 = <&ao_cec_pins>; ++ pinctrl-names = "default"; ++ hdmi-phandle = <&hdmi_tx>; ++}; ++ ++&cvbs_vdac_port { ++ cvbs_vdac_out: endpoint { ++ remote-endpoint = <&cvbs_connector_in>; ++ }; ++}; ++ ++&hdmi_tx { ++ status = "okay"; ++ pinctrl-0 = <&hdmi_hpd_pins>, <&hdmi_i2c_pins>; ++ pinctrl-names = "default"; ++ hdmi-supply = <&hdmi_5v>; ++}; ++ ++&hdmi_tx_tmds_port { ++ hdmi_tx_tmds_out: endpoint { ++ remote-endpoint = <&hdmi_connector_in>; ++ }; ++}; ++ ++/* This is connected to the Bluetooth module: */ ++&uart_A { ++ status = "okay"; ++ pinctrl-0 = <&uart_a_pins>, <&uart_a_cts_rts_pins>; ++ pinctrl-names = "default"; ++ uart-has-rtscts; ++ ++ bluetooth { ++ compatible = "qcom,qca9377-bt"; ++ enable-gpios = <&gpio GPIOX_17 GPIO_ACTIVE_HIGH>; ++ max-speed = <2000000>; ++ clocks = <&wifi32k>; ++ clock-names = "lpo"; ++ }; ++}; ++ ++/* This UART is brought out to the DB9 connector */ ++&uart_AO { ++ status = "okay"; ++}; ++ +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-vero4k.dts mod/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-vero4k.dts +--- main/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-vero4k.dts 1970-01-01 01:00:00.000000000 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-vero4k.dts 2023-03-07 09:42:04.609557229 +0100 +@@ -0,0 +1,180 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++/* ++ * Author: Christian Hewitt ++ */ ++ ++/dts-v1/; ++ ++#include "meson-gxl-s905x-p212.dtsi" ++#include ++#include ++#include ++ ++/ { ++ compatible = "osmc,vero4k", "amlogic,s905x", "amlogic,meson-gxl"; ++ model = "OSMC Vero 4K"; ++ ++ reserved-memory { ++ /* 32 MiB reserved for ARM Trusted Firmware (BL32) */ ++ secmon_reserved_bl32: secmon@5300000 { ++ reg = <0x0 0x05300000 0x0 0x2000000>; ++ no-map; ++ }; ++ }; ++ ++ gpio-keys-polled { ++ compatible = "gpio-keys-polled"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ poll-interval = <20>; ++ ++ button@0 { ++ label = "power"; ++ linux,code = ; ++ gpios = <&gpio_ao GPIOAO_2 GPIO_ACTIVE_HIGH>; ++ }; ++ }; ++ ++ leds { ++ compatible = "gpio-leds"; ++ ++ led-standby { ++ color = ; ++ function = LED_FUNCTION_POWER; ++ gpios = <&gpio GPIODV_24 GPIO_ACTIVE_LOW>; ++ default-state = "off"; ++ panic-indicator; ++ }; ++ }; ++ ++ dio2133: analog-amplifier { ++ compatible = "simple-audio-amplifier"; ++ sound-name-prefix = "AU2"; ++ VCC-supply = <&hdmi_5v>; ++ enable-gpios = <&gpio GPIOH_5 GPIO_ACTIVE_HIGH>; ++ }; ++ ++ cvbs-connector { ++ compatible = "composite-video-connector"; ++ ++ port { ++ cvbs_connector_in: endpoint { ++ remote-endpoint = <&cvbs_vdac_out>; ++ }; ++ }; ++ }; ++ ++ hdmi-connector { ++ compatible = "hdmi-connector"; ++ type = "a"; ++ ++ port { ++ hdmi_connector_in: endpoint { ++ remote-endpoint = <&hdmi_tx_tmds_out>; ++ }; ++ }; ++ }; ++ ++ sound { ++ compatible = "amlogic,gx-sound-card"; ++ model = "VERO4K"; ++ audio-aux-devs = <&dio2133>; ++ audio-widgets = "Line", "Lineout"; ++ audio-routing = "AU2 INL", "ACODEC LOLN", ++ "AU2 INR", "ACODEC LORN", ++ "Lineout", "AU2 OUTL", ++ "Lineout", "AU2 OUTR"; ++ assigned-clocks = <&clkc CLKID_MPLL0>, ++ <&clkc CLKID_MPLL1>, ++ <&clkc CLKID_MPLL2>; ++ assigned-clock-parents = <0>, <0>, <0>; ++ assigned-clock-rates = <294912000>, ++ <270950400>, ++ <393216000>; ++ status = "okay"; ++ ++ dai-link-0 { ++ sound-dai = <&aiu AIU_CPU CPU_I2S_FIFO>; ++ }; ++ ++ dai-link-1 { ++ sound-dai = <&aiu AIU_CPU CPU_I2S_ENCODER>; ++ dai-format = "i2s"; ++ mclk-fs = <256>; ++ ++ codec-0 { ++ sound-dai = <&aiu AIU_HDMI CTRL_I2S>; ++ }; ++ ++ codec-1 { ++ sound-dai = <&aiu AIU_ACODEC CTRL_I2S>; ++ }; ++ }; ++ ++ dai-link-2 { ++ sound-dai = <&aiu AIU_HDMI CTRL_OUT>; ++ ++ codec-0 { ++ sound-dai = <&hdmi_tx>; ++ }; ++ }; ++ ++ dai-link-3 { ++ sound-dai = <&aiu AIU_ACODEC CTRL_OUT>; ++ ++ codec-0 { ++ sound-dai = <&acodec>; ++ }; ++ }; ++ }; ++}; ++ ++&acodec { ++ AVDD-supply = <&vddio_ao18>; ++ status = "okay"; ++}; ++ ++&aiu { ++ status = "okay"; ++}; ++ ++&cec_AO { ++ status = "okay"; ++ pinctrl-0 = <&ao_cec_pins>; ++ pinctrl-names = "default"; ++ hdmi-phandle = <&hdmi_tx>; ++}; ++ ++&cvbs_vdac_port { ++ cvbs_vdac_out: endpoint { ++ remote-endpoint = <&cvbs_connector_in>; ++ }; ++}; ++ ++ðmac { ++ phy-mode = "rmii"; ++ phy-handle = <&internal_phy>; ++}; ++ ++&hdmi_tx { ++ status = "okay"; ++ pinctrl-0 = <&hdmi_hpd_pins>, <&hdmi_i2c_pins>; ++ pinctrl-names = "default"; ++ hdmi-supply = <&hdmi_5v>; ++}; ++ ++&hdmi_tx_tmds_port { ++ hdmi_tx_tmds_out: endpoint { ++ remote-endpoint = <&hdmi_connector_in>; ++ }; ++}; ++ ++&internal_phy { ++ pinctrl-0 = <ð_link_led_pins>, <ð_act_led_pins>; ++ pinctrl-names = "default"; ++}; ++ ++/* This UART is brought out to the DB9 connector */ ++&uart_AO { ++ status = "okay"; ++}; +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-gxm-fake-octopus-planet.dts mod/arch/arm64/boot/dts/amlogic/meson-gxm-fake-octopus-planet.dts +--- main/arch/arm64/boot/dts/amlogic/meson-gxm-fake-octopus-planet.dts 1970-01-01 01:00:00.000000000 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-gxm-fake-octopus-planet.dts 2023-03-07 09:42:04.641557477 +0100 +@@ -0,0 +1,12 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++/* ++ * Copyright (c) 2022 Flippy ++ */ ++ ++/dts-v1/; ++ ++#include "meson-gxm-octopus-planet.dts" ++ ++/ { ++ model = "Fake Octopus Planet"; ++}; +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-gxm-gt1.dts mod/arch/arm64/boot/dts/amlogic/meson-gxm-gt1.dts +--- main/arch/arm64/boot/dts/amlogic/meson-gxm-gt1.dts 1970-01-01 01:00:00.000000000 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-gxm-gt1.dts 2023-03-07 09:42:04.661557633 +0100 +@@ -0,0 +1,91 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++/* ++ * Copyright (c) Christian Hewitt ++ */ ++ ++/dts-v1/; ++ ++#include "meson-gxm.dtsi" ++#include "meson-gx-p23x-q20x.dtsi" ++#include ++#include ++ ++/ { ++ compatible = "azw,gt1", "amlogic,s912", "amlogic,meson-gxm"; ++ model = "Beelink GT1"; ++ ++ leds { ++ compatible = "gpio-leds"; ++ ++ led-white { ++ color = ; ++ function = LED_FUNCTION_POWER; ++ gpios = <&gpio_ao GPIOAO_9 GPIO_ACTIVE_HIGH>; ++ default-state = "on"; ++ panic-indicator; ++ }; ++ }; ++ ++ adc-keys { ++ compatible = "adc-keys"; ++ io-channels = <&saradc 0>; ++ io-channel-names = "buttons"; ++ keyup-threshold-microvolt = <1710000>; ++ ++ button-function { ++ label = "update"; ++ linux,code = ; ++ press-threshold-microvolt = <10000>; ++ }; ++ }; ++}; ++ ++ðmac { ++ pinctrl-0 = <ð_pins>; ++ pinctrl-names = "default"; ++ phy-handle = <&external_phy>; ++ amlogic,tx-delay-ns = <2>; ++ phy-mode = "rgmii"; ++}; ++ ++&external_mdio { ++ external_phy: ethernet-phy@0 { ++ /* Realtek RTL8211F (0x001cc916) */ ++ reg = <0>; ++ max-speed = <1000>; ++ ++ reset-assert-us = <10000>; ++ reset-deassert-us = <80000>; ++ reset-gpios = <&gpio GPIOZ_14 GPIO_ACTIVE_LOW>; ++ ++ interrupt-parent = <&gpio_intc>; ++ /* MAC_INTR on GPIOZ_15 */ ++ interrupts = <25 IRQ_TYPE_LEVEL_LOW>; ++ }; ++}; ++ ++&ir { ++ linux,rc-map-name = "rc-beelink-gs1"; ++}; ++ ++&sd_emmc_a { ++ /* QCA9377 WiFi */ ++ wifi: wifi@1 { ++ reg = <1>; ++ }; ++}; ++ ++&uart_A { ++ status = "okay"; ++ pinctrl-0 = <&uart_a_pins>, <&uart_a_cts_rts_pins>; ++ pinctrl-names = "default"; ++ uart-has-rtscts; ++ ++ bluetooth { ++ compatible = "qcom,qca9377-bt"; ++ shutdown-gpios = <&gpio GPIOX_17 GPIO_ACTIVE_HIGH>; ++ max-speed = <2000000>; ++ clocks = <&wifi32k>; ++ clock-names = "lpo"; ++ }; ++}; +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-gxm-khadas-vim2.dts mod/arch/arm64/boot/dts/amlogic/meson-gxm-khadas-vim2.dts +--- main/arch/arm64/boot/dts/amlogic/meson-gxm-khadas-vim2.dts 2023-03-07 09:42:02.653542069 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-gxm-khadas-vim2.dts 2023-03-07 09:42:04.673557726 +0100 +@@ -18,6 +18,8 @@ + aliases { + serial0 = &uart_AO; + serial2 = &uart_AO_B; ++ rtc0 = &rtc; ++ rtc1 = &vrtc; + }; + + chosen { +@@ -52,10 +54,11 @@ + gpios = <&gpio GPIODV_14 GPIO_ACTIVE_HIGH + &gpio GPIODV_15 GPIO_ACTIVE_HIGH>; + /* Dummy RPM values since fan is optional */ +- gpio-fan,speed-map = <0 0 +- 1 1 +- 2 2 +- 3 3>; ++ gpio-fan,speed-map = ++ <0 0>, ++ <1 1>, ++ <2 2>, ++ <3 3>; + #cooling-cells = <2>; + }; + +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-gxm-minix-neo-u9h.dts mod/arch/arm64/boot/dts/amlogic/meson-gxm-minix-neo-u9h.dts +--- main/arch/arm64/boot/dts/amlogic/meson-gxm-minix-neo-u9h.dts 2023-03-07 09:42:02.677542255 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-gxm-minix-neo-u9h.dts 2023-03-07 09:42:04.689557850 +0100 +@@ -14,6 +14,11 @@ + compatible = "minix,neo-u9h", "amlogic,s912", "amlogic,meson-gxm"; + model = "Minix Neo U9-H"; + ++ aliases { ++ rtc0 = &rtc; ++ rtc1 = &vrtc; ++ }; ++ + leds { + compatible = "gpio-leds"; + +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-gxm-nexbox-a2.dts mod/arch/arm64/boot/dts/amlogic/meson-gxm-nexbox-a2.dts +--- main/arch/arm64/boot/dts/amlogic/meson-gxm-nexbox-a2.dts 1970-01-01 01:00:00.000000000 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-gxm-nexbox-a2.dts 2023-03-07 09:42:04.709558003 +0100 +@@ -0,0 +1,60 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++/* ++ * Copyright (c) 2022 by sibondt ++ */ ++ ++/dts-v1/; ++ ++#include "meson-gxm-q200.dts" ++ ++/ { ++ compatible = "nexbox,a2", "amlogic,s912", "amlogic,meson-gxm"; ++ model = "Nexbox a95x-a2"; ++}; ++ ++ðmac { ++ snps,aal; ++ snps,txpbl = <0x8>; ++ snps,rxpbl = <0x8>; ++}; ++ ++/* Wireless SDIO Module */ ++&sd_emmc_a { ++ status = "okay"; ++ pinctrl-0 = <&sdio_pins>; ++ pinctrl-1 = <&sdio_clk_gate_pins>; ++ pinctrl-names = "default", "clk-gate"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ bus-width = <4>; ++ cap-sd-highspeed; ++ sd-uhs-sdr25; ++ sd-uhs-sdr50; ++ sd-uhs-sdr104; ++ min-frequency = <400000>; ++ max-frequency = <199999997>; ++ ++ non-removable; ++ disable-wp; ++ ++ /* WiFi firmware requires power to be kept while in suspend */ ++ keep-power-in-suspend; ++ ++ mmc-pwrseq = <&sdio_pwrseq>; ++ ++ vmmc-supply = <&vddao_3v3>; ++ vqmmc-supply = <&vddio_boot>; ++}; ++ ++&sd_emmc_b { ++ status = "okay"; ++}; ++ ++&sd_emmc_c { ++ status = "okay"; ++}; ++ ++&uart_A { ++ status = "disabled"; ++}; +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-gxm-octopus-planet.dts mod/arch/arm64/boot/dts/amlogic/meson-gxm-octopus-planet.dts +--- main/arch/arm64/boot/dts/amlogic/meson-gxm-octopus-planet.dts 1970-01-01 01:00:00.000000000 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-gxm-octopus-planet.dts 2023-03-07 09:42:04.721558098 +0100 +@@ -0,0 +1,58 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++/* ++ * Copyright (c) 2020 Flippy ++ */ ++ ++/dts-v1/; ++ ++#include "meson-gxm-q200.dts" ++ ++/ { ++ model = "Octopus Planet"; ++ ++ leds { ++ compatible = "gpio-leds"; ++ ++ green_led { ++ label = "green"; ++ gpios = <&gpio_ao GPIOAO_5 GPIO_ACTIVE_HIGH>; ++ linux,default-trigger = "usb-host"; ++ }; ++ ++ blue_led { ++ label = "blue"; ++ gpios = <&gpio_ao GPIOAO_6 GPIO_ACTIVE_HIGH>; ++ //linux,default-trigger = "mdio_mux-0.2009087f:00:link"; ++ linux,default-trigger = "mmc2"; ++ }; ++ ++ red_led { ++ label = "red"; ++ gpios = <&gpio_ao GPIOAO_9 GPIO_ACTIVE_HIGH>; ++ default-state = "on"; ++ }; ++ ++ }; ++}; ++ ++ðmac { ++ snps,aal; ++ snps,txpbl = <0x8>; ++ snps,rxpbl = <0x8>; ++}; ++ ++&sd_emmc_a { ++ status = "disabled"; ++}; ++ ++&sd_emmc_b { ++ status = "okay"; ++}; ++ ++&sd_emmc_c { ++ status = "okay"; ++}; ++ ++&uart_A { ++ status = "disabled"; ++}; +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-gxm-phicomm-t1.dts mod/arch/arm64/boot/dts/amlogic/meson-gxm-phicomm-t1.dts +--- main/arch/arm64/boot/dts/amlogic/meson-gxm-phicomm-t1.dts 1970-01-01 01:00:00.000000000 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-gxm-phicomm-t1.dts 2023-03-07 09:42:04.733558190 +0100 +@@ -0,0 +1,32 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++/* ++ * Copyright (c) 2016 Endless Computers, Inc. ++ * Author: Carlo Caione ++ * Create by flippy ++ */ ++ ++/dts-v1/; ++ ++#include "meson-gxm-q201.dts" ++ ++/ { ++ compatible = "phicomm,t1", "amlogic,meson-gxm"; ++ model = "Phicomm T1"; ++ ++ aliases { ++ serial1 = &uart_A; ++ }; ++}; ++ ++&uart_A { ++ status = "okay"; ++ pinctrl-0 = <&uart_a_pins>, <&uart_a_cts_rts_pins>; ++ pinctrl-names = "default"; ++ uart-has-rtscts; ++ ++ bluetooth { ++ compatible = "brcm,bcm43438-bt"; ++ shutdown-gpios = <&gpio GPIOX_17 GPIO_ACTIVE_HIGH>; ++ max-speed = <2000000>; ++ }; ++}; +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-gxm-t95z-plus.dts mod/arch/arm64/boot/dts/amlogic/meson-gxm-t95z-plus.dts +--- main/arch/arm64/boot/dts/amlogic/meson-gxm-t95z-plus.dts 1970-01-01 01:00:00.000000000 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-gxm-t95z-plus.dts 2023-03-07 09:42:04.829558934 +0100 +@@ -0,0 +1,59 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++/* ++ * Copyright (c) 2016 Endless Computers, Inc. ++ * Author: Carlo Caione , flippy ++*/ ++ ++/dts-v1/; ++ ++#include "meson-gxm.dtsi" ++#include "meson-gx-p23x-q20x.dtsi" ++ ++/ { ++ compatible = "amlogic,q201", "amlogic,s912", "amlogic,meson-gxm"; ++ model = "T95Z Plus"; ++ ++ openvfd { ++ compatible = "open,vfd"; ++ dev_name = "openvfd"; ++ status = "okay"; ++ }; ++}; ++ ++ðmac { ++ phy-mode = "rgmii"; ++ pinctrl-0 = <ð_pins>; ++ pinctrl-names = "default"; ++ reg = <0x0 0xc9410000 0x0 0x10000 ++ 0x0 0xc8834540 0x0 0x8 ++ 0x0 0xc8834558 0x0 0xc>; ++ ++ /* Select external PHY by default */ ++ phy-handle = <&external_phy>; ++ ++ amlogic,tx-delay-ns = <2>; ++ ++ /* External PHY reset is shared with internal PHY Led signals */ ++ snps,reset-gpio = <&gpio GPIOZ_14 0>; ++ snps,reset-delays-us = <0 10000 1000000>; ++ snps,reset-active-low; ++}; ++ ++&external_mdio { ++ external_phy: ethernet-phy@0 { ++ /* T95Z Plus's phy has phy id = 0381:5c11 */ ++ compatible = "ethernet-phy-id0381.5c11", "ethernet-phy-ieee802.3-c22"; ++ /* T95Z Plus's phy has phy addr = 1 */ ++ reg = <1>; ++ max-speed = <1000>; ++ interrupt-parent = <&gpio_intc>; ++ interrupts = <25 IRQ_TYPE_LEVEL_LOW>; ++ }; ++}; ++ ++&sd_emmc_a { ++ brcmf: wifi@1 { ++ reg = <1>; ++ compatible = "brcm,bcm4329-fmac"; ++ }; ++}; +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-gxm-tx8-max.dts mod/arch/arm64/boot/dts/amlogic/meson-gxm-tx8-max.dts +--- main/arch/arm64/boot/dts/amlogic/meson-gxm-tx8-max.dts 1970-01-01 01:00:00.000000000 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-gxm-tx8-max.dts 2023-03-07 09:42:04.881559335 +0100 +@@ -0,0 +1,30 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++/* ++ * Copyright (c) 2022 flippy ++ */ ++ ++/dts-v1/; ++ ++#include "meson-gxm-nexbox-a2.dts" ++ ++/ { ++ compatible = "tanix,tx8", "amlogic,s912", "amlogic,meson-gxm"; ++ model = "Tanix TX8 Max"; ++ ++}; ++ ++/* This is connected to the Bluetooth module: */ ++&uart_A { ++ status = "okay"; ++ pinctrl-0 = <&uart_a_pins>, <&uart_a_cts_rts_pins>; ++ pinctrl-names = "default"; ++ uart-has-rtscts; ++ ++ bluetooth { ++ compatible = "qcom,qca9377-bt"; ++ enable-gpios = <&gpio GPIOX_17 GPIO_ACTIVE_HIGH>; ++ max-speed = <2000000>; ++ clocks = <&wifi32k>; ++ clock-names = "lpo"; ++ }; ++}; +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-gxm-tx9-pro.dts mod/arch/arm64/boot/dts/amlogic/meson-gxm-tx9-pro.dts +--- main/arch/arm64/boot/dts/amlogic/meson-gxm-tx9-pro.dts 1970-01-01 01:00:00.000000000 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-gxm-tx9-pro.dts 2023-03-07 09:42:04.877559303 +0100 +@@ -0,0 +1,52 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++/* ++ * Copyright (c) 2022 Flippy ++ */ ++ ++/dts-v1/; ++ ++#include "meson-gxm-q200.dts" ++ ++/ { ++ compatible = "tanix,tx9-pro", "amlogic,gxm"; ++ model = "Tanix TX9 Pro"; ++ ++ openvfd { ++ compatible = "open,vfd"; ++ dev_name = "openvfd"; ++ status = "okay"; ++ }; ++}; ++ ++ðmac { ++ snps,aal; ++ snps,txpbl = <0x8>; ++ snps,rxpbl = <0x8>; ++}; ++ ++&sd_emmc_a { ++ status = "okay"; ++}; ++ ++&sd_emmc_b { ++ status = "okay"; ++}; ++ ++&sd_emmc_c { ++ status = "okay"; ++}; ++ ++&uart_A { ++ status = "okay"; ++ pinctrl-0 = <&uart_a_pins>, <&uart_a_cts_rts_pins>; ++ pinctrl-names = "default"; ++ uart-has-rtscts; ++ ++ bluetooth { ++ compatible = "brcm,bcm43438-bt"; ++ shutdown-gpios = <&gpio GPIOX_17 GPIO_ACTIVE_HIGH>; ++ max-speed = <2000000>; ++ clocks = <&wifi32k>; ++ clock-names = "lpo"; ++ }; ++}; +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-gxm-x92.dts mod/arch/arm64/boot/dts/amlogic/meson-gxm-x92.dts +--- main/arch/arm64/boot/dts/amlogic/meson-gxm-x92.dts 1970-01-01 01:00:00.000000000 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-gxm-x92.dts 2023-03-07 09:42:04.981560110 +0100 +@@ -0,0 +1,55 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++/* ++ * Copyright (c) 2017 BayLibre, SAS. ++ * Author: Neil Armstrong ++ * Copyright (c) 2017 Oleg ++ * Copyright (c) flippy ++ */ ++ ++/dts-v1/; ++ ++#include "meson-gxm-vega-s96.dts" ++ ++/ { ++ compatible = "vontar,x92", "amlogic,s912", "amlogic,meson-gxm"; ++ model = "Vontar X92"; ++ ++ openvfd { ++ compatible = "open,vfd"; ++ dev_name = "openvfd"; ++ status = "okay"; ++ }; ++}; ++ ++ðmac { ++ snps,aal; ++ snps,txpbl = <0x8>; ++ snps,rxpbl = <0x8>; ++}; ++ ++&sd_emmc_a { ++ status = "okay"; ++}; ++ ++&sd_emmc_b { ++ status = "okay"; ++}; ++ ++&sd_emmc_c { ++ status = "okay"; ++}; ++ ++&uart_A { ++ status = "okay"; ++ pinctrl-0 = <&uart_a_pins>, <&uart_a_cts_rts_pins>; ++ pinctrl-names = "default"; ++ uart-has-rtscts; ++ ++ bluetooth { ++ compatible = "brcm,bcm43438-bt"; ++ shutdown-gpios = <&gpio GPIOX_17 GPIO_ACTIVE_HIGH>; ++ max-speed = <2000000>; ++ clocks = <&wifi32k>; ++ clock-names = "lpo"; ++ }; ++}; +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-gx-p23x-q20x.dtsi mod/arch/arm64/boot/dts/amlogic/meson-gx-p23x-q20x.dtsi +--- main/arch/arm64/boot/dts/amlogic/meson-gx-p23x-q20x.dtsi 2023-03-07 09:42:02.193538500 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-gx-p23x-q20x.dtsi 2023-03-07 09:42:03.789550878 +0100 +@@ -259,7 +259,11 @@ + + bus-width = <4>; + cap-sd-highspeed; +- max-frequency = <50000000>; ++ sd-uhs-sdr12; ++ sd-uhs-sdr25; ++ sd-uhs-sdr50; ++ sd-uhs-sdr104; ++ max-frequency = <100000000>; + + non-removable; + disable-wp; +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-sm1-ac2xx.dtsi mod/arch/arm64/boot/dts/amlogic/meson-sm1-ac2xx.dtsi +--- main/arch/arm64/boot/dts/amlogic/meson-sm1-ac2xx.dtsi 2023-03-07 09:42:02.837543496 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-sm1-ac2xx.dtsi 2023-03-07 09:42:05.125561225 +0100 +@@ -127,6 +127,12 @@ + clock-frequency = <32768>; + pwms = <&pwm_ef 0 30518 0>; /* PWM_E at 32.768KHz */ + }; ++ ++ openvfd: openvfd { ++ compatible = "open,vfd"; ++ dev_name = "openvfd"; ++ status = "okay"; ++ }; + }; + + &cec_AO { +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-sm1.dtsi mod/arch/arm64/boot/dts/amlogic/meson-sm1.dtsi +--- main/arch/arm64/boot/dts/amlogic/meson-sm1.dtsi 2023-03-07 09:42:02.969544521 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-sm1.dtsi 2023-03-07 09:42:05.689565591 +0100 +@@ -134,6 +134,16 @@ + opp-hz = /bits/ 64 <1908000000>; + opp-microvolt = <950000>; + }; ++ ++ opp-2016000000 { ++ opp-hz = /bits/ 64 <2016000000>; ++ opp-microvolt = <1000000>; ++ }; ++ ++ opp-2100000000 { ++ opp-hz = /bits/ 64 <2100000000>; ++ opp-microvolt = <1022000>; ++ }; + }; + }; + +@@ -543,3 +553,7 @@ + &usb { + power-domains = <&pwrc PWRC_SM1_USB_ID>; + }; ++ ++&npu { ++ power-domains = <&pwrc PWRC_SM1_NNA_ID>; ++}; +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-sm1-h96-max-x3.dts mod/arch/arm64/boot/dts/amlogic/meson-sm1-h96-max-x3.dts +--- main/arch/arm64/boot/dts/amlogic/meson-sm1-h96-max-x3.dts 1970-01-01 01:00:00.000000000 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-sm1-h96-max-x3.dts 2023-03-07 09:42:05.173561598 +0100 +@@ -0,0 +1,269 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++/* ++ * Copyright (c) 2019 BayLibre SAS. All rights reserved. ++ * Copyright (c) 2020 Christian Hewitt ++ * Copyright (c) 2021 flippy ++ */ ++ ++/dts-v1/; ++ ++#include "meson-sm1-ac2xx.dtsi" ++#include ++ ++/ { ++ compatible = "amlogic,sm1"; ++ model = "H96 Max X3"; ++ ++ memory@0 { ++ device_type = "memory"; ++ reg = <0x0 0x0 0x0 0xFFFFFFFF>; ++ }; ++ ++ sound { ++ compatible = "amlogic,axg-sound-card"; ++ model = "H96-MAX"; ++ audio-aux-devs = <&tdmout_b>; ++ audio-routing = "TDMOUT_B IN 0", "FRDDR_A OUT 1", ++ "TDMOUT_B IN 1", "FRDDR_B OUT 1", ++ "TDMOUT_B IN 2", "FRDDR_C OUT 1", ++ "TDM_B Playback", "TDMOUT_B OUT"; ++ ++ assigned-clocks = <&clkc CLKID_MPLL2>, ++ <&clkc CLKID_MPLL0>, ++ <&clkc CLKID_MPLL1>; ++ assigned-clock-parents = <0>, <0>, <0>; ++ assigned-clock-rates = <294912000>, ++ <270950400>, ++ <393216000>; ++ status = "okay"; ++ ++ dai-link-0 { ++ sound-dai = <&frddr_a>; ++ }; ++ ++ dai-link-1 { ++ sound-dai = <&frddr_b>; ++ }; ++ ++ dai-link-2 { ++ sound-dai = <&frddr_c>; ++ }; ++ ++ /* 8ch hdmi interface */ ++ dai-link-3 { ++ sound-dai = <&tdmif_b>; ++ dai-format = "i2s"; ++ dai-tdm-slot-tx-mask-0 = <1 1>; ++ dai-tdm-slot-tx-mask-1 = <1 1>; ++ dai-tdm-slot-tx-mask-2 = <1 1>; ++ dai-tdm-slot-tx-mask-3 = <1 1>; ++ mclk-fs = <256>; ++ ++ codec { ++ sound-dai = <&tohdmitx TOHDMITX_I2S_IN_B>; ++ }; ++ }; ++ ++ /* hdmi glue */ ++ dai-link-4 { ++ sound-dai = <&tohdmitx TOHDMITX_I2S_OUT>; ++ ++ codec { ++ sound-dai = <&hdmi_tx>; ++ }; ++ }; ++ }; ++ ++ vddgpu: regulator-vddgpu { ++ compatible = "regulator-fixed"; ++ regulator-name = "mali"; ++ regulator-min-microvolt = <800000>; ++ regulator-max-microvolt = <800000>; ++ vin-supply = <&ao_5v>; ++ regulator-always-on; ++ }; ++}; ++ ++&vddcpu { ++ regulator-min-microvolt = <721000>; ++ regulator-max-microvolt = <1022000>; ++ pwms = <&pwm_AO_cd 1 1250 0>; ++}; ++ ++&arb { ++ status = "okay"; ++}; ++ ++&clkc_audio { ++ status = "okay"; ++}; ++ ++ðmac { ++ status = "okay"; ++ ++ pinctrl-0 = <ð_pins>, <ð_rgmii_pins>; ++ pinctrl-names = "default"; ++ //phy-mode = "rgmii-txid"; ++ phy-mode = "rgmii"; ++ amlogic,tx-delay-ns = <2>; ++ phy-handle = <&external_phy>; ++ ++ //rx-internal-delay-ps = <800>; ++ ++ snps,aal; ++ snps,rxpbl = <0x8>; ++ snps,txpbl = <0x8>; ++ ++ rx-fifo-depth = <4096>; ++ tx-fifo-depth = <4096>; ++ ++ nvmem-cells = <ð_mac>; ++ nvmem-cell-names = "eth_mac"; ++}; ++ ++&ext_mdio { ++ external_phy: ethernet-phy@0 { ++ /* ++ * Realtek RTL8211F (0x001cc916) ++ * JLSemi JL2101 (0x937c4032) ++ */ ++ reg = <0>; ++ max-speed = <1000>; ++ ++ reset-assert-us = <10000>; ++ reset-deassert-us = <80000>; ++ reset-gpios = <&gpio GPIOZ_15 (GPIO_ACTIVE_LOW | GPIO_OPEN_DRAIN)>; ++ ++ interrupt-parent = <&gpio_intc>; ++ /* MAC_INTR on GPIOZ_14 */ ++ interrupts = <26 IRQ_TYPE_LEVEL_LOW>; ++ }; ++}; ++ ++&frddr_a { ++ status = "okay"; ++}; ++ ++&frddr_b { ++ status = "okay"; ++}; ++ ++&frddr_c { ++ status = "okay"; ++}; ++ ++&tdmif_b { ++ status = "okay"; ++}; ++ ++&tdmout_b { ++ status = "okay"; ++}; ++ ++&tohdmitx { ++ status = "okay"; ++}; ++ ++&uart_A { ++ status = "okay"; ++ ++ pinctrl-0 = <&uart_a_pins>, <&uart_a_cts_rts_pins>; ++ pinctrl-names = "default"; ++ uart-has-rtscts; ++ ++ bluetooth { ++ compatible = "brcm,bcm43438-bt"; ++ shutdown-gpios = <&gpio GPIOX_17 GPIO_ACTIVE_HIGH>; ++ max-speed = <2000000>; ++ clocks = <&wifi32k>; ++ clock-names = "lpo"; ++ }; ++}; ++ ++&mali { ++ mali-supply=<&vddgpu>; ++}; ++ ++&usb { ++ dr_mode = "host"; ++}; ++ ++/* SDIO */ ++&sd_emmc_a { ++ ///delete-property/ sd-uhs-sdr104; ++ sd-uhs-sdr50; ++ max-frequency = <100000000>; ++ ++ //sd-uhs-ddr50; ++ //max-frequency = <50000000>; ++ ++ //sd-uhs-sdr104; ++ //max-frequency = <200000000>; ++}; ++ ++/* Begin: fix hcy6355 wifi module problem */ ++&sdio_pins { ++ mux { ++ /delete-property/ bias-disable; ++ bias-pull-up; ++ }; ++}; ++/* End: fix hcy6355 wifi module problem */ ++ ++/* SD card */ ++&sd_emmc_b { ++ max-frequency = <50000000>; ++}; ++ ++/* eMMC */ ++&sd_emmc_c { ++ max-frequency = <200000000>; ++}; ++ ++&cpu_opp_table { ++ opp-100000000 { ++ opp-hz = <0x00 100000000>; ++ opp-microvolt = <730000>; ++ }; ++ ++ opp-250000000 { ++ opp-hz = <0x00 250000000>; ++ opp-microvolt = <730000>; ++ }; ++ ++ opp-500000000 { ++ opp-hz = <0x00 500000000>; ++ opp-microvolt = <730000>; ++ }; ++ ++ opp-667000000 { ++ opp-hz = <0x00 667000000>; ++ opp-microvolt = <730000>; ++ }; ++ ++ opp-2016000000 { ++ status = "disabled"; ++ }; ++ ++ opp-2100000000 { ++ status = "disabled"; ++ }; ++}; ++ ++&efuse { ++ eth_mac: eth_mac@0 { ++ reg = <0x0 0x06>; ++ }; ++ ++ bt_mac: bt_mac@6 { ++ reg = <0x6 0x06>; ++ }; ++ ++ wifi_mac: wifi_mac@12 { ++ reg = <0x0c 0x06>; ++ }; ++ ++ usid: usid@18 { ++ reg = <0x12 0x10>; ++ }; ++}; +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-sm1-h96-max-x3-oc.dts mod/arch/arm64/boot/dts/amlogic/meson-sm1-h96-max-x3-oc.dts +--- main/arch/arm64/boot/dts/amlogic/meson-sm1-h96-max-x3-oc.dts 1970-01-01 01:00:00.000000000 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-sm1-h96-max-x3-oc.dts 2023-03-07 09:42:05.161561504 +0100 +@@ -0,0 +1,24 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++/* ++ * Author: flippy ++ */ ++ ++/dts-v1/; ++ ++#include "meson-sm1-h96-max-x3.dts" ++ ++/ { ++ model = "H96 Max X3 @ 2208Mhz"; ++}; ++ ++&cpu_opp_table { ++ opp-2100000000 { ++ opp-hz = /bits/ 64 <2100000000>; ++ opp-microvolt = <1011000>; ++ }; ++ ++ opp-2208000000 { ++ opp-hz = /bits/ 64 <2208000000>; ++ opp-microvolt = <1021000>; ++ }; ++}; +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-sm1-hk1box-vontar-x3.dts mod/arch/arm64/boot/dts/amlogic/meson-sm1-hk1box-vontar-x3.dts +--- main/arch/arm64/boot/dts/amlogic/meson-sm1-hk1box-vontar-x3.dts 1970-01-01 01:00:00.000000000 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-sm1-hk1box-vontar-x3.dts 2023-03-07 09:42:05.229562032 +0100 +@@ -0,0 +1,247 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++/* ++ * Copyright (c) 2019 BayLibre SAS. All rights reserved. ++ * Copyright (c) 2020 Christian Hewitt ++ * Copyright (c) 2021 flippy ++ */ ++ ++/dts-v1/; ++ ++#include "meson-sm1-ac2xx.dtsi" ++#include ++ ++/ { ++ compatible = "amlogic,sm1"; ++ model = "HK1 Box/Vontar X3"; ++ ++ memory@0 { ++ device_type = "memory"; ++ reg = <0x0 0x0 0x0 0xFFFFFFFF>; ++ }; ++ ++ sound { ++ compatible = "amlogic,axg-sound-card"; ++ model = "HK1-BOX"; ++ audio-aux-devs = <&tdmout_b>; ++ audio-routing = "TDMOUT_B IN 0", "FRDDR_A OUT 1", ++ "TDMOUT_B IN 1", "FRDDR_B OUT 1", ++ "TDMOUT_B IN 2", "FRDDR_C OUT 1", ++ "TDM_B Playback", "TDMOUT_B OUT"; ++ ++ assigned-clocks = <&clkc CLKID_MPLL2>, ++ <&clkc CLKID_MPLL0>, ++ <&clkc CLKID_MPLL1>; ++ assigned-clock-parents = <0>, <0>, <0>; ++ assigned-clock-rates = <294912000>, ++ <270950400>, ++ <393216000>; ++ status = "okay"; ++ ++ dai-link-0 { ++ sound-dai = <&frddr_a>; ++ }; ++ ++ dai-link-1 { ++ sound-dai = <&frddr_b>; ++ }; ++ ++ dai-link-2 { ++ sound-dai = <&frddr_c>; ++ }; ++ ++ /* 8ch hdmi interface */ ++ dai-link-3 { ++ sound-dai = <&tdmif_b>; ++ dai-format = "i2s"; ++ dai-tdm-slot-tx-mask-0 = <1 1>; ++ dai-tdm-slot-tx-mask-1 = <1 1>; ++ dai-tdm-slot-tx-mask-2 = <1 1>; ++ dai-tdm-slot-tx-mask-3 = <1 1>; ++ mclk-fs = <256>; ++ ++ codec { ++ sound-dai = <&tohdmitx TOHDMITX_I2S_IN_B>; ++ }; ++ }; ++ ++ /* hdmi glue */ ++ dai-link-4 { ++ sound-dai = <&tohdmitx TOHDMITX_I2S_OUT>; ++ ++ codec { ++ sound-dai = <&hdmi_tx>; ++ }; ++ }; ++ }; ++ ++ vddgpu: regulator-vddgpu { ++ compatible = "regulator-fixed"; ++ regulator-name = "mali"; ++ regulator-min-microvolt = <800000>; ++ regulator-max-microvolt = <800000>; ++ vin-supply = <&ao_5v>; ++ regulator-always-on; ++ }; ++}; ++ ++&vddcpu { ++ regulator-min-microvolt = <721000>; ++ regulator-max-microvolt = <1022000>; ++ pwms = <&pwm_AO_cd 1 1250 0>; ++}; ++ ++&arb { ++ status = "okay"; ++}; ++ ++&clkc_audio { ++ status = "okay"; ++}; ++ ++ðmac { ++ status = "okay"; ++ ++ pinctrl-0 = <ð_pins>, <ð_rgmii_pins>; ++ pinctrl-names = "default"; ++ phy-handle = <&external_phy>; ++ ++ //phy-mode = "rgmii-txid"; ++ //rx-internal-delay-ps = <800>; ++ phy-mode = "rgmii"; ++ amlogic,tx-delay-ns = <2>; ++ ++ snps,aal; ++ snps,rxpbl = <0x8>; ++ snps,txpbl = <0x8>; ++ ++ rx-fifo-depth = <4096>; ++ tx-fifo-depth = <4096>; ++ ++ nvmem-cells = <ð_mac>; ++ nvmem-cell-names = "eth_mac"; ++}; ++ ++&ext_mdio { ++ external_phy: ethernet-phy@0 { ++ /* ++ * Realtek RTL8211F (0x001cc916) ++ * JLSemi JL2101 (0x937c4032) ++ */ ++ reg = <0>; ++ max-speed = <1000>; ++ ++ reset-assert-us = <30000>; ++ reset-deassert-us = <80000>; ++ reset-gpios = <&gpio GPIOZ_15 (GPIO_ACTIVE_LOW | GPIO_OPEN_DRAIN)>; ++ ++ interrupt-parent = <&gpio_intc>; ++ /* MAC_INTR on GPIOZ_14 */ ++ interrupts = <26 IRQ_TYPE_LEVEL_LOW>; ++ }; ++}; ++ ++&frddr_a { ++ status = "okay"; ++}; ++ ++&frddr_b { ++ status = "okay"; ++}; ++ ++&frddr_c { ++ status = "okay"; ++}; ++ ++&tdmif_b { ++ status = "okay"; ++}; ++ ++&tdmout_b { ++ status = "okay"; ++}; ++ ++&tohdmitx { ++ status = "okay"; ++}; ++ ++&uart_A { ++ status = "okay"; ++ ++ pinctrl-0 = <&uart_a_pins>, <&uart_a_cts_rts_pins>; ++ pinctrl-names = "default"; ++ uart-has-rtscts; ++ ++ bluetooth { ++ compatible = "brcm,bcm43438-bt"; ++ shutdown-gpios = <&gpio GPIOX_17 GPIO_ACTIVE_HIGH>; ++ max-speed = <2000000>; ++ clocks = <&wifi32k>; ++ clock-names = "lpo"; ++ }; ++}; ++ ++&mali { ++ mali-supply=<&vddgpu>; ++}; ++ ++&usb { ++ dr_mode = "host"; ++}; ++ ++/* SDIO */ ++&sd_emmc_a { ++ ///delete-property/ sd-uhs-sdr104; ++ sd-uhs-sdr50; ++ max-frequency = <100000000>; ++ ++ //sd-uhs-ddr50; ++ //max-frequency = <50000000>; ++ ++ //sd-uhs-sdr104; ++ //max-frequency = <200000000>; ++}; ++ ++/* Begin: fix hcy6355 wifi module problem */ ++&sdio_pins { ++ mux { ++ /delete-property/ bias-disable; ++ bias-pull-up; ++ }; ++}; ++/* End: fix hcy6355 wifi module problem */ ++ ++/* SD card */ ++&sd_emmc_b { ++ cap-sd-highspeed; ++ max-frequency = <25000000>; ++}; ++ ++/* eMMC */ ++&sd_emmc_c { ++ max-frequency = <200000000>; ++}; ++ ++&cpu_opp_table { ++ opp-2016000000 { ++ opp-hz = /bits/ 64 <2016000000>; ++ opp-microvolt = <1000000>; ++ }; ++}; ++ ++&efuse { ++ eth_mac: eth_mac@0 { ++ reg = <0x0 0x06>; ++ }; ++ ++ bt_mac: bt_mac@6 { ++ reg = <0x6 0x06>; ++ }; ++ ++ wifi_mac: wifi_mac@12 { ++ reg = <0x0c 0x06>; ++ }; ++ ++ usid: usid@18 { ++ reg = <0x12 0x10>; ++ }; ++}; +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-sm1-hk1box-vontar-x3-oc.dts mod/arch/arm64/boot/dts/amlogic/meson-sm1-hk1box-vontar-x3-oc.dts +--- main/arch/arm64/boot/dts/amlogic/meson-sm1-hk1box-vontar-x3-oc.dts 1970-01-01 01:00:00.000000000 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-sm1-hk1box-vontar-x3-oc.dts 2023-03-07 09:42:05.209561877 +0100 +@@ -0,0 +1,24 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++/* ++ * Author: flippy ++ */ ++ ++/dts-v1/; ++ ++#include "meson-sm1-hk1box-vontar-x3.dts" ++ ++/ { ++ model = "HK1 Box/Vontar X3 @ 2208Mhz"; ++}; ++ ++&cpu_opp_table { ++ opp-2100000000 { ++ opp-hz = /bits/ 64 <2100000000>; ++ opp-microvolt = <1011000>; ++ }; ++ ++ opp-2208000000 { ++ opp-hz = /bits/ 64 <2208000000>; ++ opp-microvolt = <1021000>; ++ }; ++}; +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-sm1-sei610.dts mod/arch/arm64/boot/dts/amlogic/meson-sm1-sei610.dts +--- main/arch/arm64/boot/dts/amlogic/meson-sm1-sei610.dts 2023-03-07 09:42:02.929544209 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-sm1-sei610.dts 2023-03-07 09:42:05.337562868 +0100 +@@ -329,6 +329,12 @@ + clock-frequency = <32768>; + pwms = <&pwm_ef 0 30518 0>; /* PWM_E at 32.768KHz */ + }; ++ ++ openvfd { ++ compatible = "open,vfd"; ++ dev_name = "openvfd"; ++ status = "okay"; ++ }; + }; + + &arb { +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-sm1-skyworth-lb2004-a4091.dts mod/arch/arm64/boot/dts/amlogic/meson-sm1-skyworth-lb2004-a4091.dts +--- main/arch/arm64/boot/dts/amlogic/meson-sm1-skyworth-lb2004-a4091.dts 1970-01-01 01:00:00.000000000 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-sm1-skyworth-lb2004-a4091.dts 2023-03-07 09:42:05.337562868 +0100 +@@ -0,0 +1,284 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++/* ++ * Copyright (c) 2019 BayLibre SAS. All rights reserved. ++ * Copyright (c) 2020 Christian Hewitt ++ * Copyright (c) 2021 flippy ++ */ ++ ++/dts-v1/; ++ ++#include "meson-sm1-ac2xx.dtsi" ++#include ++#include ++ ++/ { ++ compatible = "skyworth,lb2004", "amlogic,s905x3", "amlogic,sm1"; ++ model = "SKYWORTH LB2004-A4091"; ++ ++ memory@0 { ++ device_type = "memory"; ++ reg = <0x0 0x0 0x0 0xFFFFFFFF>; ++ }; ++ ++ leds { ++ compatible = "gpio-leds"; ++ ++ /* Mainline u-boot lacks TCA6507 driver. Currently only using bootloader, TCA6507 LEDs works. */ ++ gpio_led { ++ label = "gpio_led"; ++ gpios = <&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH>; ++ linux,default-trigger = "default-on"; ++ }; ++ }; ++ ++ sound { ++ compatible = "amlogic,axg-sound-card"; ++ model = "LB2004-A4091"; ++ audio-aux-devs = <&tdmout_b>; ++ audio-routing = "TDMOUT_B IN 0", "FRDDR_A OUT 1", ++ "TDMOUT_B IN 1", "FRDDR_B OUT 1", ++ "TDMOUT_B IN 2", "FRDDR_C OUT 1", ++ "TDM_B Playback", "TDMOUT_B OUT"; ++ ++ assigned-clocks = <&clkc CLKID_MPLL2>, ++ <&clkc CLKID_MPLL0>, ++ <&clkc CLKID_MPLL1>; ++ assigned-clock-parents = <0>, <0>, <0>; ++ assigned-clock-rates = <294912000>, ++ <270950400>, ++ <393216000>; ++ status = "okay"; ++ ++ dai-link-0 { ++ sound-dai = <&frddr_a>; ++ }; ++ ++ dai-link-1 { ++ sound-dai = <&frddr_b>; ++ }; ++ ++ dai-link-2 { ++ sound-dai = <&frddr_c>; ++ }; ++ ++ /* 8ch hdmi interface */ ++ dai-link-3 { ++ sound-dai = <&tdmif_b>; ++ dai-format = "i2s"; ++ dai-tdm-slot-tx-mask-0 = <1 1>; ++ dai-tdm-slot-tx-mask-1 = <1 1>; ++ dai-tdm-slot-tx-mask-2 = <1 1>; ++ dai-tdm-slot-tx-mask-3 = <1 1>; ++ mclk-fs = <256>; ++ ++ codec { ++ sound-dai = <&tohdmitx TOHDMITX_I2S_IN_B>; ++ }; ++ }; ++ ++ /* hdmi glue */ ++ dai-link-4 { ++ sound-dai = <&tohdmitx TOHDMITX_I2S_OUT>; ++ ++ codec { ++ sound-dai = <&hdmi_tx>; ++ }; ++ }; ++ }; ++ ++ vddgpu: regulator-vddgpu { ++ compatible = "regulator-fixed"; ++ regulator-name = "mali"; ++ regulator-min-microvolt = <800000>; ++ regulator-max-microvolt = <800000>; ++ vin-supply = <&ao_5v>; ++ regulator-always-on; ++ }; ++}; ++ ++&i2c3 { ++ status = "okay"; ++ ++ /* Mainline u-boot lacks TCA6507 driver. Currently only using bootloader, TCA6507 LEDs works. */ ++ tca6507@45 { ++ compatible = "ti,tca6507", "leds,tca6507"; ++ reg = <0x45>; ++ status = "okay"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ ++ led@red { ++ reg = <0x00>; ++ linux,default-trigger = "heartbeat"; ++ }; ++ ++ led@green { ++ reg = <0x01>; ++ linux,default-trigger = "heartbeat"; ++ }; ++ ++ led@blue { ++ reg = <0x02>; ++ linux,default-trigger = "none"; ++ }; ++ }; ++}; ++ ++&vddcpu { ++ regulator-min-microvolt = <721000>; ++ regulator-max-microvolt = <1022000>; ++ pwms = <&pwm_AO_cd 1 1250 0>; ++}; ++ ++&arb { ++ status = "okay"; ++}; ++ ++&clkc_audio { ++ status = "okay"; ++}; ++ ++ðmac { ++ status = "okay"; ++ ++ pinctrl-0 = <ð_pins>, <ð_rgmii_pins>; ++ pinctrl-names = "default"; ++ phy-handle = <&external_phy>; ++ ++ phy-mode = "rgmii"; ++ amlogic,tx-delay-ns = <2>; ++ ++ snps,aal; ++ snps,rxpbl = <0x8>; ++ snps,txpbl = <0x8>; ++ ++ rx-fifo-depth = <4096>; ++ tx-fifo-depth = <4096>; ++ ++ nvmem-cells = <ð_mac>; ++ nvmem-cell-names = "eth_mac"; ++}; ++ ++&ext_mdio { ++ external_phy: ethernet-phy@0 { ++ /* ++ * Realtek RTL8211F (0x001cc916) ++ * JLSemi JL2101 (0x937c4032) ++ */ ++ reg = <0>; ++ max-speed = <1000>; ++ ++ reset-assert-us = <30000>; ++ reset-deassert-us = <80000>; ++ reset-gpios = <&gpio GPIOZ_15 (GPIO_ACTIVE_LOW | GPIO_OPEN_DRAIN)>; ++ ++ interrupt-parent = <&gpio_intc>; ++ /* MAC_INTR on GPIOZ_14 */ ++ interrupts = <26 IRQ_TYPE_LEVEL_LOW>; ++ }; ++}; ++ ++&frddr_a { ++ status = "okay"; ++}; ++ ++&frddr_b { ++ status = "okay"; ++}; ++ ++&frddr_c { ++ status = "okay"; ++}; ++ ++&ir { ++ status = "disabled"; ++}; ++ ++&tdmif_b { ++ status = "okay"; ++}; ++ ++&tdmout_b { ++ status = "okay"; ++}; ++ ++&tohdmitx { ++ status = "okay"; ++}; ++ ++&uart_A { ++ status = "disabled"; ++ pinctrl-0 = <&uart_a_pins>, <&uart_a_cts_rts_pins>; ++ pinctrl-names = "default"; ++ uart-has-rtscts; ++ ++ bluetooth: bluetooth { ++ compatible = "realtek,rtl8822cs-bt"; ++ interrupt-parent = <&gpio_intc>; ++ interrupts = <95 IRQ_TYPE_LEVEL_HIGH>; ++ interrupt-names = "host-wakeup"; ++ shutdown-gpios = <&gpio GPIOX_17 GPIO_ACTIVE_HIGH>; ++ max-speed = <2000000>; ++ clocks = <&wifi32k>; ++ clock-names = "lpo"; ++ vbat-supply = <&vddao_3v3>; ++ vddio-supply = <&vddio_ao1v8>; ++ status = "disabled"; ++ }; ++}; ++ ++&mali { ++ mali-supply=<&vddgpu>; ++}; ++ ++&usb { ++ dr_mode = "host"; ++}; ++ ++/* SDIO */ ++&sd_emmc_a { ++ sd-uhs-sdr12; ++ sd-uhs-sdr25; ++ sd-uhs-ddr50; ++ sd-uhs-sdr50; ++ sd-uhs-sdr104; ++ max-frequency = <208000000>; ++}; ++ ++/* SD card */ ++&sd_emmc_b { ++ status = "disabled"; ++}; ++ ++/* eMMC */ ++&sd_emmc_c { ++ mmc-sdr-1_8v; ++ max-frequency = <200000000>; ++}; ++ ++&cpu_opp_table { ++ opp-2016000000 { ++ opp-hz = /bits/ 64 <2016000000>; ++ opp-microvolt = <1000000>; ++ }; ++}; ++ ++&efuse { ++ eth_mac: eth_mac@0 { ++ reg = <0x0 0x06>; ++ }; ++ ++ bt_mac: bt_mac@6 { ++ reg = <0x6 0x06>; ++ }; ++ ++ wifi_mac: wifi_mac@12 { ++ reg = <0x0c 0x06>; ++ }; ++ ++ usid: usid@18 { ++ reg = <0x12 0x10>; ++ }; ++}; +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-sm1-tx3-bz.dts mod/arch/arm64/boot/dts/amlogic/meson-sm1-tx3-bz.dts +--- main/arch/arm64/boot/dts/amlogic/meson-sm1-tx3-bz.dts 1970-01-01 01:00:00.000000000 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-sm1-tx3-bz.dts 2023-03-07 09:42:05.385563240 +0100 +@@ -0,0 +1,219 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++/* ++ * Copyright (c) 2019 BayLibre SAS. All rights reserved. ++ * Copyright (c) 2020 Christian Hewitt ++ * Copyright (c) 2022 flippy ++ */ ++ ++/dts-v1/; ++ ++#include "meson-sm1-ac2xx.dtsi" ++#include ++ ++/ { ++ compatible = "tanix,tx3-bz", "amlogic,sm1"; ++ model = "Tanix TX3 (BZ)"; ++ ++ leds { ++ compatible = "gpio-leds"; ++ ++ sys_led { ++ led_name = "sys_led"; ++ gpios = <&gpio_ao GPIOAO_11 GPIO_ACTIVE_LOW>; ++ default-state = "on"; ++ }; ++ }; ++ ++ memory@0 { ++ device_type = "memory"; ++ reg = <0x0 0x0 0x0 0x80000000>; ++ }; ++ ++ sound { ++ compatible = "amlogic,axg-sound-card"; ++ model = "TX3"; ++ audio-aux-devs = <&tdmout_b>; ++ audio-routing = "TDMOUT_B IN 0", "FRDDR_A OUT 1", ++ "TDMOUT_B IN 1", "FRDDR_B OUT 1", ++ "TDMOUT_B IN 2", "FRDDR_C OUT 1", ++ "TDM_B Playback", "TDMOUT_B OUT"; ++ ++ assigned-clocks = <&clkc CLKID_MPLL2>, ++ <&clkc CLKID_MPLL0>, ++ <&clkc CLKID_MPLL1>; ++ assigned-clock-parents = <0>, <0>, <0>; ++ assigned-clock-rates = <294912000>, ++ <270950400>, ++ <393216000>; ++ status = "okay"; ++ ++ dai-link-0 { ++ sound-dai = <&frddr_a>; ++ }; ++ ++ dai-link-1 { ++ sound-dai = <&frddr_b>; ++ }; ++ ++ dai-link-2 { ++ sound-dai = <&frddr_c>; ++ }; ++ ++ /* 8ch hdmi interface */ ++ dai-link-3 { ++ sound-dai = <&tdmif_b>; ++ dai-format = "i2s"; ++ dai-tdm-slot-tx-mask-0 = <1 1>; ++ dai-tdm-slot-tx-mask-1 = <1 1>; ++ dai-tdm-slot-tx-mask-2 = <1 1>; ++ dai-tdm-slot-tx-mask-3 = <1 1>; ++ mclk-fs = <256>; ++ ++ codec { ++ sound-dai = <&tohdmitx TOHDMITX_I2S_IN_B>; ++ }; ++ }; ++ ++ /* hdmi glue */ ++ dai-link-4 { ++ sound-dai = <&tohdmitx TOHDMITX_I2S_OUT>; ++ ++ codec { ++ sound-dai = <&hdmi_tx>; ++ }; ++ }; ++ }; ++ ++ vddgpu: regulator-vddgpu { ++ compatible = "regulator-fixed"; ++ regulator-name = "mali"; ++ regulator-min-microvolt = <800000>; ++ regulator-max-microvolt = <800000>; ++ vin-supply = <&ao_5v>; ++ regulator-always-on; ++ }; ++}; ++ ++&vddcpu { ++ regulator-min-microvolt = <721000>; ++ regulator-max-microvolt = <1022000>; ++ pwms = <&pwm_AO_cd 1 1250 0>; ++}; ++ ++&arb { ++ status = "okay"; ++}; ++ ++&clkc_audio { ++ status = "okay"; ++}; ++ ++ðmac { ++ status = "okay"; ++ phy-mode = "rmii"; ++ phy-handle = <&internal_ephy>; ++ ++ nvmem-cells = <ð_mac>; ++ nvmem-cell-names = "eth_mac"; ++}; ++ ++&frddr_a { ++ status = "okay"; ++}; ++ ++&frddr_b { ++ status = "okay"; ++}; ++ ++&frddr_c { ++ status = "okay"; ++}; ++ ++&tdmif_b { ++ status = "okay"; ++}; ++ ++&tdmout_b { ++ status = "okay"; ++}; ++ ++&tohdmitx { ++ status = "okay"; ++}; ++ ++&uart_A { ++ status = "okay"; ++ ++ pinctrl-0 = <&uart_a_pins>, <&uart_a_cts_rts_pins>; ++ pinctrl-names = "default"; ++ uart-has-rtscts; ++ ++ bluetooth { ++ compatible = "brcm,bcm43438-bt"; ++ shutdown-gpios = <&gpio GPIOX_17 GPIO_ACTIVE_HIGH>; ++ max-speed = <2000000>; ++ clocks = <&wifi32k>; ++ clock-names = "lpo"; ++ }; ++}; ++ ++&mali { ++ mali-supply=<&vddgpu>; ++}; ++ ++&usb { ++ dr_mode = "host"; ++}; ++ ++/* SDIO */ ++&sd_emmc_a { ++ /delete-property/ sd-uhs-sdr104; ++ sd-uhs-sdr50; ++ max-frequency = <100000000>; ++ ++ //sd-uhs-ddr50; ++ //max-frequency = <50000000>; ++ ++ //sd-uhs-sdr104; ++ //max-frequency = <200000000>; ++}; ++ ++/* SD card */ ++&sd_emmc_b { ++ max-frequency = <50000000>; ++}; ++ ++/* eMMC */ ++&sd_emmc_c { ++ max-frequency = <200000000>; ++}; ++ ++&cpu_opp_table { ++ opp-2016000000 { ++ opp-hz = /bits/ 64 <2016000000>; ++ opp-microvolt = <1000000>; ++ }; ++ ++ opp-2100000000 { ++ opp-hz = /bits/ 64 <2100000000>; ++ opp-microvolt = <1011000>; ++ }; ++}; ++ ++&efuse { ++ eth_mac: eth_mac@0 { ++ reg = <0x0 0x06>; ++ }; ++ ++ bt_mac: bt_mac@6 { ++ reg = <0x6 0x06>; ++ }; ++ ++ wifi_mac: wifi_mac@12 { ++ reg = <0x0c 0x06>; ++ }; ++ ++ usid: usid@18 { ++ reg = <0x12 0x10>; ++ }; ++}; +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-sm1-tx3-bz-oc.dts mod/arch/arm64/boot/dts/amlogic/meson-sm1-tx3-bz-oc.dts +--- main/arch/arm64/boot/dts/amlogic/meson-sm1-tx3-bz-oc.dts 1970-01-01 01:00:00.000000000 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-sm1-tx3-bz-oc.dts 2023-03-07 09:42:05.369563117 +0100 +@@ -0,0 +1,20 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++/* ++ * Author: flippy ++ */ ++ ++/dts-v1/; ++ ++#include "meson-sm1-tx3-bz.dts" ++ ++/ { ++ model = "Tanix TX3 (BZ) @ 2208Mhz"; ++}; ++ ++&cpu_opp_table { ++ ++ opp-2208000000 { ++ opp-hz = /bits/ 64 <2208000000>; ++ opp-microvolt = <1021000>; ++ }; ++}; +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-sm1-tx3-qz.dts mod/arch/arm64/boot/dts/amlogic/meson-sm1-tx3-qz.dts +--- main/arch/arm64/boot/dts/amlogic/meson-sm1-tx3-qz.dts 1970-01-01 01:00:00.000000000 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-sm1-tx3-qz.dts 2023-03-07 09:42:05.433563612 +0100 +@@ -0,0 +1,247 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++/* ++ * Copyright (c) 2019 BayLibre SAS. All rights reserved. ++ * Copyright (c) 2020 Christian Hewitt ++ * Copyright (c) 2022 flippy ++ */ ++ ++/dts-v1/; ++ ++#include "meson-sm1-ac2xx.dtsi" ++#include ++ ++/ { ++ compatible = "tanix,tx3-qz", "amlogic,sm1"; ++ model = "Tanix TX3 (QZ)"; ++ ++ leds { ++ compatible = "gpio-leds"; ++ ++ sys_led { ++ led_name = "sys_led"; ++ gpios = <&gpio_ao GPIOAO_11 GPIO_ACTIVE_LOW>; ++ default-state = "on"; ++ }; ++ }; ++ ++ memory@0 { ++ device_type = "memory"; ++ reg = <0x0 0x0 0x0 0xFFFFFFFF>; ++ }; ++ ++ sound { ++ compatible = "amlogic,axg-sound-card"; ++ model = "TX3"; ++ audio-aux-devs = <&tdmout_b>; ++ audio-routing = "TDMOUT_B IN 0", "FRDDR_A OUT 1", ++ "TDMOUT_B IN 1", "FRDDR_B OUT 1", ++ "TDMOUT_B IN 2", "FRDDR_C OUT 1", ++ "TDM_B Playback", "TDMOUT_B OUT"; ++ ++ assigned-clocks = <&clkc CLKID_MPLL2>, ++ <&clkc CLKID_MPLL0>, ++ <&clkc CLKID_MPLL1>; ++ assigned-clock-parents = <0>, <0>, <0>; ++ assigned-clock-rates = <294912000>, ++ <270950400>, ++ <393216000>; ++ status = "okay"; ++ ++ dai-link-0 { ++ sound-dai = <&frddr_a>; ++ }; ++ ++ dai-link-1 { ++ sound-dai = <&frddr_b>; ++ }; ++ ++ dai-link-2 { ++ sound-dai = <&frddr_c>; ++ }; ++ ++ /* 8ch hdmi interface */ ++ dai-link-3 { ++ sound-dai = <&tdmif_b>; ++ dai-format = "i2s"; ++ dai-tdm-slot-tx-mask-0 = <1 1>; ++ dai-tdm-slot-tx-mask-1 = <1 1>; ++ dai-tdm-slot-tx-mask-2 = <1 1>; ++ dai-tdm-slot-tx-mask-3 = <1 1>; ++ mclk-fs = <256>; ++ ++ codec { ++ sound-dai = <&tohdmitx TOHDMITX_I2S_IN_B>; ++ }; ++ }; ++ ++ /* hdmi glue */ ++ dai-link-4 { ++ sound-dai = <&tohdmitx TOHDMITX_I2S_OUT>; ++ ++ codec { ++ sound-dai = <&hdmi_tx>; ++ }; ++ }; ++ }; ++ ++ vddgpu: regulator-vddgpu { ++ compatible = "regulator-fixed"; ++ regulator-name = "mali"; ++ regulator-min-microvolt = <800000>; ++ regulator-max-microvolt = <800000>; ++ vin-supply = <&ao_5v>; ++ regulator-always-on; ++ }; ++}; ++ ++&vddcpu { ++ regulator-min-microvolt = <721000>; ++ regulator-max-microvolt = <1022000>; ++ pwms = <&pwm_AO_cd 1 1250 0>; ++}; ++ ++&arb { ++ status = "okay"; ++}; ++ ++&clkc_audio { ++ status = "okay"; ++}; ++ ++ðmac { ++ status = "okay"; ++ ++ pinctrl-0 = <ð_pins>, <ð_rgmii_pins>; ++ pinctrl-names = "default"; ++ phy-mode = "rgmii-txid"; ++ phy-handle = <&external_phy>; ++ ++ rx-internal-delay-ps = <800>; ++ ++ snps,aal; ++ snps,rxpbl = <0x8>; ++ snps,txpbl = <0x8>; ++ ++ rx-fifo-depth = <4096>; ++ tx-fifo-depth = <4096>; ++ ++ nvmem-cells = <ð_mac>; ++ nvmem-cell-names = "eth_mac"; ++}; ++ ++&ext_mdio { ++ external_phy: ethernet-phy@0 { ++ /* Realtek RTL8211F (0x001cc916) */ ++ reg = <0>; ++ max-speed = <1000>; ++ ++ reset-assert-us = <10000>; ++ reset-deassert-us = <80000>; ++ reset-gpios = <&gpio GPIOZ_15 (GPIO_ACTIVE_LOW | GPIO_OPEN_DRAIN)>; ++ ++ interrupt-parent = <&gpio_intc>; ++ /* MAC_INTR on GPIOZ_14 */ ++ interrupts = <26 IRQ_TYPE_LEVEL_LOW>; ++ }; ++}; ++ ++&frddr_a { ++ status = "okay"; ++}; ++ ++&frddr_b { ++ status = "okay"; ++}; ++ ++&frddr_c { ++ status = "okay"; ++}; ++ ++&tdmif_b { ++ status = "okay"; ++}; ++ ++&tdmout_b { ++ status = "okay"; ++}; ++ ++&tohdmitx { ++ status = "okay"; ++}; ++ ++&uart_A { ++ status = "okay"; ++ ++ pinctrl-0 = <&uart_a_pins>, <&uart_a_cts_rts_pins>; ++ pinctrl-names = "default"; ++ uart-has-rtscts; ++ ++ bluetooth { ++ compatible = "brcm,bcm43438-bt"; ++ shutdown-gpios = <&gpio GPIOX_17 GPIO_ACTIVE_HIGH>; ++ max-speed = <2000000>; ++ clocks = <&wifi32k>; ++ clock-names = "lpo"; ++ }; ++}; ++ ++&mali { ++ mali-supply=<&vddgpu>; ++}; ++ ++&usb { ++ dr_mode = "host"; ++}; ++ ++/* SDIO */ ++&sd_emmc_a { ++ /delete-property/ sd-uhs-sdr104; ++ sd-uhs-sdr50; ++ max-frequency = <100000000>; ++ ++ //sd-uhs-ddr50; ++ //max-frequency = <50000000>; ++ ++ //sd-uhs-sdr104; ++ //max-frequency = <200000000>; ++}; ++ ++/* SD card */ ++&sd_emmc_b { ++ max-frequency = <50000000>; ++}; ++ ++/* eMMC */ ++&sd_emmc_c { ++ max-frequency = <200000000>; ++}; ++ ++&cpu_opp_table { ++ opp-2016000000 { ++ opp-hz = /bits/ 64 <2016000000>; ++ opp-microvolt = <1000000>; ++ }; ++ ++ opp-2100000000 { ++ opp-hz = /bits/ 64 <2100000000>; ++ opp-microvolt = <1011000>; ++ }; ++}; ++ ++&efuse { ++ eth_mac: eth_mac@0 { ++ reg = <0x0 0x06>; ++ }; ++ ++ bt_mac: bt_mac@6 { ++ reg = <0x6 0x06>; ++ }; ++ ++ wifi_mac: wifi_mac@12 { ++ reg = <0x0c 0x06>; ++ }; ++ ++ usid: usid@18 { ++ reg = <0x12 0x10>; ++ }; ++}; +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-sm1-tx3-qz-oc.dts mod/arch/arm64/boot/dts/amlogic/meson-sm1-tx3-qz-oc.dts +--- main/arch/arm64/boot/dts/amlogic/meson-sm1-tx3-qz-oc.dts 1970-01-01 01:00:00.000000000 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-sm1-tx3-qz-oc.dts 2023-03-07 09:42:05.425563550 +0100 +@@ -0,0 +1,20 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++/* ++ * Author: flippy ++ */ ++ ++/dts-v1/; ++ ++#include "meson-sm1-tx3-qz.dts" ++ ++/ { ++ model = "Tanix TX3 (QZ) @ 2208Mhz"; ++}; ++ ++&cpu_opp_table { ++ ++ opp-2208000000 { ++ opp-hz = /bits/ 64 <2208000000>; ++ opp-microvolt = <1021000>; ++ }; ++}; +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-sm1-ugoos-x3.dts mod/arch/arm64/boot/dts/amlogic/meson-sm1-ugoos-x3.dts +--- main/arch/arm64/boot/dts/amlogic/meson-sm1-ugoos-x3.dts 1970-01-01 01:00:00.000000000 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-sm1-ugoos-x3.dts 2023-03-07 09:42:05.481563983 +0100 +@@ -0,0 +1,289 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++/* ++ * Copyright (c) 2019 BayLibre SAS. All rights reserved. ++ * Copyright (c) 2020 Christian Hewitt ++ * Copyright (c) 2021 flippy ++ */ ++ ++/dts-v1/; ++ ++#include "meson-sm1-ac2xx.dtsi" ++#include ++ ++/ { ++ compatible = "amlogic,sm1"; ++ model = "Ugoos X3"; ++ ++ aliases { ++ rtc0 = &rtc; ++ rtc1 = &vrtc; ++ }; ++ ++ leds { ++ compatible = "gpio-leds"; ++ ++ red_led { ++ label = "red"; ++ gpios = <&gpio_ao GPIOAO_10 GPIO_ACTIVE_HIGH>; ++ default-state = "on"; ++ }; ++ ++ blue_led { ++ label = "blue"; ++ gpios = <&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH>; ++ default-state = "on"; ++ }; ++ }; ++ ++ sound { ++ compatible = "amlogic,axg-sound-card"; ++ model = "UGOOS-X3"; ++ audio-aux-devs = <&tdmout_b>; ++ audio-routing = "TDMOUT_B IN 0", "FRDDR_A OUT 1", ++ "TDMOUT_B IN 1", "FRDDR_B OUT 1", ++ "TDMOUT_B IN 2", "FRDDR_C OUT 1", ++ "TDM_B Playback", "TDMOUT_B OUT"; ++ ++ assigned-clocks = <&clkc CLKID_MPLL2>, ++ <&clkc CLKID_MPLL0>, ++ <&clkc CLKID_MPLL1>; ++ assigned-clock-parents = <0>, <0>, <0>; ++ assigned-clock-rates = <294912000>, ++ <270950400>, ++ <393216000>; ++ status = "okay"; ++ ++ dai-link-0 { ++ sound-dai = <&frddr_a>; ++ }; ++ ++ dai-link-1 { ++ sound-dai = <&frddr_b>; ++ }; ++ ++ dai-link-2 { ++ sound-dai = <&frddr_c>; ++ }; ++ ++ /* 8ch hdmi interface */ ++ dai-link-3 { ++ sound-dai = <&tdmif_b>; ++ dai-format = "i2s"; ++ dai-tdm-slot-tx-mask-0 = <1 1>; ++ dai-tdm-slot-tx-mask-1 = <1 1>; ++ dai-tdm-slot-tx-mask-2 = <1 1>; ++ dai-tdm-slot-tx-mask-3 = <1 1>; ++ mclk-fs = <256>; ++ ++ codec { ++ sound-dai = <&tohdmitx TOHDMITX_I2S_IN_B>; ++ }; ++ }; ++ ++ /* hdmi glue */ ++ dai-link-4 { ++ sound-dai = <&tohdmitx TOHDMITX_I2S_OUT>; ++ ++ codec { ++ sound-dai = <&hdmi_tx>; ++ }; ++ }; ++ }; ++ ++ vddgpu: regulator-vddgpu { ++ compatible = "regulator-fixed"; ++ regulator-name = "mali"; ++ regulator-min-microvolt = <800000>; ++ regulator-max-microvolt = <800000>; ++ vin-supply = <&ao_5v>; ++ regulator-always-on; ++ }; ++ ++ usb_pwr_en: regulator-usb-pwr-en { ++ compatible = "regulator-fixed"; ++ regulator-name = "USB_PWR_EN"; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ vin-supply = <&ao_5v>; ++ ++ gpio = <&gpio GPIOH_5 GPIO_ACTIVE_HIGH>; ++ enable-active-high; ++ }; ++}; ++ ++&vddcpu { ++ regulator-min-microvolt = <721000>; ++ regulator-max-microvolt = <1022000>; ++ pwms = <&pwm_AO_cd 1 1250 0>; ++}; ++ ++&arb { ++ status = "okay"; ++}; ++ ++&clkc_audio { ++ status = "okay"; ++}; ++ ++ðmac { ++ status = "okay"; ++ ++ pinctrl-0 = <ð_pins>, <ð_rgmii_pins>; ++ pinctrl-names = "default"; ++ phy-mode = "rgmii-txid"; ++ phy-handle = <&external_phy>; ++ ++ rx-internal-delay-ps = <800>; ++ ++ snps,aal; ++ snps,rxpbl = <0x8>; ++ snps,txpbl = <0x8>; ++ ++ rx-fifo-depth = <4096>; ++ tx-fifo-depth = <4096>; ++ ++ nvmem-cells = <ð_mac>; ++ nvmem-cell-names = "eth_mac"; ++}; ++ ++&ext_mdio { ++ external_phy: ethernet-phy@0 { ++ /* Realtek RTL8211F (0x001cc916) */ ++ reg = <0>; ++ max-speed = <1000>; ++ ++ reset-assert-us = <10000>; ++ reset-deassert-us = <80000>; ++ reset-gpios = <&gpio GPIOZ_15 (GPIO_ACTIVE_LOW | GPIO_OPEN_DRAIN)>; ++ ++ interrupt-parent = <&gpio_intc>; ++ /* MAC_INTR on GPIOZ_14 */ ++ interrupts = <26 IRQ_TYPE_LEVEL_LOW>; ++ }; ++}; ++ ++&frddr_a { ++ status = "okay"; ++}; ++ ++&frddr_b { ++ status = "okay"; ++}; ++ ++&frddr_c { ++ status = "okay"; ++}; ++ ++&tdmif_b { ++ status = "okay"; ++}; ++ ++&tdmout_b { ++ status = "okay"; ++}; ++ ++&tohdmitx { ++ status = "okay"; ++}; ++ ++&uart_A { ++ status = "okay"; ++ ++ pinctrl-0 = <&uart_a_pins>, <&uart_a_cts_rts_pins>; ++ pinctrl-names = "default"; ++ uart-has-rtscts; ++ ++ bluetooth { ++ compatible = "brcm,bcm43438-bt"; ++ shutdown-gpios = <&gpio GPIOX_17 GPIO_ACTIVE_HIGH>; ++ max-speed = <2000000>; ++ clocks = <&wifi32k>; ++ clock-names = "lpo"; ++ }; ++}; ++ ++&mali { ++ mali-supply=<&vddgpu>; ++}; ++ ++&usb { ++ dr_mode = "host"; ++ vbus-supply = <&usb_pwr_en>; ++}; ++ ++&usb2_phy0 { ++ phy-supply = <&ao_5v>; ++}; ++ ++&usb2_phy1 { ++ phy-supply = <&ao_5v>; ++}; ++ ++&i2c3 { ++ status = "okay"; ++ pinctrl-0 = <&i2c3_sda_a_pins>, <&i2c3_sck_a_pins>; ++ pinctrl-names = "default"; ++ ++ rtc: rtc@51 { ++ compatible = "haoyu,hym8563"; ++ reg = <0x51>; ++ wakeup-source; ++ ++ #clock-cells = <0>; ++ clock-frequency = <32768>; ++ clock-output-names = "xin32k"; ++ }; ++}; ++ ++/* SDIO */ ++&sd_emmc_a { ++ /delete-property/ sd-uhs-sdr104; ++ sd-uhs-sdr50; ++ max-frequency = <100000000>; ++ ++ //sd-uhs-ddr50; ++ //max-frequency = <50000000>; ++ ++ //sd-uhs-sdr104; ++ //max-frequency = <200000000>; ++}; ++ ++/* SD card */ ++&sd_emmc_b { ++ cap-sd-highspeed; ++ max-frequency = <100000000>; ++}; ++ ++/* eMMC */ ++&sd_emmc_c { ++ max-frequency = <200000000>; ++}; ++ ++&cpu_opp_table { ++ opp-2016000000 { ++ opp-hz = /bits/ 64 <2016000000>; ++ opp-microvolt = <1000000>; ++ }; ++}; ++ ++&efuse { ++ eth_mac: eth_mac@0 { ++ reg = <0x0 0x06>; ++ }; ++ ++ bt_mac: bt_mac@6 { ++ reg = <0x6 0x06>; ++ }; ++ ++ wifi_mac: wifi_mac@12 { ++ reg = <0x0c 0x06>; ++ }; ++ ++ usid: usid@18 { ++ reg = <0x12 0x10>; ++ }; ++}; ++ ++&openvfd { ++ status = "disabled"; ++}; +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-sm1-ugoos-x3-oc.dts mod/arch/arm64/boot/dts/amlogic/meson-sm1-ugoos-x3-oc.dts +--- main/arch/arm64/boot/dts/amlogic/meson-sm1-ugoos-x3-oc.dts 1970-01-01 01:00:00.000000000 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-sm1-ugoos-x3-oc.dts 2023-03-07 09:42:05.461563827 +0100 +@@ -0,0 +1,24 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++/* ++ * Author: flippy ++ */ ++ ++/dts-v1/; ++ ++#include "meson-sm1-ugoos-x3.dts" ++ ++/ { ++ model = "Ugoos X3 @ 2208Mhz"; ++}; ++ ++&cpu_opp_table { ++ opp-2100000000 { ++ opp-hz = /bits/ 64 <2100000000>; ++ opp-microvolt = <1011000>; ++ }; ++ ++ opp-2208000000 { ++ opp-hz = /bits/ 64 <2208000000>; ++ opp-microvolt = <1021000>; ++ }; ++}; +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-sm1-x96-air-gbit.dts mod/arch/arm64/boot/dts/amlogic/meson-sm1-x96-air-gbit.dts +--- main/arch/arm64/boot/dts/amlogic/meson-sm1-x96-air-gbit.dts 2023-03-07 09:42:02.949544364 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-sm1-x96-air-gbit.dts 2023-03-07 09:42:05.505564168 +0100 +@@ -131,3 +131,16 @@ + &tohdmitx { + status = "okay"; + }; ++ ++&uart_A { ++ status = "okay"; ++ pinctrl-0 = <&uart_a_pins>, <&uart_a_cts_rts_pins>; ++ pinctrl-names = "default"; ++ uart-has-rtscts; ++ ++ bluetooth { ++ compatible = "realtek,rtl8822cs-bt"; ++ enable-gpios = <&gpio GPIOX_17 GPIO_ACTIVE_HIGH>; ++ host-wake-gpios = <&gpio GPIOX_18 GPIO_ACTIVE_HIGH>; ++ }; ++}; +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-sm1-x96-max-plus-100m.dts mod/arch/arm64/boot/dts/amlogic/meson-sm1-x96-max-plus-100m.dts +--- main/arch/arm64/boot/dts/amlogic/meson-sm1-x96-max-plus-100m.dts 1970-01-01 01:00:00.000000000 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-sm1-x96-max-plus-100m.dts 2023-03-07 09:42:05.529564354 +0100 +@@ -0,0 +1,16 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++/* ++ * Copyright (c) 2019 BayLibre, SAS ++ * Author: flippy ++ */ ++/dts-v1/; ++ ++#include "meson-sm1-x96-max-plus.dts" ++ ++/ { ++ model = "AMedia X96 Max+ (eth0 speed:100Mb/s)"; ++}; ++ ++&external_phy { ++ max-speed = <100>; ++}; +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-sm1-x96-max-plus-2101.dts mod/arch/arm64/boot/dts/amlogic/meson-sm1-x96-max-plus-2101.dts +--- main/arch/arm64/boot/dts/amlogic/meson-sm1-x96-max-plus-2101.dts 1970-01-01 01:00:00.000000000 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-sm1-x96-max-plus-2101.dts 2023-03-07 09:42:05.549564507 +0100 +@@ -0,0 +1,254 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++/* ++ * Copyright (c) 2019 BayLibre SAS. All rights reserved. ++ * Copyright (c) 2020 Christian Hewitt ++ * Copyright (c) 2021 flippy ++ */ ++ ++/dts-v1/; ++ ++#include "meson-sm1-ac2xx.dtsi" ++#include ++ ++/ { ++ //compatible = "amediatech,x96-max-plus", "amlogic,sm1"; ++ //model = "Shenzhen Amediatech Technology Co., Ltd X96 Max+"; ++ compatible = "amlogic,sm1"; ++ model = "AMedia X96 Max+"; ++ ++ aliases { ++ serial0 = &uart_AO; ++ serial1 = &uart_A; ++ ethernet0 = ðmac; ++ }; ++ ++ memory@0 { ++ device_type = "memory"; ++ reg = <0x0 0x0 0x0 0xFFFFFFFF>; ++ }; ++ ++ sound { ++ compatible = "amlogic,axg-sound-card"; ++ model = "X96-MAX"; ++ audio-aux-devs = <&tdmout_b>; ++ audio-routing = "TDMOUT_B IN 0", "FRDDR_A OUT 1", ++ "TDMOUT_B IN 1", "FRDDR_B OUT 1", ++ "TDMOUT_B IN 2", "FRDDR_C OUT 1", ++ "TDM_B Playback", "TDMOUT_B OUT"; ++ ++ assigned-clocks = <&clkc CLKID_MPLL2>, ++ <&clkc CLKID_MPLL0>, ++ <&clkc CLKID_MPLL1>; ++ assigned-clock-parents = <0>, <0>, <0>; ++ assigned-clock-rates = <294912000>, ++ <270950400>, ++ <393216000>; ++ status = "okay"; ++ ++ dai-link-0 { ++ sound-dai = <&frddr_a>; ++ }; ++ ++ dai-link-1 { ++ sound-dai = <&frddr_b>; ++ }; ++ ++ dai-link-2 { ++ sound-dai = <&frddr_c>; ++ }; ++ ++ /* 8ch hdmi interface */ ++ dai-link-3 { ++ sound-dai = <&tdmif_b>; ++ dai-format = "i2s"; ++ dai-tdm-slot-tx-mask-0 = <1 1>; ++ dai-tdm-slot-tx-mask-1 = <1 1>; ++ dai-tdm-slot-tx-mask-2 = <1 1>; ++ dai-tdm-slot-tx-mask-3 = <1 1>; ++ mclk-fs = <256>; ++ ++ codec { ++ sound-dai = <&tohdmitx TOHDMITX_I2S_IN_B>; ++ }; ++ }; ++ ++ /* hdmi glue */ ++ dai-link-4 { ++ sound-dai = <&tohdmitx TOHDMITX_I2S_OUT>; ++ ++ codec { ++ sound-dai = <&hdmi_tx>; ++ }; ++ }; ++ }; ++ ++ vddgpu: regulator-vddgpu { ++ compatible = "regulator-fixed"; ++ regulator-name = "mali"; ++ regulator-min-microvolt = <800000>; ++ regulator-max-microvolt = <800000>; ++ vin-supply = <&ao_5v>; ++ regulator-always-on; ++ }; ++}; ++ ++&vddcpu { ++ regulator-min-microvolt = <721000>; ++ regulator-max-microvolt = <1022000>; ++ pwms = <&pwm_AO_cd 1 1250 0>; ++}; ++ ++&arb { ++ status = "okay"; ++}; ++ ++&clkc_audio { ++ status = "okay"; ++}; ++ ++ðmac { ++ status = "okay"; ++ ++ pinctrl-0 = <ð_pins>, <ð_rgmii_pins>; ++ pinctrl-names = "default"; ++ phy-handle = <&external_phy>; ++ ++ //phy-mode = "rgmii-txid"; ++ //rx-internal-delay-ps = <800>; ++ phy-mode = "rgmii"; ++ amlogic,tx-delay-ns = <2>; ++ ++ snps,aal; ++ snps,rxpbl = <0x8>; ++ snps,txpbl = <0x8>; ++ ++ rx-fifo-depth = <4096>; ++ tx-fifo-depth = <4096>; ++ ++ nvmem-cells = <ð_mac>; ++ nvmem-cell-names = "eth_mac"; ++}; ++ ++&ext_mdio { ++ external_phy: ethernet-phy@0 { ++ /* ++ * Realtek RTL8211F (0x001cc916) ++ * JLSemi JL2101 (0x937c4032) ++ */ ++ reg = <0>; ++ max-speed = <1000>; ++ ++ reset-assert-us = <30000>; ++ reset-deassert-us = <80000>; ++ reset-gpios = <&gpio GPIOZ_15 (GPIO_ACTIVE_LOW | GPIO_OPEN_DRAIN)>; ++ ++ interrupt-parent = <&gpio_intc>; ++ /* MAC_INTR on GPIOZ_14 */ ++ interrupts = <26 IRQ_TYPE_LEVEL_LOW>; ++ }; ++}; ++ ++&frddr_a { ++ status = "okay"; ++}; ++ ++&frddr_b { ++ status = "okay"; ++}; ++ ++&frddr_c { ++ status = "okay"; ++}; ++ ++&ir { ++ linux,rc-map-name = "rc-x96max"; ++}; ++ ++&tdmif_b { ++ status = "okay"; ++}; ++ ++&tdmout_b { ++ status = "okay"; ++}; ++ ++&tohdmitx { ++ status = "okay"; ++}; ++ ++&uart_A { ++ status = "okay"; ++ pinctrl-0 = <&uart_a_pins>, <&uart_a_cts_rts_pins>; ++ pinctrl-names = "default"; ++ uart-has-rtscts; ++ ++ bluetooth: bluetooth { ++ compatible = "realtek,rtl8822cs-bt"; ++ enable-gpios = <&gpio GPIOX_17 GPIO_ACTIVE_HIGH>; ++ host-wake-gpios = <&gpio GPIOX_19 GPIO_ACTIVE_HIGH>; ++ device-wake-gpios = <&gpio GPIOX_18 GPIO_ACTIVE_HIGH>; ++ }; ++}; ++ ++&mali { ++ mali-supply=<&vddgpu>; ++}; ++ ++&usb { ++ dr_mode = "host"; ++}; ++ ++/* SDIO */ ++&sd_emmc_a { ++ /delete-property/ sd-uhs-sdr104; ++ sd-uhs-sdr12; ++ sd-uhs-sdr25; ++ sd-uhs-sdr50; ++ max-frequency = <50000000>; ++ ++ //sd-uhs-ddr50; ++ //max-frequency = <50000000>; ++ ++ //sd-uhs-sdr104; ++ //max-frequency = <200000000>; ++ ++ rtl8822cs: wifi@1 { ++ reg = <1>; ++ }; ++}; ++ ++/* SD card */ ++&sd_emmc_b { ++ cap-sd-highspeed; ++ max-frequency = <25000000>; ++}; ++ ++/* eMMC */ ++&sd_emmc_c { ++ max-frequency = <200000000>; ++}; ++ ++&cpu_opp_table { ++ opp-2016000000 { ++ opp-hz = /bits/ 64 <2016000000>; ++ opp-microvolt = <1000000>; ++ }; ++}; ++ ++&efuse { ++ eth_mac: eth_mac@0 { ++ reg = <0x0 0x06>; ++ }; ++ ++ bt_mac: bt_mac@6 { ++ reg = <0x6 0x6>; ++ }; ++ ++ wifi_mac: wifi_mac@c { ++ reg = <0xc 0x6>; ++ }; ++ ++ usid: usid@18 { ++ reg = <0x12 0x10>; ++ }; ++}; +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-sm1-x96-max-plus.dts mod/arch/arm64/boot/dts/amlogic/meson-sm1-x96-max-plus.dts +--- main/arch/arm64/boot/dts/amlogic/meson-sm1-x96-max-plus.dts 1970-01-01 01:00:00.000000000 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-sm1-x96-max-plus.dts 2023-03-07 09:42:05.677565499 +0100 +@@ -0,0 +1,251 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++/* ++ * Copyright (c) 2019 BayLibre SAS. All rights reserved. ++ * Copyright (c) 2020 Christian Hewitt ++ * Copyright (c) 2021 flippy ++ */ ++ ++/dts-v1/; ++ ++#include "meson-sm1-ac2xx.dtsi" ++#include ++ ++/ { ++ //compatible = "amediatech,x96-max-plus", "amlogic,sm1"; ++ //model = "Shenzhen Amediatech Technology Co., Ltd X96 Max+"; ++ compatible = "amlogic,sm1"; ++ model = "AMedia X96 Max+"; ++ ++ memory@0 { ++ device_type = "memory"; ++ reg = <0x0 0x0 0x0 0xFFFFFFFF>; ++ }; ++ ++ sound { ++ compatible = "amlogic,axg-sound-card"; ++ model = "X96-MAX"; ++ audio-aux-devs = <&tdmout_b>; ++ audio-routing = "TDMOUT_B IN 0", "FRDDR_A OUT 1", ++ "TDMOUT_B IN 1", "FRDDR_B OUT 1", ++ "TDMOUT_B IN 2", "FRDDR_C OUT 1", ++ "TDM_B Playback", "TDMOUT_B OUT"; ++ ++ assigned-clocks = <&clkc CLKID_MPLL2>, ++ <&clkc CLKID_MPLL0>, ++ <&clkc CLKID_MPLL1>; ++ assigned-clock-parents = <0>, <0>, <0>; ++ assigned-clock-rates = <294912000>, ++ <270950400>, ++ <393216000>; ++ status = "okay"; ++ ++ dai-link-0 { ++ sound-dai = <&frddr_a>; ++ }; ++ ++ dai-link-1 { ++ sound-dai = <&frddr_b>; ++ }; ++ ++ dai-link-2 { ++ sound-dai = <&frddr_c>; ++ }; ++ ++ /* 8ch hdmi interface */ ++ dai-link-3 { ++ sound-dai = <&tdmif_b>; ++ dai-format = "i2s"; ++ dai-tdm-slot-tx-mask-0 = <1 1>; ++ dai-tdm-slot-tx-mask-1 = <1 1>; ++ dai-tdm-slot-tx-mask-2 = <1 1>; ++ dai-tdm-slot-tx-mask-3 = <1 1>; ++ mclk-fs = <256>; ++ ++ codec { ++ sound-dai = <&tohdmitx TOHDMITX_I2S_IN_B>; ++ }; ++ }; ++ ++ /* hdmi glue */ ++ dai-link-4 { ++ sound-dai = <&tohdmitx TOHDMITX_I2S_OUT>; ++ ++ codec { ++ sound-dai = <&hdmi_tx>; ++ }; ++ }; ++ }; ++ ++ vddgpu: regulator-vddgpu { ++ compatible = "regulator-fixed"; ++ regulator-name = "mali"; ++ regulator-min-microvolt = <800000>; ++ regulator-max-microvolt = <800000>; ++ vin-supply = <&ao_5v>; ++ regulator-always-on; ++ }; ++}; ++ ++&vddcpu { ++ regulator-min-microvolt = <721000>; ++ regulator-max-microvolt = <1022000>; ++ pwms = <&pwm_AO_cd 1 1250 0>; ++}; ++ ++&arb { ++ status = "okay"; ++}; ++ ++&clkc_audio { ++ status = "okay"; ++}; ++ ++ðmac { ++ status = "okay"; ++ ++ pinctrl-0 = <ð_pins>, <ð_rgmii_pins>; ++ pinctrl-names = "default"; ++ phy-handle = <&external_phy>; ++ ++ //phy-mode = "rgmii-txid"; ++ //rx-internal-delay-ps = <800>; ++ phy-mode = "rgmii"; ++ amlogic,tx-delay-ns = <2>; ++ ++ snps,aal; ++ snps,rxpbl = <0x8>; ++ snps,txpbl = <0x8>; ++ ++ rx-fifo-depth = <4096>; ++ tx-fifo-depth = <4096>; ++ ++ nvmem-cells = <ð_mac>; ++ nvmem-cell-names = "eth_mac"; ++}; ++ ++&ext_mdio { ++ external_phy: ethernet-phy@0 { ++ /* ++ * Realtek RTL8211F (0x001cc916) ++ * JLSemi JL2101 (0x937c4032) ++ */ ++ reg = <0>; ++ max-speed = <1000>; ++ ++ reset-assert-us = <30000>; ++ reset-deassert-us = <80000>; ++ reset-gpios = <&gpio GPIOZ_15 (GPIO_ACTIVE_LOW | GPIO_OPEN_DRAIN)>; ++ ++ interrupt-parent = <&gpio_intc>; ++ /* MAC_INTR on GPIOZ_14 */ ++ interrupts = <26 IRQ_TYPE_LEVEL_LOW>; ++ }; ++}; ++ ++&frddr_a { ++ status = "okay"; ++}; ++ ++&frddr_b { ++ status = "okay"; ++}; ++ ++&frddr_c { ++ status = "okay"; ++}; ++ ++&ir { ++ linux,rc-map-name = "rc-x96max"; ++}; ++ ++&tdmif_b { ++ status = "okay"; ++}; ++ ++&tdmout_b { ++ status = "okay"; ++}; ++ ++&tohdmitx { ++ status = "okay"; ++}; ++ ++&uart_A { ++ status = "okay"; ++ pinctrl-0 = <&uart_a_pins>, <&uart_a_cts_rts_pins>; ++ pinctrl-names = "default"; ++ uart-has-rtscts; ++ ++ bluetooth: bluetooth { ++ compatible = "brcm,bcm43438-bt"; ++ interrupt-parent = <&gpio_intc>; ++ interrupts = <95 IRQ_TYPE_LEVEL_HIGH>; ++ interrupt-names = "host-wakeup"; ++ shutdown-gpios = <&gpio GPIOX_17 GPIO_ACTIVE_HIGH>; ++ max-speed = <2000000>; ++ clocks = <&wifi32k>; ++ clock-names = "lpo"; ++ vbat-supply = <&vddao_3v3>; ++ vddio-supply = <&vddio_ao1v8>; ++ status = "disabled"; ++ }; ++}; ++ ++&mali { ++ mali-supply=<&vddgpu>; ++}; ++ ++&usb { ++ dr_mode = "host"; ++}; ++ ++/* SDIO */ ++&sd_emmc_a { ++ /delete-property/ sd-uhs-sdr104; ++ sd-uhs-sdr12; ++ sd-uhs-sdr25; ++ sd-uhs-sdr50; ++ max-frequency = <100000000>; ++ ++ //sd-uhs-ddr50; ++ //max-frequency = <50000000>; ++ ++ //sd-uhs-sdr104; ++ //max-frequency = <200000000>; ++}; ++ ++/* SD card */ ++&sd_emmc_b { ++ cap-sd-highspeed; ++ max-frequency = <25000000>; ++}; ++ ++/* eMMC */ ++&sd_emmc_c { ++ max-frequency = <200000000>; ++}; ++ ++&cpu_opp_table { ++ opp-2016000000 { ++ opp-hz = /bits/ 64 <2016000000>; ++ opp-microvolt = <1000000>; ++ }; ++}; ++ ++&efuse { ++ eth_mac: eth_mac@0 { ++ reg = <0x0 0x06>; ++ }; ++ ++ bt_mac: bt_mac@6 { ++ reg = <0x6 0x06>; ++ }; ++ ++ wifi_mac: wifi_mac@12 { ++ reg = <0x0c 0x06>; ++ }; ++ ++ usid: usid@18 { ++ reg = <0x12 0x10>; ++ }; ++}; +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-sm1-x96-max-plus-ip1001m-2.dts mod/arch/arm64/boot/dts/amlogic/meson-sm1-x96-max-plus-ip1001m-2.dts +--- main/arch/arm64/boot/dts/amlogic/meson-sm1-x96-max-plus-ip1001m-2.dts 1970-01-01 01:00:00.000000000 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-sm1-x96-max-plus-ip1001m-2.dts 2023-03-07 09:42:05.553564539 +0100 +@@ -0,0 +1,44 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++/* ++ * Copyright (c) 2019 BayLibre SAS. All rights reserved. ++ * Copyright (c) 2020 Christian Hewitt ++ * Copyright (c) 2022 flippy ++ */ ++ ++/dts-v1/; ++ ++#include "meson-sm1-x96-max-plus-oc.dts" ++ ++ðmac { ++ phy-mode = "rgmii-txid"; ++ /* After a simple testing, temporarily set rx-internal-delay-ps to 2800 ps, ++ * if anyone finds a more suitable value please let me know. ++ */ ++ rx-internal-delay-ps = <2800>; ++}; ++ ++&ext_mdio { ++ /delete-node/ ethernet-phy@0; ++ ++ external_phy: ethernet-phy@1 { ++ /* ICPlus IP1001M: 0x02430d91 */ ++ reg = <1>; ++ max-speed = <1000>; ++ ++ reset-assert-us = <10000>; ++ reset-deassert-us = <80000>; ++ reset-gpios = <&gpio GPIOZ_15 (GPIO_ACTIVE_LOW | GPIO_OPEN_DRAIN)>; ++ ++ interrupt-parent = <&gpio_intc>; ++ /* MAC_INTR on GPIOZ_14 */ ++ interrupts = <26 IRQ_TYPE_LEVEL_LOW>; ++ }; ++}; ++ ++&bluetooth { ++ /* AM7256 module is based on broadcom brcm4354-sdio, ++ * so maybe bluetooth is available. ++ */ ++ compatible = "brcm,bcm43438-bt"; ++ status = "okay"; ++}; +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-sm1-x96-max-plus-ip1001m.dts mod/arch/arm64/boot/dts/amlogic/meson-sm1-x96-max-plus-ip1001m.dts +--- main/arch/arm64/boot/dts/amlogic/meson-sm1-x96-max-plus-ip1001m.dts 1970-01-01 01:00:00.000000000 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-sm1-x96-max-plus-ip1001m.dts 2023-03-07 09:42:05.593564847 +0100 +@@ -0,0 +1,43 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++/* ++ * Copyright (c) 2019 BayLibre SAS. All rights reserved. ++ * Copyright (c) 2020 Christian Hewitt ++ * Copyright (c) 2022 flippy ++ */ ++ ++/dts-v1/; ++ ++#include "meson-sm1-x96-max-plus-oc.dts" ++ ++ðmac { ++ phy-mode = "rgmii-txid"; ++ /* After a simple testing, temporarily set rx-internal-delay-ps to 2800 ps, ++ * if anyone finds a more suitable value please let me know. ++ */ ++ rx-internal-delay-ps = <2800>; ++}; ++ ++&ext_mdio { ++ /delete-node/ ethernet-phy@0; ++ ++ external_phy: ethernet-phy@3 { ++ /* ICPlus IP1001M: 0x02430d91 */ ++ reg = <3>; ++ max-speed = <1000>; ++ ++ reset-assert-us = <10000>; ++ reset-deassert-us = <80000>; ++ reset-gpios = <&gpio GPIOZ_15 (GPIO_ACTIVE_LOW | GPIO_OPEN_DRAIN)>; ++ ++ interrupt-parent = <&gpio_intc>; ++ /* MAC_INTR on GPIOZ_14 */ ++ interrupts = <26 IRQ_TYPE_LEVEL_LOW>; ++ }; ++}; ++ ++&bluetooth { ++ /* AM7256 module is based on broadcom brcm4354-sdio, ++ * so maybe bluetooth is available. ++ */ ++ status = "okay"; ++}; +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-sm1-x96-max-plus-oc.dts mod/arch/arm64/boot/dts/amlogic/meson-sm1-x96-max-plus-oc.dts +--- main/arch/arm64/boot/dts/amlogic/meson-sm1-x96-max-plus-oc.dts 1970-01-01 01:00:00.000000000 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-sm1-x96-max-plus-oc.dts 2023-03-07 09:42:05.601564909 +0100 +@@ -0,0 +1,24 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++/* ++ * Author: flippy ++ */ ++ ++/dts-v1/; ++ ++#include "meson-sm1-x96-max-plus.dts" ++ ++/ { ++ model = "AMedia X96 Max+ @ 2208Mhz"; ++}; ++ ++&cpu_opp_table { ++ opp-2100000000 { ++ opp-hz = /bits/ 64 <2100000000>; ++ opp-microvolt = <1011000>; ++ }; ++ ++ opp-2208000000 { ++ opp-hz = /bits/ 64 <2208000000>; ++ opp-microvolt = <1021000>; ++ }; ++}; +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-sm1-x96-max-plus-q1.dts mod/arch/arm64/boot/dts/amlogic/meson-sm1-x96-max-plus-q1.dts +--- main/arch/arm64/boot/dts/amlogic/meson-sm1-x96-max-plus-q1.dts 1970-01-01 01:00:00.000000000 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-sm1-x96-max-plus-q1.dts 2023-03-07 09:42:05.641565220 +0100 +@@ -0,0 +1,41 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++/* ++ * Copyright (c) 2019 BayLibre SAS. All rights reserved. ++ * Copyright (c) 2020 Christian Hewitt ++ * Copyright (c) 2022 Flippy ++ */ ++ ++/dts-v1/; ++ ++#include "meson-sm1-x96-air.dts" ++ ++/ { ++ compatible = "amediatech,x96-max", "amlogic,sm1"; ++ model = "X96 Max Plus Q1"; ++ ++ aliases { ++ serial0 = &uart_AO; ++ ethernet0 = ðmac; ++ }; ++ ++ memory@0 { ++ device_type = "memory"; ++ reg = <0x0 0x0 0x0 0xf0800000>; ++ }; ++}; ++ ++&uart_AO { ++ status = "okay"; ++ pinctrl-0 = <&uart_ao_a_pins>; ++ pinctrl-names = "default"; ++}; ++ ++ðmac { ++ status = "okay"; ++ phy-handle = <&internal_ephy>; ++ phy-mode = "rmii"; ++}; ++ ++&internal_ephy { ++ max-speed = <100>; ++}; +diff -ruN main/arch/arm64/boot/dts/amlogic/meson-sm1-x96-max-plus-q2.dts mod/arch/arm64/boot/dts/amlogic/meson-sm1-x96-max-plus-q2.dts +--- main/arch/arm64/boot/dts/amlogic/meson-sm1-x96-max-plus-q2.dts 1970-01-01 01:00:00.000000000 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/meson-sm1-x96-max-plus-q2.dts 2023-03-07 09:42:05.649565281 +0100 +@@ -0,0 +1,21 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++/* ++ * Copyright (c) 2022 danboid, flippy ++ */ ++ ++/dts-v1/; ++ ++#include "meson-sm1-h96-max.dts" ++ ++/ { ++ compatible = "x96-max-plus-q2,x96-air-q1000", "amlogic,sm1"; ++ model = "X96 MAX PLUS Q2, X96 Air Q1000"; ++ ++}; ++ ++&uart_A { ++ bluetooth { ++ compatible = "qcom,qca9377-bt"; ++ enable-gpios = <&gpio GPIOX_17 GPIO_ACTIVE_HIGH>; ++ }; ++}; +diff -ruN main/arch/arm64/boot/dts/amlogic/overlay/Makefile mod/arch/arm64/boot/dts/amlogic/overlay/Makefile +--- main/arch/arm64/boot/dts/amlogic/overlay/Makefile 1970-01-01 01:00:00.000000000 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/overlay/Makefile 2023-03-07 09:42:06.005568040 +0100 +@@ -0,0 +1,21 @@ ++# SPDX-License-Identifier: GPL-2.0 ++dtbo-$(CONFIG_ARCH_MESON) += \ ++ meson-i2cA.dtbo \ ++ meson-i2cB.dtbo \ ++ meson-openvfd.dtbo \ ++ meson-uartA.dtbo \ ++ meson-uartC.dtbo \ ++ meson-w1-gpio.dtbo \ ++ meson-w1AB-gpio.dtbo \ ++ meson-g12-gxl-cma-pool-896MB.dtbo ++ ++scr-$(CONFIG_ARCH_MESON) += \ ++ meson-fixup.scr ++ ++dtbotxt-$(CONFIG_ARCH_MESON) += \ ++ README.meson-overlays ++ ++targets += $(dtbo-y) $(scr-y) $(dtbotxt-y) ++ ++always := $(dtbo-y) $(scr-y) $(dtbotxt-y) ++clean-files := *.dtbo *.scr +diff -ruN main/arch/arm64/boot/dts/amlogic/overlay/meson-fixup.scr-cmd mod/arch/arm64/boot/dts/amlogic/overlay/meson-fixup.scr-cmd +--- main/arch/arm64/boot/dts/amlogic/overlay/meson-fixup.scr-cmd 1970-01-01 01:00:00.000000000 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/overlay/meson-fixup.scr-cmd 2023-03-07 09:42:06.041568318 +0100 +@@ -0,0 +1,4 @@ ++# overlays fixup script ++# implements (or rather substitutes) overlay arguments functionality ++# using u-boot scripting, environment variables and "fdt" command ++ +diff -ruN main/arch/arm64/boot/dts/amlogic/overlay/meson-g12-gxl-cma-pool-896MB.dts mod/arch/arm64/boot/dts/amlogic/overlay/meson-g12-gxl-cma-pool-896MB.dts +--- main/arch/arm64/boot/dts/amlogic/overlay/meson-g12-gxl-cma-pool-896MB.dts 1970-01-01 01:00:00.000000000 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/overlay/meson-g12-gxl-cma-pool-896MB.dts 2023-03-07 09:42:06.057568442 +0100 +@@ -0,0 +1,19 @@ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "amlogic,g12a", "amlogic,g12b", "amlogic,meson-gxl"; ++ ++ fragment@0 { ++ target-path = "/reserved-memory"; ++ __overlay__ { ++ linux,cma { ++ compatible = "shared-dma-pool"; ++ reusable; ++ size = <0x0 0x38000000>; ++ alignment = <0x0 0x400000>; ++ linux,cma-default; ++ }; ++ }; ++ }; ++}; +diff -ruN main/arch/arm64/boot/dts/amlogic/overlay/meson-i2cA.dts mod/arch/arm64/boot/dts/amlogic/overlay/meson-i2cA.dts +--- main/arch/arm64/boot/dts/amlogic/overlay/meson-i2cA.dts 1970-01-01 01:00:00.000000000 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/overlay/meson-i2cA.dts 2023-03-07 09:42:06.073568564 +0100 +@@ -0,0 +1,17 @@ ++/dts-v1/; ++ ++/ { ++ compatible = "amlogic,meson-gxbb"; ++ fragment@0 { ++ target-path = "/aliases"; ++ __overlay__ { ++ i2cA = "/soc/bus@c1100000/i2c@8500"; ++ }; ++ }; ++ fragment@1 { ++ target-path = "/soc/bus@c1100000/i2c@8500"; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++}; +diff -ruN main/arch/arm64/boot/dts/amlogic/overlay/meson-i2cB.dts mod/arch/arm64/boot/dts/amlogic/overlay/meson-i2cB.dts +--- main/arch/arm64/boot/dts/amlogic/overlay/meson-i2cB.dts 1970-01-01 01:00:00.000000000 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/overlay/meson-i2cB.dts 2023-03-07 09:42:06.129568997 +0100 +@@ -0,0 +1,17 @@ ++/dts-v1/; ++ ++/ { ++ compatible = "amlogic,meson-gxbb"; ++ fragment@0 { ++ target-path = "/aliases"; ++ __overlay__ { ++ i2cA = "/soc/bus@c1100000/i2c@87c0"; ++ }; ++ }; ++ fragment@1 { ++ target-path = "/soc/bus@c1100000/i2c@87c0"; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++}; +diff -ruN main/arch/arm64/boot/dts/amlogic/overlay/meson-openvfd.dts mod/arch/arm64/boot/dts/amlogic/overlay/meson-openvfd.dts +--- main/arch/arm64/boot/dts/amlogic/overlay/meson-openvfd.dts 1970-01-01 01:00:00.000000000 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/overlay/meson-openvfd.dts 2023-03-07 09:42:06.153569185 +0100 +@@ -0,0 +1,10 @@ ++/dts-v1/; ++/plugin/; ++ ++&{/} { ++ openvfd: openvfd { ++ compatible = "open,vfd"; ++ dev_name = "openvfd"; ++ status = "okay"; ++ }; ++}; +\ Kein Zeilenumbruch am Dateiende. +diff -ruN main/arch/arm64/boot/dts/amlogic/overlay/meson-uartA.dts mod/arch/arm64/boot/dts/amlogic/overlay/meson-uartA.dts +--- main/arch/arm64/boot/dts/amlogic/overlay/meson-uartA.dts 1970-01-01 01:00:00.000000000 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/overlay/meson-uartA.dts 2023-03-07 09:42:06.189569461 +0100 +@@ -0,0 +1,11 @@ ++/dts-v1/; ++ ++/ { ++ compatible = "amlogic,meson-gxbb"; ++ fragment@0 { ++ target-path = "/soc/bus@c1100000/serial@84c0"; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++}; +diff -ruN main/arch/arm64/boot/dts/amlogic/overlay/meson-uartC.dts mod/arch/arm64/boot/dts/amlogic/overlay/meson-uartC.dts +--- main/arch/arm64/boot/dts/amlogic/overlay/meson-uartC.dts 1970-01-01 01:00:00.000000000 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/overlay/meson-uartC.dts 2023-03-07 09:42:06.201569555 +0100 +@@ -0,0 +1,11 @@ ++/dts-v1/; ++ ++/ { ++ compatible = "amlogic,meson-gxbb"; ++ fragment@0 { ++ target-path = "/soc/bus@c1100000/serial@8700"; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++}; +diff -ruN main/arch/arm64/boot/dts/amlogic/overlay/meson-w1AB-gpio.dts mod/arch/arm64/boot/dts/amlogic/overlay/meson-w1AB-gpio.dts +--- main/arch/arm64/boot/dts/amlogic/overlay/meson-w1AB-gpio.dts 1970-01-01 01:00:00.000000000 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/overlay/meson-w1AB-gpio.dts 2023-03-07 09:42:06.245569896 +0100 +@@ -0,0 +1,32 @@ ++// Definitions for w1-gpio module (without external pullup) ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "amlogic,meson-gxbb"; ++ ++ fragment@0 { ++ target-path = "/"; ++ __overlay__ { ++ ++ w1a: onewire@0 { ++ compatible = "w1-gpio"; ++ pinctrl-names = "default"; ++ gpios = <&gpio 91 6>; // GPIOY_16 ++ status = "okay"; ++ }; ++ }; ++ }; ++ fragment@1 { ++ target-path = "/"; ++ __overlay__ { ++ ++ w1b: onewire@1 { ++ compatible = "w1-gpio"; ++ pinctrl-names = "default"; ++ gpios = <&gpio 90 6>; // GPIOY_15 ++ status = "okay"; ++ }; ++ }; ++ }; ++}; +diff -ruN main/arch/arm64/boot/dts/amlogic/overlay/meson-w1-gpio.dts mod/arch/arm64/boot/dts/amlogic/overlay/meson-w1-gpio.dts +--- main/arch/arm64/boot/dts/amlogic/overlay/meson-w1-gpio.dts 1970-01-01 01:00:00.000000000 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/overlay/meson-w1-gpio.dts 2023-03-07 09:42:06.225569740 +0100 +@@ -0,0 +1,20 @@ ++// Definitions for w1-gpio module (without external pullup) ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "amlogic,meson-gxbb"; ++ ++ fragment@0 { ++ target-path = "/"; ++ __overlay__ { ++ ++ w1: onewire@0 { ++ compatible = "w1-gpio"; ++ pinctrl-names = "default"; ++ gpios = <&gpio 91 6>; // GPIOY_16 ++ status = "okay"; ++ }; ++ }; ++ }; ++}; +diff -ruN main/arch/arm64/boot/dts/amlogic/overlay/README.meson-overlays mod/arch/arm64/boot/dts/amlogic/overlay/README.meson-overlays +--- main/arch/arm64/boot/dts/amlogic/overlay/README.meson-overlays 1970-01-01 01:00:00.000000000 +0100 ++++ mod/arch/arm64/boot/dts/amlogic/overlay/README.meson-overlays 2023-03-07 09:42:06.273570112 +0100 +@@ -0,0 +1,20 @@ ++This document describes overlays provided in the kernel packages ++For generic Armbian overlays documentation please see ++https://docs.armbian.com/User-Guide_Allwinner_overlays/ ++ ++### Platform: ++ ++meson (Amlogic) ++ ++### Provided overlays: ++ ++- i2c8 ++ ++### Overlay details: ++ ++### i2c8 ++ ++Activates TWI/I2C bus 8 ++ ++I2C8 pins (SCL, SDA): GPIO1-C4, GPIO1-C5 ++ +diff -ruN main/drivers/auxdisplay/Kconfig mod/drivers/auxdisplay/Kconfig +--- main/drivers/auxdisplay/Kconfig 2023-03-07 09:42:01.205530836 +0100 ++++ mod/drivers/auxdisplay/Kconfig 2023-03-07 09:42:01.321531736 +0100 +@@ -203,6 +203,41 @@ + line and the Linux version on the second line, but that's + still useful. + ++config TM1628 ++ tristate "TM1628 driver for LED 7/11 segment displays" ++ depends on SPI ++ depends on OF || COMPILE_TEST ++ help ++ Say Y to enable support for Titan Micro Electronics TM1628 ++ LED controller. ++ ++ It's a 3-wire SPI device controlling a two-dimensional grid of ++ LEDs. Dimming is applied to all outputs through an internal PWM. ++ ++config OPENVFD ++ tristate "OpenVFD LED display driver" ++ depends on SPI ++ depends on I2C ++ depends on OF ++ help ++ Say Y to enable support for openvfd LED controller. ++ ++ This repository contains the source code for the FD628 and similar LED ++ display controllers. ++ ++ The FD628 controller is often used in Android TV boxes with a 7 segment ++ LED display at the front. ++ ++ Although the FD628 controller has support for a multitude of different ++ display configurations, the current implementation only supports common ++ cathode and common anode displays with 7 segments. The driver can also ++ support FD650, which uses a variation of the I2C communication protocol. ++ ++ In addition it supports HD44780 text based LCD displays, using an I2C ++ backpack. ++ ++ Sources: https://github.com/arthur-liberman/linux_openvfd ++ + menuconfig PARPORT_PANEL + tristate "Parallel port LCD/Keypad Panel support" + depends on PARPORT +diff -ruN main/drivers/auxdisplay/Makefile mod/drivers/auxdisplay/Makefile +--- main/drivers/auxdisplay/Makefile 2023-03-07 09:42:01.201530804 +0100 ++++ mod/drivers/auxdisplay/Makefile 2023-03-07 09:42:01.321531736 +0100 +@@ -14,3 +14,5 @@ + obj-$(CONFIG_PARPORT_PANEL) += panel.o + obj-$(CONFIG_LCD2S) += lcd2s.o + obj-$(CONFIG_LINEDISP) += line-display.o ++obj-$(CONFIG_TM1628) += tm1628.o ++obj-$(CONFIG_OPENVFD) += openvfd/ +diff -ruN main/drivers/auxdisplay/openvfd/controllers/controller.h mod/drivers/auxdisplay/openvfd/controllers/controller.h +--- main/drivers/auxdisplay/openvfd/controllers/controller.h 1970-01-01 01:00:00.000000000 +0100 ++++ mod/drivers/auxdisplay/openvfd/controllers/controller.h 2023-03-07 09:42:01.469532884 +0100 +@@ -0,0 +1,28 @@ ++#ifndef __CONTROLLERH__ ++#define __CONTROLLERH__ ++ ++#include "../openvfd_drv.h" ++ ++struct controller_interface { ++ unsigned char (*init)(void); ++ ++ unsigned short (*get_brightness_levels_count)(void); ++ unsigned short (*get_brightness_level)(void); ++ unsigned char (*set_brightness_level)(unsigned short level); ++ ++ unsigned char (*get_power)(void); ++ void (*set_power)(unsigned char state); ++ void (*power_suspend)(void); ++ void (*power_resume)(void); ++ ++ struct vfd_display *(*get_display_type)(void); ++ unsigned char (*set_display_type)(struct vfd_display *display); ++ ++ void (*set_icon)(const char *name, unsigned char state); ++ ++ size_t (*read_data)(unsigned char *data, size_t length); ++ size_t (*write_data)(const unsigned char *data, size_t length); ++ size_t (*write_display_data)(const struct vfd_display_data *data); ++}; ++ ++#endif +diff -ruN main/drivers/auxdisplay/openvfd/controllers/controller_list.h mod/drivers/auxdisplay/openvfd/controllers/controller_list.h +--- main/drivers/auxdisplay/openvfd/controllers/controller_list.h 1970-01-01 01:00:00.000000000 +0100 ++++ mod/drivers/auxdisplay/openvfd/controllers/controller_list.h 2023-03-07 09:42:01.469532884 +0100 +@@ -0,0 +1,12 @@ ++#ifndef __CONTROLLER_LIST_H__ ++#define __CONTROLLER_LIST_H__ ++ ++#include "dummy.h" ++#include "fd628.h" ++#include "fd650.h" ++#include "hd44780.h" ++#include "ssd1306.h" ++#include "pcd8544.h" ++#include "il3829.h" ++ ++#endif +diff -ruN main/drivers/auxdisplay/openvfd/controllers/dummy.c mod/drivers/auxdisplay/openvfd/controllers/dummy.c +--- main/drivers/auxdisplay/openvfd/controllers/dummy.c 1970-01-01 01:00:00.000000000 +0100 ++++ mod/drivers/auxdisplay/openvfd/controllers/dummy.c 2023-03-07 09:42:01.501533134 +0100 +@@ -0,0 +1,99 @@ ++#include "dummy.h" ++ ++static unsigned char dummy_init(void); ++static unsigned short dummy_get_brightness_levels_count(void); ++static unsigned short dummy_get_brightness_level(void); ++static unsigned char dummy_set_brightness_level(unsigned short level); ++static unsigned char dummy_get_power(void); ++static void dummy_set_power(unsigned char state); ++static struct vfd_display *dummy_get_display_type(void); ++static unsigned char dummy_set_display_type(struct vfd_display *display); ++static void dummy_set_icon(const char *name, unsigned char state); ++static size_t dummy_read_data(unsigned char *data, size_t length); ++static size_t dummy_write_data(const unsigned char *data, size_t length); ++static size_t dummy_write_display_data(const struct vfd_display_data *data); ++ ++static struct controller_interface dummy_interface = { ++ .init = dummy_init, ++ .get_brightness_levels_count = dummy_get_brightness_levels_count, ++ .get_brightness_level = dummy_get_brightness_level, ++ .set_brightness_level = dummy_set_brightness_level, ++ .get_power = dummy_get_power, ++ .set_power = dummy_set_power, ++ .get_display_type = dummy_get_display_type, ++ .set_display_type = dummy_set_display_type, ++ .set_icon = dummy_set_icon, ++ .read_data = dummy_read_data, ++ .write_data = dummy_write_data, ++ .write_display_data = dummy_write_display_data, ++}; ++ ++static struct vfd_dev *dev = NULL; ++ ++struct controller_interface *init_dummy(struct vfd_dev *_dev) ++{ ++ dev = _dev; ++ return &dummy_interface; ++} ++ ++static unsigned char dummy_init(void) ++{ ++ return 1; ++} ++ ++static unsigned short dummy_get_brightness_levels_count(void) ++{ ++ return 8; ++} ++ ++static unsigned short dummy_get_brightness_level(void) ++{ ++ return dev->brightness; ++} ++ ++static unsigned char dummy_set_brightness_level(unsigned short level) ++{ ++ dev->brightness = level & 0x7; ++ dev->power = 1; ++ return 1; ++} ++ ++static unsigned char dummy_get_power(void) ++{ ++ return dev->power; ++} ++ ++static void dummy_set_power(unsigned char state) ++{ ++ dev->power = state; ++} ++ ++static struct vfd_display *dummy_get_display_type(void) ++{ ++ return &dev->dtb_active.display; ++} ++ ++static unsigned char dummy_set_display_type(struct vfd_display *display) ++{ ++ dev->dtb_active.display = *display; ++ return 1; ++} ++ ++static void dummy_set_icon(const char *name, unsigned char state) ++{ ++} ++ ++static size_t dummy_read_data(unsigned char *data, size_t length) ++{ ++ return 0; ++} ++ ++static size_t dummy_write_data(const unsigned char *_data, size_t length) ++{ ++ return length; ++} ++ ++static size_t dummy_write_display_data(const struct vfd_display_data *data) ++{ ++ return sizeof(*data); ++} +diff -ruN main/drivers/auxdisplay/openvfd/controllers/dummy.h mod/drivers/auxdisplay/openvfd/controllers/dummy.h +--- main/drivers/auxdisplay/openvfd/controllers/dummy.h 1970-01-01 01:00:00.000000000 +0100 ++++ mod/drivers/auxdisplay/openvfd/controllers/dummy.h 2023-03-07 09:42:01.509533196 +0100 +@@ -0,0 +1,8 @@ ++#ifndef __DUMMYH__ ++#define __DUMMYH__ ++ ++#include "controller.h" ++ ++struct controller_interface *init_dummy(struct vfd_dev *dev); ++ ++#endif +diff -ruN main/drivers/auxdisplay/openvfd/controllers/fd628.c mod/drivers/auxdisplay/openvfd/controllers/fd628.c +--- main/drivers/auxdisplay/openvfd/controllers/fd628.c 1970-01-01 01:00:00.000000000 +0100 ++++ mod/drivers/auxdisplay/openvfd/controllers/fd628.c 2023-03-07 09:42:01.521533289 +0100 +@@ -0,0 +1,375 @@ ++#include "../protocols/i2c_sw.h" ++#include "../protocols/spi_sw.h" ++#include "fd628.h" ++ ++/* ****************************** Define FD628 Commands ****************************** */ ++#define FD628_KEY_RDCMD 0x42 /* Read keys command */ ++#define FD628_4DIG_CMD 0x00 /* Set FD628 to work in 4-digit mode */ ++#define FD628_5DIG_CMD 0x01 /* Set FD628 to work in 5-digit mode */ ++#define FD628_6DIG_CMD 0x02 /* Set FD628 to work in 6-digit mode */ ++#define FD628_7DIG_CMD 0x03 /* Set FD628 to work in 7-digit mode */ ++#define FD628_DIGADDR_WRCMD 0xC0 /* Write FD628 address */ ++#define FD628_ADDR_INC_DIGWR_CMD 0x40 /* Set Address Increment Mode */ ++#define FD628_ADDR_STATIC_DIGWR_CMD 0x44 /* Set Static Address Mode */ ++#define FD628_DISP_STATUE_WRCMD 0x80 /* Set display brightness command */ ++/* *********************************************************************************** */ ++ ++static unsigned char fd628_init(void); ++static unsigned short fd628_get_brightness_levels_count(void); ++static unsigned short fd628_get_brightness_level(void); ++static unsigned char fd628_set_brightness_level(unsigned short level); ++static unsigned char fd628_get_power(void); ++static void fd628_set_power(unsigned char state); ++static void fd628_power_suspend(void) { fd628_set_power(0); } ++static void fd628_power_resume(void) { fd628_set_power(1); } ++static struct vfd_display *fd628_get_display_type(void); ++static unsigned char fd628_set_display_type(struct vfd_display *display); ++static void fd628_set_icon(const char *name, unsigned char state); ++static size_t fd628_read_data(unsigned char *data, size_t length); ++static size_t fd628_write_data(const unsigned char *data, size_t length); ++static size_t fd628_write_display_data(const struct vfd_display_data *data); ++ ++static struct controller_interface fd628_interface = { ++ .init = fd628_init, ++ .get_brightness_levels_count = fd628_get_brightness_levels_count, ++ .get_brightness_level = fd628_get_brightness_level, ++ .set_brightness_level = fd628_set_brightness_level, ++ .get_power = fd628_get_power, ++ .set_power = fd628_set_power, ++ .power_suspend = fd628_power_suspend, ++ .power_resume = fd628_power_resume, ++ .get_display_type = fd628_get_display_type, ++ .set_display_type = fd628_set_display_type, ++ .set_icon = fd628_set_icon, ++ .read_data = fd628_read_data, ++ .write_data = fd628_write_data, ++ .write_display_data = fd628_write_display_data, ++}; ++ ++size_t seg7_write_display_data(const struct vfd_display_data *data, unsigned short *raw_wdata, size_t sz); ++ ++static struct vfd_dev *dev = NULL; ++static struct protocol_interface *protocol = NULL; ++static unsigned char ram_grid_size = 2; ++static unsigned char ram_grid_count = 7; ++static unsigned char ram_size = 14; ++static struct vfd_display_data vfd_display_data; ++extern const led_bitmap *ledCodes; ++extern unsigned char ledDot; ++ ++struct controller_interface *init_fd628(struct vfd_dev *_dev) ++{ ++ dev = _dev; ++ return &fd628_interface; ++} ++ ++static size_t fd628_write_data_real(unsigned char address, const unsigned char *data, size_t length) ++{ ++ unsigned char cmd = FD628_DIGADDR_WRCMD | address; ++ if (length + address > ram_size) ++ return (-1); ++ ++ protocol->write_byte(FD628_ADDR_INC_DIGWR_CMD); ++ protocol->write_cmd_data(&cmd, 1, data, length); ++ return (0); ++} ++ ++static unsigned char fd628_init(void) ++{ ++ unsigned char slow_freq = dev->dtb_active.display.flags & DISPLAY_FLAG_LOW_FREQ; ++ protocol = dev->dtb_active.display.controller == CONTROLLER_HBS658 ? ++ init_sw_i2c(0, LSB_FIRST, 1, dev->clk_pin, dev->dat_pin, slow_freq ? I2C_DELAY_20KHz : I2C_DELAY_100KHz, NULL) : ++ init_sw_spi_3w(LSB_FIRST, dev->clk_pin, dev->dat_pin, dev->stb_pin, slow_freq ? SPI_DELAY_20KHz : SPI_DELAY_100KHz); ++ if (!protocol) ++ return 0; ++ ++ switch(dev->dtb_active.display.type) { ++ case DISPLAY_TYPE_5D_7S_T95: ++ ledCodes = LED_decode_tab1; ++ break; ++ case DISPLAY_TYPE_5D_7S_G9SX: ++ ledCodes = LED_decode_tab3; ++ break; ++ case DISPLAY_TYPE_5D_7S_TAP1: ++ ledCodes = LED_decode_tab5; ++ break; ++ default: ++ ledCodes = LED_decode_tab2; ++ break; ++ } ++ switch (dev->dtb_active.display.controller) { ++ case CONTROLLER_FD628: ++ default: ++ ram_grid_size = 2; ++ ram_grid_count = 7; ++ protocol->write_byte(FD628_7DIG_CMD); ++ break; ++ case CONTROLLER_FD620: ++ ram_grid_size = 2; ++ ram_grid_count = 5; ++ switch (dev->dtb_active.display.type) { ++ case DISPLAY_TYPE_FD620_REF: ++ protocol->write_byte(FD628_4DIG_CMD); ++ break; ++ default: ++ protocol->write_byte(FD628_5DIG_CMD); ++ break; ++ } ++ break; ++ case CONTROLLER_TM1618: ++ ram_grid_size = 2; ++ ram_grid_count = 7; ++ switch (dev->dtb_active.display.type) { ++ case DISPLAY_TYPE_4D_7S_COL: ++ protocol->write_byte(FD628_7DIG_CMD); ++ break; ++ case DISPLAY_TYPE_FD620_REF: ++ protocol->write_byte(FD628_4DIG_CMD); ++ break; ++ default: ++ protocol->write_byte(FD628_5DIG_CMD); ++ break; ++ } ++ break; ++ case CONTROLLER_HBS658: ++ ram_grid_size = 1; ++ ram_grid_count = 5; ++ break; ++ } ++ ++ ram_size = ram_grid_size * ram_grid_count; ++ memset(dev->wbuf, 0x00, sizeof(dev->wbuf)); ++ fd628_write_data((unsigned char *)dev->wbuf, sizeof(dev->wbuf)); ++ fd628_set_brightness_level(dev->brightness); ++ return 1; ++} ++ ++static unsigned short fd628_get_brightness_levels_count(void) ++{ ++ return 8; ++} ++ ++static unsigned short fd628_get_brightness_level(void) ++{ ++ return dev->brightness; ++} ++ ++static unsigned char fd628_set_brightness_level(unsigned short level) ++{ ++ dev->brightness = level & 0x7; ++ protocol->write_byte(FD628_DISP_STATUE_WRCMD | dev->brightness | FD628_DISP_ON); ++ dev->power = 1; ++ return 1; ++} ++ ++static unsigned char fd628_get_power(void) ++{ ++ return dev->power; ++} ++ ++static void fd628_set_power(unsigned char state) ++{ ++ dev->power = state; ++ if (state) ++ fd628_set_brightness_level(dev->brightness); ++ else ++ protocol->write_byte(FD628_DISP_STATUE_WRCMD | FD628_DISP_OFF); ++} ++ ++static struct vfd_display *fd628_get_display_type(void) ++{ ++ return &dev->dtb_active.display; ++} ++ ++static unsigned char fd628_set_display_type(struct vfd_display *display) ++{ ++ unsigned char ret = 0; ++ if (display->type < DISPLAY_TYPE_MAX && display->controller < CONTROLLER_7S_MAX && display->controller == CONTROLLER_FD650) ++ { ++ dev->dtb_active.display = *display; ++ fd628_init(); ++ ret = 1; ++ } ++ ++ return ret; ++} ++ ++static void fd628_set_icon(const char *name, unsigned char state) ++{ ++ struct vfd_dtb_config *dtb = &dev->dtb_active; ++ switch (dtb->display.type) { ++ case DISPLAY_TYPE_5D_7S_NORMAL: ++ case DISPLAY_TYPE_5D_7S_T95: ++ case DISPLAY_TYPE_5D_7S_G9SX: ++ default: ++ if (strncmp(name,"alarm",5) == 0) { ++ dev->status_led_mask = state ? (dev->status_led_mask | dtb->led_dots[LED_DOT1_ALARM]) : (dev->status_led_mask & ~dtb->led_dots[LED_DOT1_ALARM]); ++ } else if (strncmp(name,"usb",3) == 0) { ++ dev->status_led_mask = state ? (dev->status_led_mask | dtb->led_dots[LED_DOT1_USB]) : (dev->status_led_mask & ~dtb->led_dots[LED_DOT1_USB]); ++ } else if (strncmp(name,"play",4) == 0) { ++ dev->status_led_mask = state ? (dev->status_led_mask | dtb->led_dots[LED_DOT1_PLAY]) : (dev->status_led_mask & ~dtb->led_dots[LED_DOT1_PLAY]); ++ } else if (strncmp(name,"pause",5) == 0) { ++ dev->status_led_mask = state ? (dev->status_led_mask | dtb->led_dots[LED_DOT1_PAUSE]) : (dev->status_led_mask & ~dtb->led_dots[LED_DOT1_PAUSE]); ++ } else if (strncmp(name,"colon",5) == 0) { ++ dev->status_led_mask = state ? (dev->status_led_mask | dtb->led_dots[LED_DOT1_SEC]) : (dev->status_led_mask & ~dtb->led_dots[LED_DOT1_SEC]); ++ } else if (strncmp(name,"eth",3) == 0) { ++ dev->status_led_mask = state ? (dev->status_led_mask | dtb->led_dots[LED_DOT1_ETH]) : (dev->status_led_mask & ~dtb->led_dots[LED_DOT1_ETH]); ++ } else if (strncmp(name,"wifi",4) == 0) { ++ dev->status_led_mask = state ? (dev->status_led_mask | dtb->led_dots[LED_DOT1_WIFI]) : (dev->status_led_mask & ~dtb->led_dots[LED_DOT1_WIFI]); ++ } ++ break; ++ case DISPLAY_TYPE_5D_7S_X92: ++ if (strncmp(name,"apps",4) == 0) { ++ dev->status_led_mask = state ? (dev->status_led_mask | dtb->led_dots[LED_DOT2_APPS]) : (dev->status_led_mask & ~dtb->led_dots[LED_DOT2_APPS]); ++ } else if (strncmp(name,"setup",5) == 0) { ++ dev->status_led_mask = state ? (dev->status_led_mask | dtb->led_dots[LED_DOT2_SETUP]) : (dev->status_led_mask & ~dtb->led_dots[LED_DOT2_SETUP]); ++ } else if (strncmp(name,"usb",3) == 0) { ++ dev->status_led_mask = state ? (dev->status_led_mask | dtb->led_dots[LED_DOT2_USB]) : (dev->status_led_mask & ~dtb->led_dots[LED_DOT2_USB]); ++ } else if (strncmp(name,"sd",2) == 0) { ++ dev->status_led_mask = state ? (dev->status_led_mask | dtb->led_dots[LED_DOT2_CARD]) : (dev->status_led_mask & ~dtb->led_dots[LED_DOT2_CARD]); ++ } else if (strncmp(name,"colon",5) == 0) { ++ dev->status_led_mask = state ? (dev->status_led_mask | dtb->led_dots[LED_DOT2_SEC]) : (dev->status_led_mask & ~dtb->led_dots[LED_DOT2_SEC]); ++ } else if (strncmp(name,"hdmi",4) == 0) { ++ dev->status_led_mask = state ? (dev->status_led_mask | dtb->led_dots[LED_DOT2_HDMI]) : (dev->status_led_mask & ~dtb->led_dots[LED_DOT2_HDMI]); ++ } else if (strncmp(name,"cvbs",4) == 0) { ++ dev->status_led_mask = state ? (dev->status_led_mask | dtb->led_dots[LED_DOT2_CVBS]) : (dev->status_led_mask & ~dtb->led_dots[LED_DOT2_CVBS]); ++ } ++ break; ++ case DISPLAY_TYPE_5D_7S_ABOX: ++ if (strncmp(name,"power",5) == 0) { ++ dev->status_led_mask = state ? (dev->status_led_mask | dtb->led_dots[LED_DOT3_POWER]) : (dev->status_led_mask & ~dtb->led_dots[LED_DOT3_POWER]); ++ } else if (strncmp(name,"eth",3) == 0) { ++ dev->status_led_mask = state ? (dev->status_led_mask | dtb->led_dots[LED_DOT3_LAN]) : (dev->status_led_mask & ~dtb->led_dots[LED_DOT3_LAN]); ++ } else if (strncmp(name,"colon",5) == 0) { ++ dev->status_led_mask = state ? (dev->status_led_mask | dtb->led_dots[LED_DOT3_SEC]) : (dev->status_led_mask & ~dtb->led_dots[LED_DOT3_SEC]); ++ } else if (strncmp(name,"wifi",4) == 0) { ++ dev->status_led_mask = state ? (dev->status_led_mask | dtb->led_dots[LED_DOT3_WIFIHI] | dtb->led_dots[LED_DOT3_WIFILO]) : (dev->status_led_mask & ~(dtb->led_dots[LED_DOT3_WIFIHI] | dtb->led_dots[LED_DOT3_WIFILO])); ++ } ++ break; ++ case DISPLAY_TYPE_5D_7S_M9_PRO: ++ if (strncmp(name,"b-t",3) == 0) { ++ dev->status_led_mask = state ? (dev->status_led_mask | dtb->led_dots[LED_DOT4_BT]) : (dev->status_led_mask & ~dtb->led_dots[LED_DOT4_BT]); ++ } else if (strncmp(name,"eth",3) == 0) { ++ dev->status_led_mask = state ? (dev->status_led_mask | dtb->led_dots[LED_DOT4_ETH]) : (dev->status_led_mask & ~dtb->led_dots[LED_DOT4_ETH]); ++ } else if (strncmp(name,"wifi",4) == 0) { ++ dev->status_led_mask = state ? (dev->status_led_mask | dtb->led_dots[LED_DOT4_WIFI]) : (dev->status_led_mask & ~dtb->led_dots[LED_DOT4_WIFI]); ++ } else if (strncmp(name,"spdif",5) == 0) { ++ dev->status_led_mask = state ? (dev->status_led_mask | dtb->led_dots[LED_DOT4_SPDIF]) : (dev->status_led_mask & ~dtb->led_dots[LED_DOT4_SPDIF]); ++ } else if (strncmp(name,"colon",5) == 0) { ++ dev->status_led_mask = state ? (dev->status_led_mask | dtb->led_dots[LED_DOT4_SEC]) : (dev->status_led_mask & ~dtb->led_dots[LED_DOT4_SEC]); ++ } else if (strncmp(name,"hdmi",4) == 0) { ++ dev->status_led_mask = state ? (dev->status_led_mask | dtb->led_dots[LED_DOT4_HDMI]) : (dev->status_led_mask & ~dtb->led_dots[LED_DOT4_HDMI]); ++ } else if (strncmp(name,"cvbs",4) == 0) { ++ dev->status_led_mask = state ? (dev->status_led_mask | dtb->led_dots[LED_DOT4_AV]) : (dev->status_led_mask & ~dtb->led_dots[LED_DOT4_AV]); ++ } ++ break; ++ } ++} ++ ++static size_t fd628_read_data(unsigned char *data, size_t length) ++{ ++ protocol->write_byte(FD628_KEY_RDCMD); ++ return protocol->read_data(data, length) == 0 ? length : -1; ++} ++ ++extern void transpose8rS64(unsigned char* A, unsigned char* B); ++ ++static size_t fd628_write_data(const unsigned char *_data, size_t length) ++{ ++ size_t i; ++ struct vfd_dtb_config *dtb = &dev->dtb_active; ++ unsigned short *data = (unsigned short *)_data; ++ ++ memset(dev->wbuf, 0x00, sizeof(dev->wbuf)); ++ length = length > ram_size ? ram_grid_count : (length / sizeof(unsigned short)); ++ if (data[0] & ledDots[LED_DOT_SEC]) { ++ data[0] &= ~ledDots[LED_DOT_SEC]; ++ data[0] |= dtb->led_dots[LED_DOT_SEC]; ++ } ++ // Apply LED indicators mask (usb, eth, wifi etc.) ++ if (vfd_display_data.mode == DISPLAY_MODE_CLOCK) ++ data[0] |= dev->status_led_mask; ++ else ++ data[0] |= (dev->status_led_mask & ~dtb->led_dots[LED_DOT_SEC]); ++ ++ switch (dtb->display.type) { ++ case DISPLAY_TYPE_5D_7S_NORMAL: ++ case DISPLAY_TYPE_5D_7S_T95: ++ case DISPLAY_TYPE_5D_7S_X92: ++ case DISPLAY_TYPE_5D_7S_ABOX: ++ case DISPLAY_TYPE_4D_7S_COL: ++ case DISPLAY_TYPE_5D_7S_M9_PRO: ++ case DISPLAY_TYPE_5D_7S_G9SX: ++ default: ++ for (i = 0; i < length; i++) ++ dev->wbuf[dtb->dat_index[i]] = data[i]; ++ break; ++ case DISPLAY_TYPE_FD620_REF: ++ case DISPLAY_TYPE_4D_7S_FREESATGTC: ++ for (i = 1; i < length; i++) { ++ dev->wbuf[dtb->dat_index[i]] = data[i]; ++ if (data[0] & dtb->led_dots[LED_DOT_SEC]) ++ dev->wbuf[dtb->dat_index[i]] |= ledDot; // DP is the colon. ++ } ++ break; ++ } ++ ++ if (dtb->display.flags & DISPLAY_FLAG_TRANSPOSED) { ++ unsigned char trans[8]; ++ length = ram_grid_count; ++ memset(trans, 0, sizeof(trans)); ++ for (i = 0; i < length; i++) ++ trans[i] = (unsigned char)dev->wbuf[i] << 1; ++ trans[ram_grid_count] = trans[0]; ++ transpose8rS64(trans, trans); ++ memset(dev->wbuf, 0x00, sizeof(dev->wbuf)); ++ for (i = 0; i < ram_grid_count; i++) ++ dev->wbuf[i] = trans[i+1]; ++ } ++ ++ switch (dtb->display.controller) { ++ case CONTROLLER_FD628: ++ // Memory map: ++ // S1 S2 S3 S4 S5 S6 S7 S8 S9 S10 xx S12 S13 S14 xx xx ++ // b0 b1 b2 b3 b4 b5 b6 b7 b0 b1 b2 b3 b4 b5 b6 b7 ++ for (i = 0; i < length; i++) ++ dev->wbuf[i] |= (dev->wbuf[i] & 0xFC00) << 1; ++ break; ++ case CONTROLLER_FD620: ++ // Memory map: ++ // S1 S2 S3 S4 S5 S6 S7 xx xx xx xx xx xx S8 xx xx ++ // b0 b1 b2 b3 b4 b5 b6 b7 b0 b1 b2 b3 b4 b5 b6 b7 ++ for (i = 0; i < length; i++) ++ dev->wbuf[i] |= (dev->wbuf[i] & 0x80) ? 0x2000 : 0; ++ break; ++ case CONTROLLER_TM1618: ++ // Memory map: ++ // S1 S2 S3 S4 S5 xx xx xx xx xx xx S12 S13 S14 xx xx ++ // b0 b1 b2 b3 b4 b5 b6 b7 b0 b1 b2 b3 b4 b5 b6 b7 ++ for (i = 0; i < length; i++) ++ dev->wbuf[i] |= (dev->wbuf[i] & 0x00E0) << 6; ++ break; ++ case CONTROLLER_HBS658: { ++ // Memory map: ++ // S1 S2 S3 S4 S5 S6 S7 xx ++ // b0 b1 b2 b3 b4 b5 b6 b7 ++ unsigned char *tempBuf = (unsigned char *)dev->wbuf; ++ for (i = 1; i < length; i++) ++ tempBuf[i] = (unsigned char)(dev->wbuf[i] & 0xFF); ++ } ++ break; ++ } ++ ++ length *= ram_grid_size; ++ return fd628_write_data_real(0, (unsigned char *)dev->wbuf, length) == 0 ? length : 0; ++} ++ ++static size_t fd628_write_display_data(const struct vfd_display_data *data) ++{ ++ unsigned short wdata[7]; ++ size_t status = seg7_write_display_data(data, wdata, sizeof(wdata)); ++ vfd_display_data = *data; ++ if (status && !fd628_write_data((unsigned char*)wdata, 5*sizeof(wdata[0]))) ++ status = 0; ++ return status; ++} +diff -ruN main/drivers/auxdisplay/openvfd/controllers/fd628.h mod/drivers/auxdisplay/openvfd/controllers/fd628.h +--- main/drivers/auxdisplay/openvfd/controllers/fd628.h 1970-01-01 01:00:00.000000000 +0100 ++++ mod/drivers/auxdisplay/openvfd/controllers/fd628.h 2023-03-07 09:42:01.529533351 +0100 +@@ -0,0 +1,8 @@ ++#ifndef __FD628H__ ++#define __FD628H__ ++ ++#include "controller.h" ++ ++struct controller_interface *init_fd628(struct vfd_dev *dev); ++ ++#endif +diff -ruN main/drivers/auxdisplay/openvfd/controllers/fd650.c mod/drivers/auxdisplay/openvfd/controllers/fd650.c +--- main/drivers/auxdisplay/openvfd/controllers/fd650.c 1970-01-01 01:00:00.000000000 +0100 ++++ mod/drivers/auxdisplay/openvfd/controllers/fd650.c 2023-03-07 09:42:01.537533413 +0100 +@@ -0,0 +1,297 @@ ++#include "../protocols/i2c_sw.h" ++#include "fd650.h" ++ ++/* ****************************** Define FD650 Commands ****************************** */ ++#define FD650_KEY_RDCMD 0x4F /* Read keys command */ ++#define FD650_MODE_WRCMD 0x48 /* Write mode command */ ++#define FD650_DISP_ON 0x01 /* FD650 Display On */ ++#define FD650_DISP_OFF 0x00 /* FD650 Display Off */ ++#define FD650_7SEG_CMD 0x40 /* Set FD650 to work in 7-segment mode */ ++#define FD650_8SEG_CMD 0x00 /* Set FD650 to work in 8-segment mode */ ++#define FD650_BASE_ADDR 0x68 /* Base data address */ ++#define FD655_BASE_ADDR 0x66 /* Base data address */ ++#define FD650_DISP_STATE_WRCMD 0x00 /* Set display modw command */ ++/* *********************************************************************************** */ ++ ++static unsigned char fd650_init(void); ++static unsigned short fd650_get_brightness_levels_count(void); ++static unsigned short fd650_get_brightness_level(void); ++static unsigned char fd650_set_brightness_level(unsigned short level); ++static unsigned char fd650_get_power(void); ++static void fd650_set_power(unsigned char state); ++static void fd650_power_suspend(void) { fd650_set_power(0); } ++static void fd650_power_resume(void) { fd650_set_power(1); } ++static struct vfd_display *fd650_get_display_type(void); ++static unsigned char fd650_set_display_type(struct vfd_display *display); ++static void fd650_set_icon(const char *name, unsigned char state); ++static size_t fd650_read_data(unsigned char *data, size_t length); ++static size_t fd650_write_data(const unsigned char *data, size_t length); ++static size_t fd650_write_display_data(const struct vfd_display_data *data); ++ ++static struct controller_interface fd650_interface = { ++ .init = fd650_init, ++ .get_brightness_levels_count = fd650_get_brightness_levels_count, ++ .get_brightness_level = fd650_get_brightness_level, ++ .set_brightness_level = fd650_set_brightness_level, ++ .get_power = fd650_get_power, ++ .set_power = fd650_set_power, ++ .power_suspend = fd650_power_suspend, ++ .power_resume = fd650_power_resume, ++ .get_display_type = fd650_get_display_type, ++ .set_display_type = fd650_set_display_type, ++ .set_icon = fd650_set_icon, ++ .read_data = fd650_read_data, ++ .write_data = fd650_write_data, ++ .write_display_data = fd650_write_display_data, ++}; ++ ++size_t seg7_write_display_data(const struct vfd_display_data *data, unsigned short *raw_wdata, size_t sz); ++ ++static struct vfd_dev *dev = NULL; ++static struct protocol_interface *protocol = NULL; ++static unsigned char ram_grid_count = 5; ++static unsigned char ram_size = 10; ++static struct vfd_display_data vfd_display_data; ++extern const led_bitmap *ledCodes; ++extern unsigned char ledDot; ++ ++struct controller_interface *init_fd650(struct vfd_dev *_dev) ++{ ++ dev = _dev; ++ return &fd650_interface; ++} ++ ++inline static void fd650_write_cmd_data(unsigned char cmd, unsigned char data) ++{ ++ protocol->write_cmd_data(&cmd, 1, &data, 1); ++} ++ ++static size_t fd650_write_data_real(unsigned char address, const unsigned char *data, size_t length) ++{ ++ unsigned char cmd = FD655_BASE_ADDR | (address & 0x07), i; ++ if (length + address > ram_grid_count) ++ return (-1); ++ ++ for (i = 0; i < length; i++, cmd += 2) ++ fd650_write_cmd_data(cmd, *data++); ++ return (0); ++} ++ ++static unsigned char fd650_init(void) ++{ ++ unsigned char slow_freq = dev->dtb_active.display.flags & DISPLAY_FLAG_LOW_FREQ; ++ protocol = init_sw_i2c(0, MSB_FIRST, 0, dev->clk_pin, dev->dat_pin, slow_freq ? I2C_DELAY_20KHz : I2C_DELAY_100KHz, NULL); ++ if (!protocol) ++ return 0; ++ ++ memset(dev->wbuf, 0x00, sizeof(dev->wbuf)); ++ fd650_write_data((unsigned char *)dev->wbuf, sizeof(dev->wbuf)); ++ fd650_set_brightness_level(dev->brightness); ++ switch(dev->dtb_active.display.type) { ++ case DISPLAY_TYPE_5D_7S_T95: ++ ledCodes = LED_decode_tab1; ++ break; ++ case DISPLAY_TYPE_4D_7S_FREESATGTC: ++ ledCodes = LED_decode_tab4; ++ ledDot = p4; ++ break; ++ default: ++ ledCodes = LED_decode_tab2; ++ break; ++ } ++ return 1; ++} ++ ++inline static unsigned char is_fd650(void) ++{ ++ return dev->dtb_active.display.controller == CONTROLLER_FD650; ++} ++ ++inline static unsigned char is_fd655(void) ++{ ++ return dev->dtb_active.display.controller == CONTROLLER_FD655; ++} ++ ++inline static unsigned char is_fd6551(void) ++{ ++ return dev->dtb_active.display.controller == CONTROLLER_FD6551; ++} ++ ++static unsigned short fd650_get_brightness_levels_count(void) ++{ ++ return is_fd655() ? 3 : 8; ++} ++ ++static unsigned short fd650_get_brightness_level(void) ++{ ++ return dev->brightness; ++} ++ ++static unsigned char get_actual_brightness(void) ++{ ++ unsigned char brightness = 0; ++ if (is_fd655()) ++ brightness = min(2, (dev->brightness + 1) & 0x3) << 5; // 11B disables current limit. ++ else if (is_fd6551()) ++ brightness = min(7, 7 - dev->brightness) << 1; ++ else ++ brightness = ((dev->brightness + 1) & 0x7) << 4; // 000B => 8/8 Duty cycle, 001B - 111B => 1/8 - 7/8 Duty cycle ++ return brightness; ++} ++ ++static unsigned char fd650_set_brightness_level(unsigned short level) ++{ ++ dev->brightness = level & 0x7; ++ fd650_write_cmd_data(FD650_MODE_WRCMD, FD650_DISP_STATE_WRCMD | get_actual_brightness() | FD650_DISP_ON); ++ dev->power = 1; ++ return 1; ++} ++ ++static unsigned char fd650_get_power(void) ++{ ++ return dev->power; ++} ++ ++static void fd650_set_power(unsigned char state) ++{ ++ dev->power = state; ++ if (state) ++ fd650_set_brightness_level(dev->brightness); ++ else ++ fd650_write_cmd_data(FD650_MODE_WRCMD, FD650_DISP_STATE_WRCMD | FD650_DISP_OFF); ++} ++ ++static struct vfd_display *fd650_get_display_type(void) ++{ ++ return &dev->dtb_active.display; ++} ++ ++static unsigned char fd650_set_display_type(struct vfd_display *display) ++{ ++ unsigned char ret = 0; ++ if (display->type < DISPLAY_TYPE_MAX && (is_fd650() || is_fd655() || is_fd6551())) ++ { ++ dev->dtb_active.display = *display; ++ fd650_init(); ++ ret = 1; ++ } ++ ++ return ret; ++} ++ ++static void fd650_set_icon(const char *name, unsigned char state) ++{ ++ struct vfd_dtb_config *dtb = &dev->dtb_active; ++ switch (dtb->display.type) { ++ case DISPLAY_TYPE_5D_7S_NORMAL: ++ case DISPLAY_TYPE_5D_7S_T95: ++ case DISPLAY_TYPE_5D_7S_G9SX: ++ if (strncmp(name,"alarm",5) == 0) { ++ dev->status_led_mask = state ? (dev->status_led_mask | dtb->led_dots[LED_DOT1_ALARM]) : (dev->status_led_mask & ~dtb->led_dots[LED_DOT1_ALARM]); ++ } else if (strncmp(name,"usb",3) == 0) { ++ dev->status_led_mask = state ? (dev->status_led_mask | dtb->led_dots[LED_DOT1_USB]) : (dev->status_led_mask & ~dtb->led_dots[LED_DOT1_USB]); ++ } else if (strncmp(name,"play",4) == 0) { ++ dev->status_led_mask = state ? (dev->status_led_mask | dtb->led_dots[LED_DOT1_PLAY]) : (dev->status_led_mask & ~dtb->led_dots[LED_DOT1_PLAY]); ++ } else if (strncmp(name,"pause",5) == 0) { ++ dev->status_led_mask = state ? (dev->status_led_mask | dtb->led_dots[LED_DOT1_PAUSE]) : (dev->status_led_mask & ~dtb->led_dots[LED_DOT1_PAUSE]); ++ } else if (strncmp(name,"colon",5) == 0) { ++ dev->status_led_mask = state ? (dev->status_led_mask | dtb->led_dots[LED_DOT1_SEC]) : (dev->status_led_mask & ~dtb->led_dots[LED_DOT1_SEC]); ++ } else if (strncmp(name,"eth",3) == 0) { ++ dev->status_led_mask = state ? (dev->status_led_mask | dtb->led_dots[LED_DOT1_ETH]) : (dev->status_led_mask & ~dtb->led_dots[LED_DOT1_ETH]); ++ } else if (strncmp(name,"wifi",4) == 0) { ++ dev->status_led_mask = state ? (dev->status_led_mask | dtb->led_dots[LED_DOT1_WIFI]) : (dev->status_led_mask & ~dtb->led_dots[LED_DOT1_WIFI]); ++ } ++ break; ++ case DISPLAY_TYPE_5D_7S_X92: ++ if (strncmp(name,"apps",4) == 0) { ++ dev->status_led_mask = state ? (dev->status_led_mask | dtb->led_dots[LED_DOT2_APPS]) : (dev->status_led_mask & ~dtb->led_dots[LED_DOT2_APPS]); ++ } else if (strncmp(name,"setup",5) == 0) { ++ dev->status_led_mask = state ? (dev->status_led_mask | dtb->led_dots[LED_DOT2_SETUP]) : (dev->status_led_mask & ~dtb->led_dots[LED_DOT2_SETUP]); ++ } else if (strncmp(name,"usb",3) == 0) { ++ dev->status_led_mask = state ? (dev->status_led_mask | dtb->led_dots[LED_DOT2_USB]) : (dev->status_led_mask & ~dtb->led_dots[LED_DOT2_USB]); ++ } else if (strncmp(name,"sd",2) == 0) { ++ dev->status_led_mask = state ? (dev->status_led_mask | dtb->led_dots[LED_DOT2_CARD]) : (dev->status_led_mask & ~dtb->led_dots[LED_DOT2_CARD]); ++ } else if (strncmp(name,"colon",5) == 0) { ++ dev->status_led_mask = state ? (dev->status_led_mask | dtb->led_dots[LED_DOT2_SEC]) : (dev->status_led_mask & ~dtb->led_dots[LED_DOT2_SEC]); ++ } else if (strncmp(name,"hdmi",4) == 0) { ++ dev->status_led_mask = state ? (dev->status_led_mask | dtb->led_dots[LED_DOT2_HDMI]) : (dev->status_led_mask & ~dtb->led_dots[LED_DOT2_HDMI]); ++ } else if (strncmp(name,"cvbs",4) == 0) { ++ dev->status_led_mask = state ? (dev->status_led_mask | dtb->led_dots[LED_DOT2_CVBS]) : (dev->status_led_mask & ~dtb->led_dots[LED_DOT2_CVBS]); ++ } ++ break; ++ case DISPLAY_TYPE_5D_7S_ABOX: ++ if (strncmp(name,"power",5) == 0) { ++ dev->status_led_mask = state ? (dev->status_led_mask | dtb->led_dots[LED_DOT3_POWER]) : (dev->status_led_mask & ~dtb->led_dots[LED_DOT3_POWER]); ++ } else if (strncmp(name,"eth",3) == 0) { ++ dev->status_led_mask = state ? (dev->status_led_mask | dtb->led_dots[LED_DOT3_LAN]) : (dev->status_led_mask & ~dtb->led_dots[LED_DOT3_LAN]); ++ } else if (strncmp(name,"colon",5) == 0) { ++ dev->status_led_mask = state ? (dev->status_led_mask | dtb->led_dots[LED_DOT3_SEC]) : (dev->status_led_mask & ~dtb->led_dots[LED_DOT3_SEC]); ++ } else if (strncmp(name,"wifi",4) == 0) { ++ dev->status_led_mask = state ? (dev->status_led_mask | dtb->led_dots[LED_DOT3_WIFIHI] | dtb->led_dots[LED_DOT3_WIFILO]) : (dev->status_led_mask & ~(dtb->led_dots[LED_DOT3_WIFIHI] | dtb->led_dots[LED_DOT3_WIFILO])); ++ } ++ break; ++ case DISPLAY_TYPE_5D_7S_M9_PRO: ++ if (strncmp(name,"b-t",3) == 0) { ++ dev->status_led_mask = state ? (dev->status_led_mask | dtb->led_dots[LED_DOT4_BT]) : (dev->status_led_mask & ~dtb->led_dots[LED_DOT4_BT]); ++ } else if (strncmp(name,"eth",3) == 0) { ++ dev->status_led_mask = state ? (dev->status_led_mask | dtb->led_dots[LED_DOT4_ETH]) : (dev->status_led_mask & ~dtb->led_dots[LED_DOT4_ETH]); ++ } else if (strncmp(name,"wifi",4) == 0) { ++ dev->status_led_mask = state ? (dev->status_led_mask | dtb->led_dots[LED_DOT4_WIFI]) : (dev->status_led_mask & ~dtb->led_dots[LED_DOT4_WIFI]); ++ } else if (strncmp(name,"spdif",5) == 0) { ++ dev->status_led_mask = state ? (dev->status_led_mask | dtb->led_dots[LED_DOT4_SPDIF]) : (dev->status_led_mask & ~dtb->led_dots[LED_DOT4_SPDIF]); ++ } else if (strncmp(name,"colon",5) == 0) { ++ dev->status_led_mask = state ? (dev->status_led_mask | dtb->led_dots[LED_DOT4_SEC]) : (dev->status_led_mask & ~dtb->led_dots[LED_DOT4_SEC]); ++ } else if (strncmp(name,"hdmi",4) == 0) { ++ dev->status_led_mask = state ? (dev->status_led_mask | dtb->led_dots[LED_DOT4_HDMI]) : (dev->status_led_mask & ~dtb->led_dots[LED_DOT4_HDMI]); ++ } else if (strncmp(name,"cvbs",4) == 0) { ++ dev->status_led_mask = state ? (dev->status_led_mask | dtb->led_dots[LED_DOT4_AV]) : (dev->status_led_mask & ~dtb->led_dots[LED_DOT4_AV]); ++ } ++ break; ++ default: ++ if (strncmp(name,"colon",5) == 0) ++ dev->status_led_mask = state ? (dev->status_led_mask | ledDots[LED_DOT_SEC]) : (dev->status_led_mask & ~ledDots[LED_DOT_SEC]); ++ break; ++ } ++} ++ ++static size_t fd650_read_data(unsigned char *data, size_t length) ++{ ++ unsigned char cmd = FD650_KEY_RDCMD; ++ return protocol->read_cmd_data(&cmd, 1, data, length > 1 ? 1 : length) == 0 ? 1 : -1; ++} ++ ++static size_t fd650_write_data(const unsigned char *_data, size_t length) ++{ ++ size_t i; ++ struct vfd_dtb_config *dtb = &dev->dtb_active; ++ unsigned short *data = (unsigned short *)_data; ++ unsigned char *tempBuf = (unsigned char *)dev->wbuf; ++ ++ memset(dev->wbuf, 0x00, sizeof(dev->wbuf)); ++ length = min(length, (size_t)ram_size) / sizeof(unsigned short); ++ if (data[0] & ledDots[LED_DOT_SEC]) { ++ data[0] &= ~ledDots[LED_DOT_SEC]; ++ data[0] |= dtb->led_dots[LED_DOT_SEC]; ++ } ++ // Apply LED indicators mask (usb, eth, wifi etc.) ++ if (vfd_display_data.mode == DISPLAY_MODE_CLOCK) ++ data[0] |= dev->status_led_mask; ++ else ++ data[0] |= (dev->status_led_mask & ~dtb->led_dots[LED_DOT_SEC]); ++ for (i = 0; i <= length; i++) ++ tempBuf[dtb->dat_index[i]] = (unsigned char)(data[i] & 0xFF); ++ if (is_fd650()) ++ tempBuf[dtb->dat_index[0]] |= ((data[0] | dev->status_led_mask) & ledDots[LED_DOT_SEC]) ? ledDot : 0x00; ++ ++ return fd650_write_data_real(0, tempBuf, length) == 0 ? length : 0; ++} ++ ++static size_t fd650_write_display_data(const struct vfd_display_data *data) ++{ ++ unsigned short wdata[7]; ++ size_t status = seg7_write_display_data(data, wdata, sizeof(wdata)); ++ vfd_display_data = *data; ++ if (status && !fd650_write_data((unsigned char*)wdata, 5*sizeof(wdata[0]))) ++ status = 0; ++ return status; ++} +diff -ruN main/drivers/auxdisplay/openvfd/controllers/fd650.h mod/drivers/auxdisplay/openvfd/controllers/fd650.h +--- main/drivers/auxdisplay/openvfd/controllers/fd650.h 1970-01-01 01:00:00.000000000 +0100 ++++ mod/drivers/auxdisplay/openvfd/controllers/fd650.h 2023-03-07 09:42:01.549533505 +0100 +@@ -0,0 +1,8 @@ ++#ifndef __FD650H__ ++#define __FD650H__ ++ ++#include "controller.h" ++ ++struct controller_interface *init_fd650(struct vfd_dev *dev); ++ ++#endif +diff -ruN main/drivers/auxdisplay/openvfd/controllers/fonts/Grotesk16x32_h.h mod/drivers/auxdisplay/openvfd/controllers/fonts/Grotesk16x32_h.h +--- main/drivers/auxdisplay/openvfd/controllers/fonts/Grotesk16x32_h.h 1970-01-01 01:00:00.000000000 +0100 ++++ mod/drivers/auxdisplay/openvfd/controllers/fonts/Grotesk16x32_h.h 2023-03-07 09:42:05.761566151 +0100 +@@ -0,0 +1,112 @@ ++// Grotesk16x32_h.h ++// Font type : Full (96 characters) ++// Font size : 16x32 pixels ++// Memory usage : 6148 bytes ++ ++// Origin: http://www.rinkydinkelectronics.com/r_fonts.php ++// Modified by Arthur Liberman for compatibility with the OpenVFD driver. ++ ++const unsigned char Grotesk16x32_H[6148] = { ++0x10,0x20,0x20,0x60, ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ++0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ! ++0x00,0x00,0x00,0x00,0x06,0x18,0x06,0x18,0x0E,0x38,0x0E,0x38,0x1E,0x78,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // " ++0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x8C,0x03,0x8C,0x03,0x8C,0x03,0x1C,0x03,0x18,0x03,0x18,0x3F,0xFF,0x3F,0xFF,0x3F,0xFF,0x06,0x38,0x06,0x30,0x06,0x30,0x0E,0x30,0x0C,0x70,0x0C,0x60,0xFF,0xFC,0xFF,0xFE,0xFF,0xFE,0x1C,0xE0,0x18,0xE0,0x18,0xC0,0x18,0xC0,0x38,0xC0,0x39,0xC0,0x31,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // # ++0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x03,0xF0,0x0F,0xF8,0x1F,0xFC,0x1C,0x8C,0x18,0x80,0x38,0x80,0x38,0x80,0x38,0x80,0x1C,0x80,0x1F,0x80,0x0F,0xF0,0x07,0xF8,0x01,0xFC,0x00,0x9C,0x00,0x8E,0x00,0x8E,0x00,0x8E,0x00,0x8E,0x30,0x8C,0x38,0x9C,0x3F,0xF8,0x1F,0xF0,0x01,0xC0,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80, // $ ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x7F,0x00,0x77,0x00,0xE3,0x80,0xC1,0x80,0xC1,0x80,0xC1,0x80,0x63,0x82,0x7F,0x0F,0x3E,0x3E,0x1C,0xF8,0x03,0xE0,0x0F,0x80,0x3E,0x38,0x78,0x7C,0xE0,0xFE,0x01,0xC6,0x01,0x83,0x01,0x83,0x01,0x83,0x01,0xC7,0x00,0xEE,0x00,0xFC,0x00,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // % ++0x00,0x00,0x00,0x00,0x03,0xC0,0x07,0xF0,0x0F,0xF0,0x1E,0x30,0x1C,0x00,0x1C,0x00,0x1C,0x00,0x1C,0x00,0x1C,0x00,0x0E,0x00,0x0E,0x00,0x1F,0x00,0x1F,0x00,0x3B,0x87,0x71,0xC7,0x71,0xC7,0x60,0xE7,0x60,0xE7,0x60,0x76,0x60,0x7E,0x70,0x3E,0x70,0x1C,0x78,0x1C,0x3C,0x7E,0x1F,0xFE,0x0F,0xE7,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // & ++0x00,0x00,0x00,0x00,0x00,0xE0,0x00,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x03,0x80,0x03,0x80,0x03,0x80,0x03,0x80,0x03,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ' ++0x00,0x60,0x00,0xE0,0x00,0xC0,0x00,0xC0,0x01,0xC0,0x01,0x80,0x03,0x80,0x03,0x80,0x03,0x80,0x03,0x00,0x03,0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x03,0x00,0x03,0x00,0x03,0x80,0x03,0x80,0x03,0x80,0x01,0x80,0x01,0xC0,0x01,0xC0,0x00,0xC0,0x00,0xE0,0x00,0x60,0x00,0x00, // ( ++0x06,0x00,0x07,0x00,0x03,0x00,0x03,0x00,0x03,0x80,0x01,0x80,0x01,0x80,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xE0,0x00,0xE0,0x00,0xE0,0x00,0xE0,0x00,0xE0,0x00,0xE0,0x00,0xE0,0x00,0xE0,0x00,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0x80,0x01,0x80,0x03,0x80,0x03,0x00,0x03,0x00,0x07,0x00,0x06,0x00,0x00,0x00, // ) ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x61,0x86,0x79,0x8E,0x3D,0x9C,0x0F,0xF8,0x07,0xE0,0x03,0xC0,0x07,0xE0,0x0F,0xF8,0x3D,0xBC,0x79,0x8E,0x71,0x86,0x01,0x82,0x01,0x80,0x01,0x80,0x01,0x80,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // * ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x7F,0xFE,0x7F,0xFE,0x3F,0xFE,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // + ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xC0,0x03,0xC0,0x03,0xC0,0x03,0xC0,0x03,0xC0,0x03,0xC0,0x07,0x80,0x07,0x80,0x07,0x00,0x07,0x00,0x07,0x00,0x0E,0x00, // , ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0xFE,0x7F,0xFE,0x7F,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // - ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xC0,0x07,0xC0,0x07,0xC0,0x07,0xC0,0x07,0xC0,0x07,0xC0,0x07,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // . ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x1C,0x00,0x18,0x00,0x38,0x00,0x38,0x00,0x70,0x00,0x70,0x00,0xE0,0x00,0xE0,0x00,0xC0,0x01,0xC0,0x01,0xC0,0x03,0x80,0x03,0x80,0x03,0x00,0x07,0x00,0x06,0x00,0x0E,0x00,0x0E,0x00,0x1C,0x00,0x1C,0x00,0x18,0x00,0x38,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // / ++ ++0x00,0x00,0x00,0x00,0x01,0xC0,0x07,0xE0,0x0F,0xF0,0x1E,0x78,0x1C,0x38,0x1C,0x1C,0x38,0x3C,0x38,0x3C,0x38,0x7C,0x38,0x7C,0x38,0xCC,0x38,0xCE,0x39,0xCE,0x39,0x8E,0x3B,0x8E,0x3B,0x0C,0x3F,0x0C,0x3E,0x1C,0x3E,0x1C,0x3C,0x1C,0x3C,0x1C,0x1C,0x1C,0x1C,0x38,0x0E,0x78,0x0F,0xF0,0x07,0xE0,0x01,0x80,0x00,0x00,0x00,0x00,0x00,0x00, // 0 ++0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xE0,0x07,0xE0,0x1F,0xE0,0x1F,0xE0,0x1C,0xE0,0x10,0xE0,0x00,0xE0,0x00,0xE0,0x00,0xE0,0x00,0xE0,0x00,0xE0,0x00,0xE0,0x00,0xE0,0x00,0xE0,0x00,0xE0,0x00,0xE0,0x00,0xE0,0x00,0xE0,0x00,0xE0,0x00,0xE0,0x00,0xC0,0x00,0xC0,0x0F,0xFC,0x1F,0xFE,0x0F,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 1 ++0x00,0x00,0x00,0x00,0x07,0xC0,0x1F,0xF0,0x3F,0xF8,0x3C,0x3C,0x30,0x1C,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x1C,0x00,0x1C,0x00,0x38,0x00,0x38,0x00,0x70,0x00,0xE0,0x01,0xE0,0x01,0xC0,0x03,0x80,0x07,0x00,0x0E,0x00,0x1E,0x00,0x3C,0x00,0x3F,0xFE,0x3F,0xFE,0x3F,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 2 ++0x00,0x00,0x00,0x00,0x07,0xC0,0x1F,0xF0,0x3F,0xF8,0x3C,0x78,0x00,0x3C,0x00,0x1C,0x00,0x1C,0x00,0x1C,0x00,0x1C,0x00,0x1C,0x00,0x38,0x07,0xF0,0x07,0xE0,0x07,0xF0,0x00,0x38,0x00,0x1C,0x00,0x1C,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x1C,0x20,0x3C,0x3F,0xFC,0x3F,0xF8,0x3F,0xF0,0x03,0x80,0x00,0x00,0x00,0x00,0x00,0x00, // 3 ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x00,0xF0,0x00,0xF0,0x01,0xF0,0x01,0xB0,0x03,0x30,0x03,0x30,0x07,0x70,0x06,0x70,0x0E,0x70,0x0C,0x70,0x1C,0x70,0x18,0x70,0x38,0x70,0x30,0x30,0x70,0x30,0x7F,0xFE,0x7F,0xFE,0x7F,0xFE,0x00,0x70,0x00,0x30,0x00,0x70,0x00,0x70,0x00,0x70,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 4 ++0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0xF8,0x1F,0xF8,0x1F,0xF8,0x1C,0x00,0x1C,0x00,0x1C,0x00,0x1C,0x00,0x1C,0x00,0x1F,0xC0,0x1F,0xF0,0x1F,0xF8,0x18,0x7C,0x00,0x3C,0x00,0x1C,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x1C,0x20,0x3C,0x3F,0xF8,0x3F,0xF8,0x3F,0xE0,0x07,0x80,0x00,0x00,0x00,0x00,0x00,0x00, // 5 ++0x00,0x00,0x00,0x00,0x01,0xF0,0x07,0xF8,0x0F,0xF8,0x0F,0x18,0x1C,0x00,0x1C,0x00,0x18,0x00,0x38,0x00,0x38,0x00,0x39,0xE0,0x33,0xF0,0x3F,0xF8,0x3E,0x3C,0x3C,0x1C,0x38,0x1C,0x38,0x0C,0x38,0x0E,0x38,0x0E,0x38,0x0E,0x38,0x0E,0x38,0x0C,0x18,0x1C,0x1C,0x1C,0x1E,0x38,0x0F,0xF8,0x07,0xF0,0x01,0xC0,0x00,0x00,0x00,0x00,0x00,0x00, // 6 ++0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0xFE,0x3F,0xFE,0x3F,0xFC,0x00,0x1C,0x00,0x1C,0x00,0x38,0x00,0x38,0x00,0x38,0x00,0x70,0x00,0x70,0x00,0x70,0x00,0x60,0x00,0xE0,0x00,0xE0,0x00,0xE0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x03,0x80,0x03,0x80,0x03,0x80,0x07,0x00,0x07,0x00,0x07,0x00,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 7 ++0x00,0x00,0x00,0x00,0x03,0xC0,0x0F,0xF0,0x1F,0xF8,0x1E,0x38,0x1C,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x1C,0x1C,0x1C,0x1C,0x38,0x0F,0xF0,0x07,0xE0,0x0F,0xF0,0x1E,0x78,0x1C,0x1C,0x38,0x1C,0x38,0x0E,0x38,0x0E,0x38,0x0E,0x38,0x0E,0x38,0x1C,0x3C,0x1C,0x1E,0x7C,0x1F,0xF8,0x0F,0xF0,0x01,0xC0,0x00,0x00,0x00,0x00,0x00,0x00, // 8 ++0x00,0x00,0x00,0x00,0x03,0xC0,0x0F,0xF0,0x1F,0xF0,0x1C,0x78,0x38,0x38,0x38,0x1C,0x38,0x1C,0x38,0x1C,0x30,0x1C,0x30,0x1C,0x38,0x1C,0x38,0x1E,0x38,0x1E,0x38,0x3E,0x1E,0x7E,0x1F,0xEC,0x0F,0xCC,0x03,0x8C,0x00,0x1C,0x00,0x1C,0x00,0x1C,0x00,0x38,0x00,0x38,0x1F,0xF0,0x1F,0xF0,0x1F,0xE0,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 9 ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xC0,0x03,0xC0,0x03,0xC0,0x03,0xC0,0x03,0xC0,0x03,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xC0,0x03,0xC0,0x03,0xC0,0x03,0xC0,0x03,0xC0,0x03,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // : ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xC0,0x03,0xC0,0x03,0xC0,0x03,0xC0,0x03,0xC0,0x03,0xC0,0x03,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xC0,0x03,0xC0,0x03,0xC0,0x03,0xC0,0x03,0xC0,0x03,0xC0,0x03,0x80,0x07,0x80,0x07,0x80,0x07,0x00,0x07,0x00,0x00,0x00, // ; ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x0E,0x00,0x3E,0x00,0xFC,0x03,0xF0,0x0F,0xC0,0x3F,0x00,0x7C,0x00,0x78,0x00,0x7E,0x00,0x3F,0x80,0x0F,0xE0,0x03,0xF8,0x00,0xFE,0x00,0x3E,0x00,0x0E,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // < ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0xFE,0x7F,0xFE,0x7F,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0xFE,0x7F,0xFE,0x7F,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // = ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x78,0x00,0x7E,0x00,0x3F,0x80,0x0F,0xE0,0x03,0xF8,0x00,0xFE,0x00,0x3E,0x00,0x0E,0x00,0x3E,0x00,0xFC,0x03,0xF0,0x0F,0xC0,0x3F,0x00,0x7C,0x00,0x70,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // > ++0x00,0x00,0x00,0x00,0x03,0xE0,0x0F,0xF0,0x1F,0xF8,0x1C,0x3C,0x18,0x1C,0x00,0x1C,0x00,0x1C,0x00,0x1C,0x00,0x1C,0x00,0x38,0x00,0x78,0x00,0xF0,0x00,0xE0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0x80,0x01,0xC0,0x01,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x80,0x03,0x80,0x03,0x80,0x01,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ? ++ ++0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xF0,0x0F,0xF8,0x1E,0x3C,0x1C,0x0C,0x38,0x0E,0x30,0x06,0x70,0x06,0x60,0xF6,0x61,0xFE,0xE3,0xFE,0xC3,0x0E,0xC7,0x06,0xC6,0x06,0xC6,0x06,0xC6,0x06,0xC6,0x06,0xC7,0x06,0xC7,0x0E,0xE3,0x9E,0x63,0xFE,0x61,0xF6,0x70,0x60,0x30,0x00,0x38,0x00,0x1C,0x00,0x1E,0x00,0x0F,0xFC,0x07,0xFE,0x00,0xFC, // @ ++0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xC0,0x03,0xC0,0x07,0xC0,0x07,0xC0,0x06,0xE0,0x06,0xE0,0x0E,0x60,0x0E,0x60,0x0E,0x70,0x0C,0x70,0x0C,0x70,0x1C,0x30,0x1C,0x38,0x1C,0x38,0x18,0x38,0x3F,0xF8,0x3F,0xFC,0x3F,0xFC,0x3F,0xFC,0x70,0x1C,0x70,0x0C,0x70,0x0E,0x70,0x0E,0xE0,0x0E,0xE0,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // A ++0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0xE0,0x3F,0xF0,0x3F,0xF8,0x38,0x3C,0x38,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x38,0x3F,0xF8,0x3F,0xF0,0x3F,0xF0,0x38,0x78,0x38,0x1C,0x38,0x1C,0x38,0x0C,0x38,0x0E,0x38,0x0E,0x38,0x0E,0x38,0x0E,0x38,0x1C,0x38,0x3C,0x3F,0xF8,0x3F,0xF8,0x3F,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // B ++0x00,0x00,0x00,0x00,0x01,0xF0,0x07,0xF8,0x0F,0xFC,0x0F,0x1C,0x1C,0x04,0x1C,0x00,0x38,0x00,0x38,0x00,0x38,0x00,0x38,0x00,0x78,0x00,0x70,0x00,0x70,0x00,0x70,0x00,0x70,0x00,0x70,0x00,0x38,0x00,0x38,0x00,0x38,0x00,0x38,0x00,0x38,0x00,0x1C,0x00,0x1E,0x0C,0x0F,0x3C,0x07,0xFC,0x03,0xF8,0x00,0xE0,0x00,0x00,0x00,0x00,0x00,0x00, // C ++0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0xC0,0x7F,0xE0,0x7F,0xF0,0x70,0x78,0x70,0x38,0x70,0x3C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x38,0x70,0x38,0x70,0xF8,0x7F,0xF0,0x7F,0xE0,0x3F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // D ++0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0xFC,0x3F,0xFC,0x3F,0xFC,0x38,0x00,0x38,0x00,0x38,0x00,0x38,0x00,0x38,0x00,0x38,0x00,0x3F,0xF8,0x3F,0xFC,0x3F,0xFC,0x38,0x00,0x38,0x00,0x38,0x00,0x38,0x00,0x38,0x00,0x38,0x00,0x38,0x00,0x38,0x00,0x38,0x00,0x38,0x00,0x3F,0xFC,0x3F,0xFC,0x3F,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // E ++0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0xFC,0x1F,0xFC,0x1F,0xFC,0x1C,0x00,0x1C,0x00,0x1C,0x00,0x1C,0x00,0x1C,0x00,0x1C,0x00,0x1F,0xF8,0x1F,0xFC,0x1F,0xFC,0x1C,0x00,0x1C,0x00,0x1C,0x00,0x1C,0x00,0x1C,0x00,0x1C,0x00,0x1C,0x00,0x1C,0x00,0x1C,0x00,0x1C,0x00,0x1C,0x00,0x1C,0x00,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // F ++0x00,0x00,0x00,0x00,0x01,0xE0,0x07,0xF8,0x0F,0xFC,0x1E,0x1C,0x1C,0x0C,0x38,0x00,0x38,0x00,0x38,0x00,0x38,0x00,0x70,0x00,0x70,0x00,0x70,0x00,0x70,0x00,0x70,0x7C,0x70,0x7C,0x70,0x7C,0x70,0x0C,0x70,0x0C,0x38,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x0C,0x1C,0x1C,0x1F,0x3C,0x0F,0xFC,0x07,0xF8,0x00,0xC0,0x00,0x00,0x00,0x00,0x00,0x00, // G ++0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x7F,0xFC,0x7F,0xFC,0x7F,0xFC,0x78,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x30,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // H ++0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0xF8,0x3F,0xF8,0x3F,0xF8,0x03,0x80,0x03,0x80,0x03,0x80,0x03,0x80,0x03,0x80,0x03,0x80,0x03,0x80,0x03,0x80,0x03,0x80,0x03,0x80,0x03,0x80,0x03,0x80,0x03,0x80,0x03,0x80,0x03,0x80,0x03,0x80,0x03,0x80,0x03,0x80,0x03,0x80,0x3F,0xF8,0x3F,0xF8,0x3F,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // I ++0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xF0,0x0F,0xF0,0x07,0xF0,0x00,0x30,0x00,0x70,0x00,0x70,0x00,0x70,0x00,0x70,0x00,0x70,0x00,0x70,0x00,0x70,0x00,0x70,0x00,0x70,0x00,0x70,0x00,0x70,0x00,0x70,0x00,0x70,0x00,0x30,0x00,0x70,0x00,0x70,0x40,0x70,0x60,0x70,0x79,0xF0,0x7F,0xE0,0x3F,0xC0,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // J ++0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x0E,0x70,0x1C,0x70,0x3C,0x70,0x38,0x70,0x70,0x70,0xE0,0x71,0xE0,0x71,0xC0,0x73,0x80,0x77,0x00,0x7F,0x00,0x7F,0x80,0x7F,0x80,0x79,0xC0,0x79,0xC0,0x70,0xE0,0x70,0xE0,0x70,0x70,0x70,0x70,0x70,0x38,0x70,0x3C,0x70,0x1C,0x70,0x1E,0x70,0x0E,0x30,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // K ++0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x00,0x38,0x00,0x38,0x00,0x38,0x00,0x38,0x00,0x38,0x00,0x38,0x00,0x38,0x00,0x38,0x00,0x38,0x00,0x38,0x00,0x38,0x00,0x38,0x00,0x38,0x00,0x38,0x00,0x38,0x00,0x38,0x00,0x38,0x00,0x38,0x00,0x38,0x00,0x38,0x00,0x38,0x00,0x3F,0xFE,0x3F,0xFE,0x1F,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // L ++0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0x3C,0xF0,0x3C,0xF8,0x3C,0xF8,0x3C,0xF8,0x7C,0xF8,0x6C,0xEC,0x6C,0xEC,0xCC,0xEC,0xCC,0xEC,0xCC,0xE6,0xCC,0xE7,0xCC,0xE7,0x8C,0xE7,0x8C,0xE3,0x8C,0xE3,0x0C,0xE0,0x0C,0xE0,0x0C,0xE0,0x0C,0xE0,0x0C,0xE0,0x0C,0xE0,0x0C,0xE0,0x0C,0xE0,0x0C,0xE0,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // M ++0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0x1C,0xF0,0x1C,0xF8,0x1C,0xF8,0x1C,0xFC,0x1C,0xFC,0x1C,0xEC,0x1C,0xEE,0x1C,0xEE,0x1C,0xE6,0x1C,0xE7,0x1C,0xE7,0x1C,0xE3,0x9C,0xE3,0x9C,0xE1,0x9C,0xE1,0xDC,0xE1,0xDC,0xE0,0xDC,0xE0,0xFC,0xE0,0xFC,0xE0,0x7C,0xE0,0x7C,0xE0,0x7C,0xE0,0x3C,0xE0,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // N ++0x00,0x00,0x00,0x00,0x03,0xC0,0x0F,0xE0,0x1F,0xF0,0x1E,0x78,0x3C,0x38,0x38,0x1C,0x38,0x1C,0x38,0x1C,0x30,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x0E,0x70,0x1E,0x70,0x1E,0x70,0x1E,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x1C,0x1C,0x38,0x1E,0x78,0x0F,0xF0,0x07,0xE0,0x01,0x80,0x00,0x00,0x00,0x00,0x00,0x00, // O ++ ++0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0xF0,0x3F,0xF8,0x3F,0xFC,0x38,0x1C,0x38,0x1E,0x38,0x0E,0x38,0x0E,0x38,0x0E,0x38,0x0E,0x38,0x0E,0x38,0x1C,0x38,0x3C,0x3F,0xFC,0x3F,0xF8,0x3F,0xE0,0x38,0x00,0x38,0x00,0x38,0x00,0x38,0x00,0x38,0x00,0x38,0x00,0x38,0x00,0x38,0x00,0x38,0x00,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // P ++0x00,0x00,0x00,0x00,0x03,0xC0,0x0F,0xF0,0x1F,0xF0,0x1C,0x78,0x38,0x38,0x38,0x1C,0x38,0x1C,0x38,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x0E,0x70,0x1E,0x70,0x1E,0x70,0x0E,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x38,0x1C,0x78,0x1F,0xF0,0x0F,0xE0,0x03,0xE0,0x00,0x70,0x00,0x38,0x00,0x38,0x00,0x10, // Q ++0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0xE0,0x3F,0xF0,0x3F,0xF8,0x30,0x38,0x38,0x3C,0x38,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x1C,0x30,0x38,0x3F,0xF8,0x3F,0xF0,0x3F,0xE0,0x3F,0xF0,0x30,0x70,0x38,0x38,0x38,0x38,0x38,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x0E,0x38,0x0E,0x38,0x0E,0x30,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // R ++0x00,0x00,0x00,0x00,0x03,0xE0,0x0F,0xF8,0x1F,0xF8,0x3C,0x38,0x38,0x08,0x38,0x00,0x30,0x00,0x70,0x00,0x70,0x00,0x38,0x00,0x3C,0x00,0x3F,0x80,0x1F,0xE0,0x0F,0xF0,0x03,0xF8,0x00,0x7C,0x00,0x1C,0x00,0x1C,0x00,0x1C,0x00,0x0C,0x00,0x1C,0x00,0x1C,0x30,0x3C,0x3C,0x78,0x3F,0xF8,0x1F,0xF0,0x03,0x80,0x00,0x00,0x00,0x00,0x00,0x00, // S ++0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x7F,0xFE,0x01,0x80,0x03,0x80,0x03,0x80,0x03,0x80,0x03,0x80,0x03,0x80,0x03,0x80,0x03,0x80,0x03,0x80,0x03,0x80,0x03,0x80,0x03,0x80,0x03,0x80,0x03,0x80,0x03,0x80,0x03,0x80,0x03,0x80,0x03,0x80,0x03,0x80,0x03,0x80,0x03,0x80,0x01,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // T ++0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x1C,0x1E,0x78,0x1F,0xF8,0x0F,0xF0,0x01,0x80,0x00,0x00,0x00,0x00,0x00,0x00, // U ++0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x0E,0x70,0x0E,0x70,0x0E,0x70,0x0E,0x38,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x1C,0x18,0x18,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x0C,0x30,0x0E,0x70,0x0E,0x70,0x0E,0x70,0x06,0x60,0x06,0x60,0x06,0x60,0x07,0xE0,0x07,0xE0,0x03,0xC0,0x03,0xC0,0x03,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // V ++0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0x07,0xE0,0x07,0xE0,0x07,0xE0,0x07,0xE0,0x07,0x60,0x06,0x61,0x86,0x63,0xC6,0x63,0xC6,0x73,0xCE,0x73,0xCE,0x73,0xCE,0x72,0xCE,0x76,0x6E,0x36,0x6C,0x36,0x6C,0x36,0x6C,0x36,0x6C,0x3E,0x7C,0x3C,0x3C,0x3C,0x3C,0x3C,0x3C,0x3C,0x3C,0x1C,0x38,0x1C,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // W ++0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x0E,0x38,0x0E,0x38,0x1C,0x1C,0x1C,0x1C,0x38,0x0E,0x38,0x0E,0x70,0x06,0x70,0x07,0xE0,0x03,0xE0,0x03,0xC0,0x01,0xC0,0x03,0xC0,0x03,0xE0,0x07,0xE0,0x07,0x60,0x0E,0x70,0x0E,0x30,0x1C,0x38,0x1C,0x38,0x38,0x1C,0x38,0x1C,0x70,0x0E,0x70,0x0E,0xE0,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // X ++0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x0E,0x70,0x0E,0x30,0x1C,0x38,0x1C,0x38,0x18,0x1C,0x38,0x1C,0x38,0x0E,0x70,0x0E,0x70,0x06,0x60,0x07,0xE0,0x03,0xC0,0x03,0xC0,0x03,0x80,0x01,0x80,0x03,0x80,0x03,0x80,0x03,0x80,0x03,0x80,0x03,0x80,0x03,0x80,0x03,0x80,0x03,0x80,0x03,0x80,0x01,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // Y ++0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0xFE,0x3F,0xFE,0x3F,0xFE,0x00,0x1C,0x00,0x1C,0x00,0x38,0x00,0x38,0x00,0x70,0x00,0x70,0x00,0xE0,0x00,0xE0,0x01,0xC0,0x01,0xC0,0x03,0x80,0x03,0x80,0x07,0x00,0x07,0x00,0x0E,0x00,0x0E,0x00,0x1C,0x00,0x1C,0x00,0x38,0x00,0x3F,0xFE,0x3F,0xFE,0x3F,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // Z ++0x01,0xF8,0x01,0xF8,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xF8,0x01,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // [ ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x00,0x38,0x00,0x38,0x00,0x1C,0x00,0x1C,0x00,0x0C,0x00,0x0E,0x00,0x0E,0x00,0x07,0x00,0x07,0x00,0x03,0x80,0x03,0x80,0x01,0x80,0x01,0xC0,0x01,0xC0,0x00,0xE0,0x00,0xE0,0x00,0x70,0x00,0x70,0x00,0x30,0x00,0x38,0x00,0x38,0x00,0x1C,0x00,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ++0x0F,0x80,0x0F,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x0F,0xC0,0x0F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ] ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xC0,0x03,0xC0,0x07,0xE0,0x07,0xF0,0x0E,0x70,0x1E,0x78,0x1C,0x38,0x38,0x1C,0x70,0x0E,0x70,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ^ ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // _ ++ ++0x00,0x00,0x00,0x00,0x00,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x03,0x80,0x03,0x80,0x03,0x80,0x03,0x80,0x03,0x80,0x03,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ` ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x1F,0xE0,0x3F,0xF0,0x3C,0x78,0x30,0x38,0x00,0x18,0x00,0x1C,0x00,0x1C,0x07,0xFC,0x1F,0xFC,0x3F,0xFC,0x38,0x1C,0x30,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x3C,0x38,0x3C,0x3C,0xFC,0x3F,0xDC,0x1F,0xDC,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // a ++0x00,0x00,0x00,0x00,0x38,0x00,0x38,0x00,0x38,0x00,0x38,0x00,0x38,0x00,0x38,0x00,0x38,0x80,0x3B,0xE0,0x3F,0xF0,0x3E,0x78,0x3C,0x38,0x38,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x0C,0x38,0x0C,0x38,0x0C,0x38,0x0C,0x38,0x0C,0x38,0x1C,0x38,0x1C,0x38,0x1C,0x3C,0x38,0x3E,0x78,0x3F,0xF0,0x3B,0xF0,0x01,0xC0,0x00,0x00,0x00,0x00,0x00,0x00, // b ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x03,0xF8,0x07,0xFC,0x0F,0x1C,0x1E,0x0C,0x1C,0x00,0x18,0x00,0x38,0x00,0x38,0x00,0x38,0x00,0x38,0x00,0x38,0x00,0x38,0x00,0x38,0x00,0x18,0x00,0x1C,0x00,0x1E,0x04,0x0F,0x1C,0x07,0xFC,0x03,0xF8,0x00,0xE0,0x00,0x00,0x00,0x00,0x00,0x00, // c ++0x00,0x00,0x00,0x00,0x00,0x1C,0x00,0x1C,0x00,0x1C,0x00,0x1C,0x00,0x1C,0x00,0x1C,0x01,0x1C,0x0F,0xDC,0x1F,0xFC,0x1E,0xFC,0x38,0x3C,0x38,0x3C,0x38,0x1C,0x30,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x30,0x1C,0x30,0x1C,0x38,0x3C,0x38,0x3C,0x1C,0x7C,0x1F,0xFC,0x0F,0xDC,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // d ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x07,0xE0,0x0F,0xF0,0x1E,0x78,0x1C,0x1C,0x38,0x1C,0x38,0x0C,0x30,0x0E,0x7F,0xFE,0x7F,0xFE,0x7F,0xFC,0x70,0x00,0x70,0x00,0x30,0x00,0x38,0x00,0x38,0x00,0x1C,0x04,0x1E,0x3C,0x0F,0xFC,0x07,0xF8,0x01,0xC0,0x00,0x00,0x00,0x00,0x00,0x00, // e ++0x00,0x00,0x00,0x00,0x00,0xFC,0x01,0xFC,0x01,0xF8,0x03,0x80,0x03,0x80,0x03,0x80,0x03,0x80,0x3F,0xFC,0x3F,0xFC,0x1F,0xF8,0x03,0x80,0x03,0x80,0x03,0x80,0x03,0x80,0x03,0x80,0x03,0x80,0x03,0x80,0x03,0x80,0x03,0x80,0x03,0x80,0x03,0x80,0x03,0x80,0x03,0x80,0x03,0x80,0x03,0x80,0x03,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // f ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x0F,0xDC,0x1F,0xFC,0x1C,0x7C,0x38,0x3C,0x38,0x1C,0x30,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x30,0x1C,0x30,0x1C,0x38,0x3C,0x3C,0x3C,0x1F,0xFC,0x0F,0xDC,0x07,0x9C,0x00,0x1C,0x00,0x18,0x00,0x38,0x1C,0xF0,0x1F,0xF0,0x0F,0xC0, // g ++0x00,0x00,0x00,0x00,0x38,0x00,0x38,0x00,0x38,0x00,0x38,0x00,0x38,0x00,0x38,0x00,0x38,0x40,0x3B,0xF0,0x3B,0xF0,0x3F,0xF8,0x3C,0x38,0x38,0x18,0x38,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // h ++0x00,0x00,0x00,0x00,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xC0,0x0F,0xC0,0x0F,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x0F,0xFC,0x1F,0xFE,0x1F,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // i ++0x00,0x00,0x00,0x00,0x00,0x80,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0xC0,0x1F,0xC0,0x01,0xC0,0x00,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x00,0xC0,0x01,0xC0,0x01,0xC0,0x1F,0x80,0x3F,0x80,0x3F,0x00, // j ++0x00,0x00,0x00,0x00,0x1C,0x00,0x1C,0x00,0x1C,0x00,0x1C,0x00,0x1C,0x00,0x1C,0x00,0x1C,0x00,0x1C,0x1C,0x1C,0x3C,0x1C,0x38,0x1C,0x70,0x1C,0xE0,0x19,0xC0,0x19,0xC0,0x1F,0x80,0x1F,0xC0,0x1F,0xC0,0x1C,0xE0,0x1C,0xE0,0x18,0x70,0x1C,0x70,0x1C,0x38,0x1C,0x1C,0x1C,0x1C,0x1C,0x0E,0x18,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // k ++0x00,0x00,0x0F,0x80,0x1F,0x80,0x1F,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0xC0,0x01,0xC0,0x00,0xFC,0x00,0xFE,0x00,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // l ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x6F,0x78,0x7F,0xFC,0x7B,0xDC,0x73,0x8E,0x71,0x8E,0x71,0x8E,0x61,0x8E,0x71,0x8E,0x71,0x8E,0x71,0x8E,0x71,0x8E,0x71,0x8E,0x71,0x8E,0x71,0x8E,0x71,0x8E,0x71,0x8E,0x71,0x8E,0x71,0x8E,0x61,0x8E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // m ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x3B,0xF0,0x3B,0xF0,0x3F,0xF8,0x3C,0x38,0x38,0x18,0x38,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // n ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x07,0xE0,0x0F,0xF0,0x1E,0x78,0x3C,0x38,0x38,0x1C,0x38,0x1C,0x30,0x1C,0x30,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x0C,0x30,0x1C,0x30,0x1C,0x38,0x1C,0x38,0x1C,0x3C,0x38,0x1E,0x78,0x0F,0xF0,0x0F,0xE0,0x01,0x80,0x00,0x00,0x00,0x00,0x00,0x00, // o ++ ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x3B,0xF0,0x3F,0xF8,0x3E,0x38,0x3C,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x0C,0x38,0x0C,0x38,0x0C,0x38,0x0C,0x38,0x1C,0x38,0x1C,0x38,0x1C,0x3C,0x38,0x3E,0x78,0x3F,0xF0,0x3B,0xE0,0x38,0x00,0x38,0x00,0x38,0x00,0x38,0x00,0x38,0x00,0x38,0x00, // p ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x0F,0xDC,0x1F,0xFC,0x1C,0x7C,0x38,0x3C,0x38,0x1C,0x30,0x1C,0x30,0x1C,0x70,0x1C,0x70,0x1C,0x70,0x1C,0x30,0x1C,0x38,0x1C,0x38,0x3C,0x38,0x3C,0x1E,0xFC,0x0F,0xFC,0x07,0x9C,0x00,0x1C,0x00,0x1C,0x00,0x1C,0x00,0x1C,0x00,0x1C,0x00,0x1C, // q ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x06,0x7E,0x0E,0xFE,0x0F,0xFE,0x0F,0x82,0x0F,0x00,0x0F,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // r ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x07,0xF0,0x0F,0xF8,0x1E,0x38,0x1C,0x08,0x18,0x00,0x18,0x00,0x1C,0x00,0x1E,0x00,0x1F,0xE0,0x0F,0xF0,0x03,0xF8,0x00,0x78,0x00,0x18,0x00,0x1C,0x00,0x18,0x10,0x38,0x1C,0x78,0x1F,0xF0,0x1F,0xE0,0x03,0x80,0x00,0x00,0x00,0x00,0x00,0x00, // s ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x3F,0xF8,0x7F,0xF8,0x3F,0xF8,0x07,0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x03,0x80,0x03,0xF8,0x03,0xF8,0x00,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // t ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x1C,0x18,0x1C,0x1C,0x3C,0x1E,0x7C,0x1F,0xFC,0x0F,0xDC,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // u ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x0E,0x70,0x0C,0x30,0x1C,0x38,0x1C,0x38,0x1C,0x18,0x18,0x1C,0x38,0x1C,0x38,0x1C,0x30,0x0C,0x30,0x0E,0x70,0x0E,0x70,0x06,0x60,0x06,0x60,0x07,0xE0,0x07,0xE0,0x03,0xC0,0x03,0xC0,0x03,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // v ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x03,0xE0,0x07,0xE0,0x07,0xE0,0x07,0x60,0x06,0x61,0x86,0x71,0x8E,0x73,0xCE,0x73,0xCE,0x33,0xCC,0x33,0xCC,0x32,0x4C,0x32,0x4C,0x3E,0x7C,0x3E,0x7C,0x1E,0x78,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // w ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x0C,0x38,0x1C,0x1C,0x38,0x1C,0x38,0x0E,0x70,0x0E,0x70,0x07,0xE0,0x03,0xC0,0x03,0xC0,0x03,0xC0,0x03,0xC0,0x07,0xE0,0x06,0x60,0x0E,0x70,0x1C,0x38,0x1C,0x38,0x38,0x1C,0x38,0x1C,0x70,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // x ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x0E,0x30,0x0E,0x38,0x0C,0x38,0x1C,0x18,0x1C,0x1C,0x18,0x1C,0x38,0x0C,0x38,0x0E,0x30,0x0E,0x70,0x06,0x70,0x07,0x60,0x03,0xE0,0x03,0xE0,0x03,0xC0,0x01,0xC0,0x01,0xC0,0x01,0x80,0x03,0x80,0x03,0x00,0x1F,0x00,0x3E,0x00,0x3C,0x00, // y ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0xFC,0x1F,0xFC,0x1F,0xFC,0x00,0x38,0x00,0x38,0x00,0x70,0x00,0xE0,0x00,0xE0,0x01,0xC0,0x01,0xC0,0x03,0x80,0x07,0x00,0x07,0x00,0x0E,0x00,0x0E,0x00,0x1C,0x00,0x3F,0xF8,0x3F,0xFC,0x1F,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // z ++0x00,0x78,0x00,0xFC,0x01,0xE0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x03,0x80,0x3F,0x00,0x3E,0x00,0x1F,0x00,0x03,0x80,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xE0,0x00,0xFC,0x00,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // { ++0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // | ++0x1E,0x00,0x1F,0x00,0x07,0x80,0x03,0x80,0x01,0x80,0x03,0x80,0x03,0x80,0x03,0x80,0x03,0x80,0x03,0x80,0x01,0x80,0x01,0xC0,0x01,0xC0,0x00,0xFC,0x00,0x7C,0x00,0xFC,0x01,0xC0,0x01,0xC0,0x01,0x80,0x03,0x80,0x03,0x80,0x03,0x80,0x03,0x80,0x01,0x80,0x03,0x80,0x07,0x80,0x1F,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // } ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x3E,0x00,0x3F,0x00,0x7F,0x02,0x63,0x87,0xE1,0xC7,0xC1,0xCE,0x40,0xFE,0x00,0x7C,0x00,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ~ ++0x00,0x00,0x00,0x00,0x07,0xC0,0x0F,0xE0,0x1C,0x70,0x38,0x38,0x30,0x18,0x30,0x18,0x30,0x18,0x38,0x38,0x1C,0x70,0x0F,0xE0,0x07,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ° ++}; +diff -ruN main/drivers/auxdisplay/openvfd/controllers/fonts/Grotesk16x32_v.h mod/drivers/auxdisplay/openvfd/controllers/fonts/Grotesk16x32_v.h +--- main/drivers/auxdisplay/openvfd/controllers/fonts/Grotesk16x32_v.h 1970-01-01 01:00:00.000000000 +0100 ++++ mod/drivers/auxdisplay/openvfd/controllers/fonts/Grotesk16x32_v.h 2023-03-07 09:42:05.761566151 +0100 +@@ -0,0 +1,107 @@ ++// Grotesk16x32_v.h ++// Font type : Full (96 characters) ++// Font size : 16x32 pixels ++// Memory usage : 6148 bytes ++ ++// Origin: http://www.rinkydinkelectronics.com/r_fonts.php ++// Modified by Arthur Liberman for compatibility with the OpenVFD driver. ++ ++const unsigned char Grotesk16x32_V[6148] = { ++0x10,0x20,0x20,0x60, ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0xF8,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x0F,0x0F,0x00,0x00,0x00,0x00,0x00,0x00, // ! ++0x00,0x00,0x00,0xC0,0xF0,0xFC,0x7C,0x00,0x00,0xC0,0xF0,0xFC,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x0F,0x0F,0x00,0x00,0x00,0x0F,0x0F,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // " ++0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0xF8,0x38,0x00,0x00,0xC0,0xF8,0x78,0x00,0x00,0x00,0x00,0x0E,0x0E,0x8E,0xFE,0xFF,0x0F,0x0E,0x0E,0xFE,0xFF,0x1F,0x0E,0x0E,0x0E,0x1C,0x1C,0x1C,0xFC,0xFF,0x3F,0x1C,0x1C,0xFC,0xFF,0x7F,0x1D,0x1C,0x1C,0x18,0x00,0x00,0x00,0x0E,0x0F,0x07,0x00,0x00,0x0C,0x0F,0x0F,0x00,0x00,0x00,0x00,0x00,0x00, // # ++0x00,0x00,0x00,0xC0,0xE0,0xE0,0x70,0x70,0xFF,0x70,0x70,0x70,0xE0,0xC0,0x00,0x00,0x00,0x00,0x0E,0x3F,0x7F,0xF0,0xE0,0xE0,0xFF,0xC0,0xC0,0xC0,0x80,0x00,0x00,0x00,0x00,0x00,0xC0,0xC0,0x80,0x00,0x00,0x01,0xFF,0x01,0x01,0x83,0xFF,0xFF,0x3C,0x00,0x00,0x00,0x01,0x03,0x03,0x03,0x03,0x07,0xFF,0x07,0x03,0x03,0x01,0x00,0x00,0x00, // $ ++0x80,0xE0,0xF0,0x70,0x30,0x70,0xF0,0xE0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x1F,0x38,0x70,0x70,0x70,0xB8,0x9F,0xCF,0xC0,0xE0,0x60,0x70,0x30,0x38,0x10,0x08,0x0C,0x0E,0x06,0x07,0x03,0x03,0xF1,0xF9,0x1C,0x0E,0x0E,0x0E,0x1C,0xF8,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x07,0x0F,0x0E,0x0C,0x0E,0x07,0x03,0x01, // % ++0x00,0x00,0x00,0xE0,0xF0,0xF8,0x3C,0x1C,0x1C,0x1C,0x38,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xE7,0xFF,0x7F,0xF8,0xE0,0x80,0x00,0x00,0x00,0x00,0x80,0x80,0x80,0x00,0xFF,0xFF,0xC3,0x00,0x00,0x00,0x03,0x0F,0x3F,0x7C,0xF0,0xE0,0xFF,0x7F,0x0F,0x00,0x01,0x03,0x07,0x0F,0x0E,0x1C,0x1C,0x0C,0x0E,0x0E,0x07,0x07,0x0F,0x0E,0x08, // & ++0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xF0,0xFC,0x7C,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x0F,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ' ++0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xF0,0xFE,0x1F,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0xFF,0xFF,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xFF,0xFF,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0F,0x3F,0x7C,0x60,0x00,0x00,0x00,0x00,0x00, // ( ++0x00,0x00,0x00,0x00,0x00,0x03,0x1F,0xFE,0xF0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xFF,0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xFF,0xFF,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x7C,0x3F,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ) ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x1C,0x18,0x38,0x70,0xE0,0xFF,0xFF,0xE0,0x60,0x30,0x38,0x1C,0x0C,0x00,0x00,0x18,0x1C,0x1C,0x0E,0x07,0x03,0xFF,0xFF,0x03,0x07,0x06,0x0E,0x1C,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // * ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xC0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xFF,0xFF,0xFF,0xC0,0xC0,0xC0,0xC0,0xC0,0x00,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0xFF,0xFF,0xFF,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // + ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0xF0,0xF0,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xFC,0xFF,0x7F,0x0F,0x03,0x00,0x00,0x00,0x00,0x00,0x00, // , ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // - ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xE0,0xE0,0xE0,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x0F,0x0F,0x0F,0x0F,0x00,0x00,0x00,0x00,0x00,0x00, // . ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xE0,0xF0,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xF8,0xFE,0x1F,0x07,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xE0,0xF8,0x7F,0x0F,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x0F,0x07,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // / ++0x00,0x00,0x00,0xE0,0xF0,0xF8,0x38,0x1C,0x1C,0x3C,0x78,0xF0,0xE0,0x80,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0x00,0x00,0xC0,0xF0,0x7C,0x0F,0x0F,0xFF,0xFF,0xE0,0x00,0x00,0x00,0x7F,0xFF,0xFF,0xFC,0x1F,0x07,0x01,0x00,0x00,0xF8,0xFF,0xFF,0x01,0x00,0x00,0x00,0x00,0x01,0x07,0x0F,0x0E,0x1C,0x1C,0x0E,0x0F,0x07,0x03,0x00,0x00,0x00, // 0 ++0x00,0x00,0x00,0xE0,0xE0,0xF0,0x70,0x78,0xF8,0xF8,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x0E,0x0E,0x0E,0x0E,0x0F,0x0F,0x0E,0x0E,0x0E,0x0E,0x04,0x00, // 1 ++0x00,0x00,0x70,0x78,0x38,0x3C,0x1C,0x1C,0x1C,0x1C,0x38,0x78,0xF0,0xE0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xF0,0xFF,0x3F,0x0F,0x00,0x00,0x00,0x00,0x80,0xC0,0xE0,0xF0,0x3C,0x1E,0x0F,0x07,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x0F,0x0F,0x0F,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x00, // 2 ++0x00,0x00,0x30,0x38,0x38,0x3C,0x1C,0x1C,0x1C,0x3C,0x78,0xF8,0xF0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xE0,0xE0,0xE0,0xE0,0xF0,0xBF,0x1F,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x87,0xFF,0xFE,0x78,0x00,0x00,0x00,0x0F,0x0E,0x0E,0x0E,0x1E,0x1E,0x1E,0x0E,0x0F,0x0F,0x07,0x03,0x00,0x00, // 3 ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xF0,0x78,0xF8,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xF0,0x7C,0x1F,0x07,0x00,0xFC,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x3C,0x3F,0x3F,0x39,0x38,0x38,0x38,0x38,0x79,0xFF,0xFF,0x38,0x38,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x0F,0x0F,0x00,0x00,0x00,0x00, // 4 ++0x00,0x00,0x00,0xF8,0xF8,0xF8,0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x7F,0x3F,0x38,0x38,0x38,0x78,0xF0,0xF0,0xE0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0xFF,0xFF,0x7E,0x00,0x00,0x00,0x0F,0x0E,0x0E,0x1E,0x1E,0x1E,0x1E,0x0E,0x0F,0x07,0x07,0x01,0x00,0x00, // 5 ++0x00,0x00,0x00,0xC0,0xF0,0xF8,0x38,0x3C,0x1C,0x1C,0x1C,0x3C,0x38,0x00,0x00,0x00,0x00,0x00,0xFE,0xFF,0xEF,0xE0,0x70,0x38,0x38,0x38,0x78,0xF0,0xE0,0xC0,0x00,0x00,0x00,0x00,0x7F,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0xFF,0xFF,0x3C,0x00,0x00,0x00,0x00,0x03,0x07,0x0F,0x0E,0x1C,0x1C,0x1C,0x0E,0x0F,0x07,0x01,0x00,0x00, // 6 ++0x00,0x00,0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x38,0xF8,0xF8,0xF8,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xF8,0xFF,0x3F,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xFC,0xFF,0x1F,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x0F,0x0F,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 7 ++0x00,0x00,0x80,0xF0,0xF8,0x78,0x3C,0x1C,0x1C,0x1C,0x38,0xF8,0xF0,0xC0,0x00,0x00,0x00,0x00,0x07,0x1F,0xBF,0xF8,0xE0,0xE0,0xE0,0xE0,0xF0,0xBF,0x1F,0x0F,0x00,0x00,0x00,0x00,0xFC,0xFF,0xFF,0x03,0x01,0x00,0x00,0x01,0x01,0x87,0xFF,0xFE,0x78,0x00,0x00,0x00,0x01,0x07,0x0F,0x0F,0x0E,0x1C,0x1C,0x1E,0x0E,0x0F,0x07,0x03,0x00,0x00, // 8 ++0x00,0x00,0xC0,0xF0,0xF8,0x38,0x1C,0x1C,0x1C,0x3C,0x78,0xF8,0xE0,0x80,0x00,0x00,0x00,0x00,0xFF,0xFF,0xF3,0x00,0x00,0x00,0x00,0x00,0x80,0xFF,0xFF,0xFF,0xE0,0x00,0x00,0x00,0x00,0x03,0x07,0x07,0x0F,0x0E,0x0E,0x07,0x83,0xF1,0xFF,0x7F,0x01,0x00,0x00,0x00,0x00,0x0E,0x0E,0x0E,0x1E,0x1E,0x0E,0x0E,0x0F,0x07,0x01,0x00,0x00,0x00, // 9 ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x3F,0x3F,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0xF0,0xF0,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x03,0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x00, // : ++0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x3F,0x3F,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0xF0,0xF0,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x78,0x7F,0x7F,0x1F,0x03,0x00,0x00,0x00,0x00,0x00,0x00, // ; ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0xC0,0xE0,0xE0,0xF0,0x70,0x38,0x38,0x1C,0x1C,0x0E,0x0E,0x07,0x07,0x03,0x00,0x00,0x01,0x03,0x03,0x07,0x07,0x0F,0x0E,0x1E,0x1C,0x3C,0x38,0x78,0x70,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // < ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x00,0x00,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // = ++0x00,0x80,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x07,0x07,0x0F,0x0E,0x1E,0x1C,0x3C,0x38,0x78,0x70,0xF0,0xE0,0xE0,0x00,0x00,0xE0,0xF0,0x70,0x38,0x38,0x1C,0x1C,0x0E,0x0E,0x07,0x07,0x03,0x03,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // > ++0x00,0x00,0x00,0x70,0x78,0x38,0x1C,0x1C,0x1C,0x1C,0x3C,0xF8,0xF0,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xE0,0xF0,0x78,0x3F,0x1F,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x1F,0x1B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x0F,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ? ++0x00,0x00,0x80,0xE0,0xF0,0x70,0x38,0x18,0x18,0x18,0x38,0x38,0xF0,0xE0,0x80,0x00,0xF0,0xFE,0x1F,0x03,0x00,0xC0,0xF0,0x78,0x1C,0x1C,0x1C,0x1C,0x38,0xFF,0xFF,0x00,0x3F,0xFF,0xE0,0x00,0x00,0x1F,0x7F,0xF8,0xE0,0xC0,0xC0,0xE0,0x70,0xFF,0xFF,0x00,0x00,0x01,0x07,0x1F,0x3C,0x78,0x70,0x60,0xE0,0xE1,0xE1,0xE0,0xE0,0xE0,0x40,0x00, // @ ++0x00,0x00,0x00,0x00,0x00,0xE0,0xF8,0x78,0xF8,0xF8,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xFE,0xFF,0x0F,0x00,0x01,0x3F,0xFF,0xF8,0x80,0x00,0x00,0x00,0x00,0xC0,0xFC,0xFF,0x3F,0x3D,0x3C,0x3C,0x3C,0x3C,0x3F,0x7F,0xFF,0xF8,0x00,0x00,0x0C,0x0F,0x0F,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x0F,0x0F,0x00, // A ++0x00,0x00,0xF8,0xF8,0xF8,0x38,0x38,0x38,0x38,0x38,0x78,0xF0,0xE0,0xC0,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0x70,0x70,0x70,0x70,0xF0,0xF8,0xFF,0x9F,0x07,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x83,0xFF,0xFF,0x78,0x00,0x00,0x00,0x0F,0x0F,0x0F,0x0E,0x0E,0x0E,0x0E,0x0E,0x0F,0x07,0x07,0x01,0x00,0x00, // B ++0x00,0x00,0x00,0xC0,0xF0,0xF8,0x38,0x3C,0x1C,0x1C,0x1C,0x3C,0x38,0x70,0x00,0x00,0x00,0xF0,0xFF,0xFF,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x7F,0xFF,0xFC,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x07,0x0F,0x0E,0x1C,0x1C,0x1E,0x0E,0x0F,0x07,0x00,0x00, // C ++0x00,0xF8,0xF8,0xF8,0x38,0x38,0x38,0x38,0x38,0x78,0xF0,0xE0,0xC0,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xFF,0xFF,0xFF,0x00,0x00,0x00,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xFF,0xFF,0x3F,0x00,0x00,0x00,0x07,0x0F,0x0F,0x0E,0x0E,0x0E,0x0E,0x0F,0x07,0x07,0x03,0x01,0x00,0x00,0x00, // D ++0x00,0x00,0xF8,0xF8,0xF8,0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x60,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x0F,0x0F,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x00,0x00, // E ++0x00,0x00,0x00,0xF8,0xF8,0xF8,0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x60,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x0F,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // F ++0x00,0x00,0x80,0xE0,0xF0,0x78,0x38,0x1C,0x1C,0x1C,0x1C,0x38,0x78,0x70,0x00,0x00,0x00,0xF8,0xFF,0xFF,0x07,0x00,0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x0F,0xFF,0xFF,0xF0,0x00,0x00,0x00,0x00,0x03,0x03,0x73,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x03,0x07,0x0F,0x0E,0x0E,0x1C,0x1C,0x0E,0x0F,0x0F,0x07,0x00,0x00, // G ++0x00,0xF8,0xF8,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0xF8,0xF8,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xF0,0x70,0x70,0x70,0x70,0x70,0x70,0xFF,0xFF,0xFF,0x00,0x00,0x00,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x07,0x0F,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x0F,0x0F,0x00,0x00, // H ++0x00,0x00,0x38,0x38,0x38,0x38,0xF8,0xF8,0xF8,0x38,0x38,0x38,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0x0E,0x0E,0x0E,0x0F,0x0F,0x0F,0x0E,0x0E,0x0E,0x0E,0x00,0x00,0x00, // I ++0x00,0x00,0x00,0x00,0x18,0x38,0x38,0x38,0x38,0xB8,0xF8,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xEF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x07,0x0F,0x0E,0x0E,0x1C,0x1C,0x1E,0x0E,0x0F,0x07,0x03,0x00,0x00,0x00,0x00, // J ++0x00,0xF8,0xF8,0xF8,0x00,0x00,0x00,0x00,0x00,0x80,0xE0,0xF0,0x78,0x38,0x08,0x00,0x00,0xFF,0xFF,0xFF,0xE0,0xF0,0xF8,0xFE,0xCF,0x07,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0x03,0x00,0x00,0x03,0x0F,0x3F,0xFC,0xF0,0xC0,0x80,0x00,0x00,0x00,0x07,0x0F,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x0F,0x0F,0x0E,0x08, // K ++0x00,0x00,0xF8,0xF8,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x0F,0x0F,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x00, // L ++0xF8,0xF8,0xF8,0xF8,0xE0,0x00,0x00,0x00,0x00,0x80,0xF8,0xF8,0xF8,0xF8,0x00,0x00,0xFF,0xFF,0xFF,0x01,0x1F,0xFE,0xE0,0xC0,0xFC,0x7F,0x03,0x00,0xFF,0xFF,0x00,0x00,0xFF,0xFF,0xFF,0x00,0x00,0x01,0x07,0x07,0x03,0x00,0x00,0x00,0xFF,0xFF,0x00,0x00,0x0F,0x0F,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x0F,0x00,0x00, // M ++0xF8,0xF8,0xF8,0xF8,0xE0,0x80,0x00,0x00,0x00,0x00,0x00,0xF8,0xF8,0xF8,0x00,0x00,0xFF,0xFF,0xFF,0x01,0x0F,0x7F,0xFC,0xE0,0x80,0x00,0x00,0xFF,0xFF,0xFF,0x00,0x00,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x01,0x0F,0x7F,0xFC,0xE0,0xFF,0xFF,0xFF,0x00,0x00,0x0F,0x0F,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x0F,0x0F,0x0F,0x0F,0x00,0x00, // N ++0x00,0x00,0xC0,0xF0,0xF8,0x78,0x3C,0x1C,0x1C,0x3C,0x78,0xF0,0xE0,0x80,0x00,0x00,0x00,0xF8,0xFF,0xFF,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0xDF,0xFF,0xFF,0xE0,0x00,0x00,0x0F,0xFF,0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0x01,0x00,0x00,0x00,0x00,0x03,0x07,0x0F,0x0E,0x1C,0x1C,0x0E,0x0F,0x07,0x03,0x00,0x00,0x00, // O ++0x00,0x00,0xF8,0xF8,0xF8,0x38,0x38,0x38,0x38,0x38,0x38,0xF8,0xF0,0xE0,0x80,0x00,0x00,0x00,0xFF,0xFF,0xFF,0x80,0x80,0x80,0x80,0x80,0xC0,0xE0,0xFF,0xFF,0x1F,0x00,0x00,0x00,0xFF,0xFF,0xFF,0x03,0x03,0x03,0x03,0x03,0x03,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x0F,0x0F,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // P ++0x00,0x00,0xC0,0xF0,0xF8,0x38,0x1C,0x1C,0x1C,0x3C,0x78,0xF8,0xE0,0x80,0x00,0x00,0x00,0xFC,0xFF,0xFF,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0xDF,0xFF,0xFF,0xE0,0x00,0x00,0x0F,0xFF,0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x80,0xFE,0xFF,0x7F,0x01,0x00,0x00,0x00,0x00,0x03,0x07,0x07,0x0E,0x0E,0x0E,0x1F,0x7F,0xF3,0x61,0x00,0x00,0x00, // Q ++0x00,0x00,0xF8,0xF8,0xB8,0x38,0x38,0x38,0x38,0x38,0xF8,0xF0,0xE0,0x80,0x00,0x00,0x00,0x00,0xFF,0xFF,0xDF,0xC0,0xC0,0xC0,0xC0,0xC0,0xE0,0xFF,0x7F,0x1F,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFB,0x03,0x03,0x03,0x03,0x07,0x1F,0xFE,0xF8,0xE0,0x00,0x00,0x00,0x00,0x0F,0x0F,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x0F,0x0F,0x08, // R ++0x00,0x00,0xE0,0xF0,0xF8,0x38,0x1C,0x1C,0x1C,0x1C,0x3C,0x38,0x78,0x00,0x00,0x00,0x00,0x06,0x3F,0x7F,0xF8,0xF0,0xE0,0xE0,0xE0,0xC0,0xC0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x03,0x03,0xDF,0xFF,0xFE,0x00,0x00,0x00,0x00,0x07,0x0F,0x0E,0x0E,0x1C,0x1C,0x1C,0x0E,0x0F,0x0F,0x07,0x01,0x00,0x00, // S ++0x18,0x38,0x38,0x38,0x38,0x38,0xB8,0xF8,0xF8,0x38,0x38,0x38,0x38,0x38,0x38,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x0F,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // T ++0x00,0x00,0xF8,0xF8,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0xF8,0xF8,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x01,0x07,0x0F,0x0E,0x0E,0x1C,0x1C,0x0E,0x0E,0x0F,0x07,0x01,0x00,0x00, // U ++0x00,0x78,0xF8,0xF8,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xF8,0xF8,0x78,0x00,0x00,0x00,0x07,0xFF,0xFF,0xF0,0x00,0x00,0x00,0x00,0xF0,0xFF,0xFF,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xFF,0xFE,0x80,0x80,0xFE,0xFF,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0F,0x0F,0x0F,0x0F,0x01,0x00,0x00,0x00,0x00,0x00, // V ++0xF8,0xF8,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0xF8,0xF8,0x00,0xFF,0xFF,0xF0,0x00,0x00,0xFC,0x7E,0xFE,0xFC,0x00,0x00,0xF0,0xFF,0xFF,0x00,0x00,0x01,0xFF,0xFF,0xE0,0xFF,0x3F,0x00,0x00,0x3F,0xFF,0xE0,0xFF,0xFF,0x01,0x00,0x00,0x00,0x03,0x0F,0x0F,0x0F,0x00,0x00,0x00,0x00,0x0F,0x0F,0x0F,0x03,0x00,0x00, // W ++0x00,0x08,0x38,0xF8,0xF0,0xC0,0x00,0x00,0x00,0x00,0x80,0xE0,0xF8,0x78,0x18,0x00,0x00,0x00,0x00,0x00,0x03,0x0F,0xBF,0xF8,0xF8,0xFE,0x1F,0x07,0x01,0x00,0x00,0x00,0x00,0x00,0x80,0xE0,0xF8,0x7E,0x1F,0x07,0x03,0x0F,0x7F,0xF8,0xE0,0x80,0x00,0x00,0x08,0x0E,0x0F,0x07,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x07,0x0F,0x0E,0x08, // X ++0x00,0x18,0xF8,0xF8,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xF8,0x78,0x18,0x00,0x00,0x00,0x00,0x03,0x0F,0x3F,0xFC,0xE0,0xE0,0xFC,0x3F,0x0F,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFD,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x0F,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // Y ++0x00,0x00,0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x38,0x38,0xF8,0xF8,0xF8,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xF0,0xFC,0x3F,0x0F,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xF0,0xFC,0x3F,0x0F,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x0F,0x0F,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x00, // Z ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0x03,0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x0F,0x0F,0x0C,0x0C,0x0C,0x00,0x00,0x00, // [ ++0x00,0x10,0x70,0xF0,0xE0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0F,0x3F,0xFC,0xF0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x1F,0x7E,0xF8,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x0F,0x0F,0x0C,0x00,0x00, // ++0x00,0x00,0x00,0x00,0x03,0x03,0x03,0xFF,0xFF,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x0C,0x0C,0x0F,0x0F,0x07,0x00,0x00,0x00,0x00,0x00,0x00, // ] ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xE0,0xF0,0x7C,0x3F,0x0F,0x0F,0x3F,0x7C,0xF8,0xE0,0x80,0x00,0x00,0x00,0x03,0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ^ ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E, // _ ++0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xF8,0xFC,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x0F,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ` ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x1E,0x0E,0x0E,0x06,0x07,0x06,0x0E,0x1E,0xFC,0xF8,0xC0,0x00,0x00,0x00,0xE0,0xFC,0xFE,0x0E,0x07,0x07,0x07,0x07,0x07,0x87,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x07,0x0F,0x0F,0x1E,0x1C,0x1C,0x0E,0x0E,0x03,0x0F,0x0F,0x0F,0x00,0x00, // a ++0x00,0x00,0xFC,0xFC,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0x1C,0x0E,0x06,0x07,0x0E,0x1E,0xFC,0xF8,0xE0,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xFF,0xFF,0x00,0x00,0x00,0x00,0x0F,0x0F,0x0F,0x07,0x0E,0x1C,0x1C,0x1E,0x0F,0x0F,0x03,0x00,0x00,0x00, // b ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xF0,0xF8,0x3C,0x1E,0x0E,0x06,0x07,0x06,0x0E,0x1E,0x1C,0x00,0x00,0x00,0x00,0x3F,0xFF,0xFF,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x07,0x0F,0x0E,0x1C,0x1C,0x1C,0x0E,0x0E,0x07,0x00,0x00, // c ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFC,0xFC,0xFC,0x00,0x00,0x00,0x00,0xF0,0xFC,0x7E,0x0E,0x0E,0x07,0x0E,0x0E,0x3C,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x1F,0xFF,0xFF,0x80,0x00,0x00,0x00,0x00,0x00,0x80,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x01,0x07,0x0F,0x0E,0x1C,0x1C,0x0C,0x0E,0x07,0x0F,0x0F,0x0F,0x00,0x00, // d ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xF8,0x7C,0x1E,0x0E,0x06,0x07,0x0E,0x0E,0x3C,0xF8,0xF0,0x80,0x00,0x00,0x1F,0xFF,0xFF,0xC7,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x03,0x00,0x00,0x00,0x00,0x03,0x07,0x0F,0x0E,0x1C,0x1C,0x1C,0x0E,0x0E,0x0E,0x07,0x00,0x00, // e ++0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xF8,0xFC,0x1C,0x1C,0x1C,0x1C,0x0C,0x00,0x00,0x00,0x00,0x06,0x0E,0x0E,0x0E,0xFF,0xFF,0xFF,0x0E,0x0E,0x0E,0x0E,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x0F,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // f ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xF0,0xFC,0x3E,0x0E,0x06,0x07,0x06,0x0E,0x1C,0xFE,0xFE,0xFE,0x00,0x00,0x00,0x07,0x7F,0xFF,0xE0,0xC0,0x80,0x80,0x80,0x80,0xE0,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x60,0xE1,0xE3,0xC3,0xC3,0xE3,0xE1,0x70,0x7F,0x1F,0x07,0x00,0x00, // g ++0x00,0x00,0xFC,0xFC,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0x18,0x0E,0x0E,0x0E,0x0F,0x1E,0xFE,0xF8,0xC0,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x0F,0x0F,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x0F,0x0F,0x00,0x00, // h ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3C,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0x0E,0x0E,0x0E,0xFE,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x0E,0x0E,0x0E,0x0E,0x0F,0x0F,0x0E,0x0E,0x0E,0x0E,0x0C,0x00, // i ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x3C,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x06,0x06,0x06,0xEE,0xFE,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xE0,0xE0,0xE0,0xE0,0xFB,0x7F,0x1F,0x00,0x00,0x00,0x00,0x00,0x00, // j ++0x00,0x00,0x00,0xFC,0xFC,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x3F,0x00,0xC0,0xE0,0xF0,0x3C,0x1E,0x0E,0x06,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xDF,0x07,0x07,0x1F,0x7E,0xF8,0xE0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x0F,0x07,0x00,0x00,0x00,0x00,0x00,0x03,0x0F,0x0F,0x0C,0x00, // k ++0x00,0x00,0x00,0x0C,0x0E,0x0E,0x0E,0xFE,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x07,0x0F,0x0E,0x0E,0x0E,0x0E,0x04,0x00, // l ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0xFE,0x7C,0x0E,0x06,0x1E,0xFE,0xFC,0x0E,0x06,0x0F,0xFE,0xFC,0xF0,0x00,0x00,0xFF,0xFF,0xFF,0x00,0x00,0x00,0xFF,0xFF,0x00,0x00,0x00,0xFF,0xFF,0xFF,0x00,0x00,0x0F,0x0F,0x07,0x00,0x00,0x00,0x0F,0x0F,0x00,0x00,0x00,0x0F,0x0F,0x0F,0x00, // m ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0xFE,0xFE,0x18,0x0E,0x0E,0x0E,0x0F,0x1E,0xFE,0xF8,0xC0,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x0F,0x0F,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x0F,0x0F,0x00,0x00, // n ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0xF8,0x7C,0x1E,0x0E,0x07,0x06,0x0E,0x1E,0xFC,0xF8,0xE0,0x00,0x00,0x00,0x0E,0xFF,0xFF,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0xF7,0xFF,0xFF,0x00,0x00,0x00,0x00,0x01,0x03,0x0F,0x0F,0x0E,0x1C,0x1C,0x0E,0x0F,0x07,0x03,0x00,0x00,0x00, // o ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0xFE,0xFE,0x1C,0x0E,0x06,0x07,0x06,0x0E,0x7E,0xFC,0xF0,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xC0,0x80,0x00,0x00,0x80,0xC0,0xF8,0xFF,0x3F,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0x01,0x03,0x03,0x03,0x03,0x03,0x01,0x00,0x00,0x00,0x00, // p ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0xFC,0x3E,0x0E,0x06,0x07,0x06,0x0E,0x1C,0xFE,0xFE,0xFE,0x00,0x00,0x00,0x07,0x7F,0xFF,0xF0,0x80,0x80,0x00,0x80,0x80,0xE0,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x03,0x03,0x03,0x01,0x01,0xFF,0xFF,0xFF,0x00,0x00, // q ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFC,0xFE,0xFE,0x78,0x1C,0x0E,0x0E,0x0F,0x0E,0x0E,0x1E,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x0F,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // r ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0xFC,0x9E,0x0E,0x06,0x07,0x06,0x0E,0x0E,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x07,0x07,0x0F,0x0E,0x0E,0x1E,0x1E,0xFC,0xF8,0x40,0x00,0x00,0x00,0x00,0x00,0x0F,0x0E,0x0E,0x1C,0x1C,0x1C,0x0E,0x0F,0x07,0x03,0x00,0x00,0x00, // s ++0x00,0x00,0x00,0x00,0x00,0xF0,0xF0,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x0E,0x0E,0x0E,0xFF,0xFF,0xFF,0x0E,0x0E,0x0E,0x0E,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x0F,0x0E,0x0E,0x0E,0x0E,0x00,0x00,0x00, // t ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0xFE,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0xFE,0xFE,0x00,0x00,0x00,0x00,0x7F,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x07,0x0F,0x0F,0x1E,0x1C,0x0C,0x0E,0x07,0x0F,0x0F,0x0F,0x00,0x00, // u ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x3E,0xFE,0xF0,0x80,0x00,0x00,0x00,0x00,0x80,0xF8,0xFE,0x3E,0x02,0x00,0x00,0x00,0x00,0x03,0x1F,0xFF,0xF8,0x80,0x80,0xF8,0xFF,0x1F,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0F,0x0F,0x0F,0x0F,0x01,0x00,0x00,0x00,0x00,0x00, // v ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0xFE,0xFC,0x80,0x00,0x00,0x00,0xC0,0xC0,0x00,0x00,0x00,0x80,0xFC,0xFE,0x1E,0x00,0x03,0xFF,0xFF,0xC0,0xC0,0xFF,0x0F,0x0F,0xFF,0xC0,0xC0,0xFF,0xFF,0x03,0x00,0x00,0x00,0x00,0x0F,0x0F,0x0F,0x01,0x00,0x00,0x01,0x0F,0x0F,0x0F,0x00,0x00,0x00, // w ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x1E,0x7C,0xF8,0xE0,0x80,0x80,0xE0,0xF8,0x7C,0x1E,0x06,0x00,0x00,0x00,0x00,0x00,0x80,0xC0,0xF0,0x7F,0x1F,0x1F,0x7F,0xF0,0xC0,0x80,0x00,0x00,0x00,0x00,0x08,0x0E,0x0F,0x07,0x01,0x00,0x00,0x00,0x00,0x01,0x07,0x0F,0x0E,0x08,0x00, // x ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x1E,0xFE,0xF8,0xC0,0x00,0x00,0x00,0x00,0x80,0xF0,0xFE,0x3E,0x06,0x00,0x00,0x00,0x00,0x00,0x07,0x1F,0xFE,0xF0,0xE0,0xFC,0x7F,0x0F,0x01,0x00,0x00,0x00,0x00,0x00,0xC0,0xE0,0xE0,0xE0,0x78,0x3F,0x0F,0x03,0x00,0x00,0x00,0x00,0x00,0x00, // y ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0x0E,0x0E,0x0E,0x0E,0x8E,0xCE,0xFE,0x7E,0x3E,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xF0,0xF8,0x3E,0x0F,0x07,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x0F,0x0F,0x0F,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0C,0x00,0x00, // z ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFC,0xFE,0xFF,0x07,0x03,0x03,0x02,0x00,0x00,0x00,0x00,0x60,0xE0,0xE0,0xE0,0xF0,0xBF,0x1F,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xFF,0xFF,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x07,0x0F,0x0E,0x0C,0x0C,0x0C,0x00,0x00, // { ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x0F,0x0F,0x00,0x00,0x00,0x00,0x00,0x00, // | ++0x00,0x00,0x00,0x03,0x03,0x07,0xEF,0xFE,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x1F,0xBF,0xF8,0xE0,0xE0,0xE0,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x78,0xFF,0xFF,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x0C,0x0E,0x0F,0x07,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // } ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xF0,0x7C,0x1C,0x1E,0x1E,0x3C,0xF8,0xE0,0xC0,0x00,0x00,0x80,0xE0,0xF0,0x60,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x07,0x07,0x07,0x03,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ~ ++0x00,0x00,0x00,0xC0,0xF0,0x38,0x1C,0x0C,0x0C,0x0C,0x1C,0x38,0xF0,0xC0,0x00,0x00,0x00,0x00,0x00,0x03,0x07,0x0E,0x1C,0x18,0x18,0x18,0x1C,0x0E,0x07,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ° ++}; +diff -ruN main/drivers/auxdisplay/openvfd/controllers/fonts/Grotesk24x48_v.h mod/drivers/auxdisplay/openvfd/controllers/fonts/Grotesk24x48_v.h +--- main/drivers/auxdisplay/openvfd/controllers/fonts/Grotesk24x48_v.h 1970-01-01 01:00:00.000000000 +0100 ++++ mod/drivers/auxdisplay/openvfd/controllers/fonts/Grotesk24x48_v.h 2023-03-07 09:42:05.797566429 +0100 +@@ -0,0 +1,107 @@ ++// Grotesk24x48_v.h ++// Font type : Full (96 characters) ++// Font size : 24x48 pixels ++// Memory usage : 13828 bytes ++ ++// Origin: http://www.rinkydinkelectronics.com/r_fonts.php ++// Modified by Arthur Liberman for compatibility with the OpenVFD driver. ++ ++const unsigned char Grotesk24x48_V[13828] = { ++0x18,0x30,0x20,0x60, ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0xF0,0xF0,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x1F,0x1F,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0xF0,0xF0,0xF0,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x03,0x03,0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ! ++0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xF0,0xF8,0xF8,0x38,0x00,0x00,0x00,0x00,0x80,0xF0,0xF8,0xF8,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0xFE,0xFF,0xFF,0xFF,0x0F,0x00,0x00,0x00,0xF0,0xFE,0xFF,0xFF,0xFF,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x03,0x03,0x03,0x03,0x00,0x00,0x00,0x00,0x03,0x03,0x03,0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // " ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xE0,0xE0,0x00,0x00,0x00,0x00,0x00,0xE0,0xE0,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xC0,0xC0,0xC0,0xC0,0xE0,0xFF,0xFF,0xFF,0xC3,0xC0,0xC0,0xC0,0xE0,0xFF,0xFF,0xFF,0xC3,0xC0,0xC0,0xC0,0x00,0x00,0x00,0x03,0x03,0x03,0x03,0xFB,0xFF,0xFF,0x1F,0x03,0x03,0x03,0x03,0xFB,0xFF,0xFF,0x0F,0x03,0x03,0x03,0x03,0x03,0xF0,0xF8,0xF8,0xF8,0xF8,0xF8,0xFF,0xFF,0xFF,0xFB,0xF8,0xF8,0xF8,0xF8,0xFF,0xFF,0xFF,0xF9,0xF8,0xF8,0xF8,0x70,0x00,0x00,0x00,0x00,0x00,0x80,0xFC,0xFF,0xFF,0x0F,0x00,0x00,0x00,0x80,0xFC,0xFF,0xFF,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x03,0x03,0x01,0x00,0x00,0x00,0x00,0x03,0x03,0x03,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // # ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x80,0xC0,0xC0,0xFF,0xFF,0xC0,0xC0,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0xFE,0xFF,0x3F,0x0F,0x07,0x03,0x03,0xFF,0xFF,0x03,0x03,0x03,0x07,0x07,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x1F,0x3F,0x7F,0xFC,0xF8,0xF0,0xF0,0xFF,0xFF,0xE0,0xE0,0xE0,0xC0,0x80,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xFF,0xFF,0x01,0x03,0x03,0x07,0xFF,0xFF,0xFE,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x3C,0x78,0x78,0xF8,0xF0,0xF0,0xF0,0xFF,0xFF,0xF0,0xF0,0x78,0x7C,0x3F,0x1F,0x0F,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // $ ++0x00,0x00,0x00,0x80,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0xFC,0xFF,0x9F,0x07,0x03,0x01,0x01,0x03,0x07,0xFF,0xFF,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x0F,0x1F,0x3E,0x3C,0x3C,0x3C,0x3C,0x9E,0x9F,0xCF,0xC3,0xE0,0xE0,0xF0,0x70,0x78,0x38,0x3C,0x1C,0x1E,0x0E,0x00,0x00,0x78,0x78,0x38,0x3C,0x1E,0x1E,0x0F,0x07,0x07,0x03,0xC3,0xF1,0xF9,0x78,0x3C,0x1C,0x1C,0x3C,0x3C,0xF8,0xF0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0xFF,0xFF,0xE0,0xC0,0x80,0x80,0xC0,0xC0,0xF0,0xFF,0x7F,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x03,0x03,0x03,0x03,0x03,0x01,0x00,0x00,0x00, // % ++0x00,0x00,0x00,0x00,0x00,0x80,0xC0,0xE0,0xF0,0xF0,0xF8,0xF8,0xF8,0xF8,0xF0,0xF0,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xE0,0xF0,0xFB,0x7F,0x3F,0xFF,0xFC,0xF0,0xC0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x00,0xF8,0xFF,0xFF,0xFF,0x07,0x01,0x00,0x00,0x00,0x01,0x07,0x1F,0x7F,0xFE,0xF8,0xE0,0x80,0x00,0x00,0xFF,0xFF,0xFF,0x07,0x00,0x07,0x1F,0x7F,0xFF,0xFE,0xF0,0xE0,0xC0,0xC0,0x80,0x80,0x80,0xC0,0xC1,0xE7,0xFF,0xFF,0xFF,0xFF,0xFF,0xC7,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x03,0x07,0x07,0x07,0x07,0x07,0x07,0x03,0x03,0x01,0x00,0x00,0x03,0x03,0x03,0x03,0x02, // & ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xF8,0xF8,0xF8,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0xFF,0xFF,0xFF,0xFF,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x03,0x03,0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ' ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xF8,0xFE,0x7F,0x0F,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0xFF,0xFF,0x7F,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x7F,0xFF,0xFF,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x0F,0x3F,0x7F,0x78,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ( ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x0F,0x7F,0xFE,0xF8,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x7F,0xFF,0xFF,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0xFF,0xFF,0x7F,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x78,0x7F,0x3F,0x0F,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ) ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0xFE,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xC0,0x80,0x00,0x00,0x02,0x03,0x07,0x0F,0x0F,0x1E,0x3C,0x38,0x78,0xF0,0xFF,0xFF,0xFF,0xF0,0x78,0x3C,0x3E,0x1E,0x0F,0x07,0x07,0x03,0x00,0x00,0x20,0xE0,0xF0,0x78,0x7C,0x3C,0x1E,0x0F,0x07,0x07,0xFF,0xFF,0xFF,0x07,0x0F,0x1E,0x1E,0x3C,0x78,0xF8,0xF0,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x3F,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // * ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFC,0xFE,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xFF,0xFF,0xFF,0xF0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0x00,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0xFF,0xFF,0xFF,0x03,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x0F,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // + ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xFF,0xFF,0xFF,0xFF,0xFF,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0xFF,0xFF,0xFF,0x3F,0x07,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // , ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0x00,0x00,0x00,0x01,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // - ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // . ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xC0,0xC0,0xC0,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xF8,0xFE,0xFF,0x3F,0x0F,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xF0,0xFC,0xFF,0x7F,0x1F,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xF0,0xFE,0xFF,0x3F,0x0F,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xE0,0xF8,0xFF,0xFF,0x1F,0x07,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x03,0x03,0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // / ++0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xE0,0xE0,0xF0,0xF0,0xF8,0xF8,0xF0,0xF0,0xF0,0xE0,0xC0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xFC,0xFF,0xFF,0x7F,0x07,0x01,0x00,0x00,0x00,0x00,0x81,0xF3,0xFF,0xFF,0xFF,0xFE,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x80,0xE0,0xF8,0xFE,0x1F,0x07,0x01,0x05,0xFF,0xFF,0xFF,0xFE,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xE0,0xF8,0xFE,0x3F,0x0F,0x03,0x00,0x00,0x00,0x00,0xF8,0xFF,0xFF,0xFF,0x1F,0x00,0x00,0x00,0x00,0x00,0x01,0x0F,0x7F,0xFF,0xFF,0xF3,0xE0,0xC0,0xC0,0x80,0xC0,0xC0,0xF0,0xFC,0xFF,0x7F,0x3F,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x03,0x07,0x07,0x07,0x07,0x07,0x03,0x03,0x01,0x00,0x00,0x00,0x00,0x00,0x00, // 0 ++0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0xC0,0xC0,0xE0,0xF0,0xF0,0xF0,0xF0,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x1F,0x1F,0x0F,0x07,0x07,0x03,0x03,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xE0,0xFF,0xFF,0xFF,0xFF,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x00,0x00, // 1 ++0x00,0x00,0x00,0xC0,0xE0,0xE0,0xF0,0xF0,0xF0,0xF8,0xF8,0xF8,0xF8,0xF8,0xF0,0xF0,0xF0,0xE0,0xE0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x03,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x07,0xFF,0xFF,0xFF,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xC0,0xF0,0xFC,0xFF,0x7F,0x1F,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xC0,0xE0,0xF8,0xFC,0x7E,0x3F,0x0F,0x07,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xF0,0xF8,0xFC,0xFF,0xFF,0xCF,0xC7,0xC1,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0x00,0x00,0x00,0x00,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x01,0x00, // 2 ++0x00,0x00,0x00,0x00,0xE0,0xF0,0xF0,0xF0,0xF0,0xF8,0xF8,0xF8,0xF8,0xF8,0xF0,0xF0,0xE0,0xE0,0xC0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x07,0xFF,0xFF,0xFF,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0xF0,0xF0,0xF0,0xF8,0xF8,0xF8,0xFC,0xFE,0x9F,0x8F,0x07,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x07,0x1F,0xFF,0xFF,0xFC,0xF0,0x00,0x00,0x00,0x00,0x00,0xF0,0xE0,0xE0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xE0,0xF0,0xFC,0xFF,0x7F,0x3F,0x07,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x03,0x03,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x03,0x03,0x01,0x00,0x00,0x00,0x00,0x00,0x00, // 3 ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xE0,0xF0,0xF0,0xF0,0xF0,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xE0,0xF8,0xFE,0x1F,0x07,0xF7,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xE0,0xF8,0xFE,0x3F,0x0F,0x03,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0xFC,0xFF,0xFF,0xE7,0xE1,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xFF,0xFF,0xFF,0xFF,0xFF,0xE0,0xE0,0xE0,0xC0,0x00,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0xFF,0xFF,0xFF,0xFF,0xFF,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x03,0x03,0x03,0x03,0x00,0x00,0x00,0x00,0x00, // 4 ++0x00,0x00,0x00,0x00,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x7F,0x3F,0x3F,0x3E,0x1E,0x1E,0x1E,0x3E,0x3E,0x3E,0x7E,0xFC,0xF8,0xF8,0xE0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xFF,0xFF,0xFF,0xFE,0x00,0x00,0x00,0x00,0x00,0xF0,0xE0,0xE0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xE0,0xF0,0xFC,0xFF,0x7F,0x1F,0x07,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x03,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x03,0x03,0x03,0x01,0x00,0x00,0x00,0x00,0x00,0x00, // 5 ++0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xC0,0xE0,0xF0,0xF0,0xF0,0xF8,0xF8,0xF8,0xF8,0xF0,0xF0,0xF0,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xF8,0xFE,0xFF,0x3F,0x07,0x03,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xE7,0xF0,0xF8,0x3C,0x3E,0x1E,0x1E,0x1E,0x1E,0x3E,0x7C,0xFC,0xF8,0xF0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xFF,0xFF,0xFF,0xFE,0x00,0x00,0x00,0x00,0x00,0x01,0x1F,0x7F,0xFF,0xFE,0xF0,0xE0,0xC0,0x80,0x80,0x80,0xC0,0xC0,0xF0,0xFC,0xFF,0x7F,0x3F,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x03,0x07,0x07,0x07,0x07,0x07,0x07,0x03,0x03,0x01,0x00,0x00,0x00,0x00,0x00, // 6 ++0x00,0x00,0x00,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0xC1,0xFD,0xFF,0xFF,0x3F,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xF0,0xFE,0xFF,0xFF,0x1F,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xFC,0xFF,0xFF,0x7F,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xF0,0xFE,0xFF,0xFF,0x1F,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x03,0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 7 ++0x00,0x00,0x00,0x00,0x00,0x80,0xE0,0xE0,0xF0,0xF0,0xF8,0xF8,0xF8,0xF8,0xF0,0xF0,0xF0,0xE0,0xC0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0xFF,0xFF,0xFF,0xFF,0x03,0x01,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0xFF,0xFF,0xFF,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x0F,0x9F,0x9F,0xFC,0xF8,0xF0,0xF0,0xF0,0xF0,0xF0,0xF8,0xFE,0x9F,0x8F,0x07,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0xFE,0xFF,0xFF,0x0F,0x03,0x01,0x01,0x00,0x00,0x01,0x01,0x01,0x03,0x1F,0xFF,0xFF,0xFC,0xF0,0x00,0x00,0x00,0x00,0x00,0x1F,0x7F,0xFF,0xFF,0xF8,0xE0,0xC0,0xC0,0x80,0x80,0x80,0xC0,0xC0,0xE0,0xFC,0xFF,0xFF,0x3F,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x03,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x03,0x03,0x01,0x00,0x00,0x00,0x00,0x00, // 8 ++0x00,0x00,0x00,0x00,0x00,0xC0,0xE0,0xF0,0xF0,0xF0,0xF8,0xF8,0xF8,0xF8,0xF0,0xF0,0xE0,0xC0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFC,0xFF,0xFF,0xFF,0x07,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x07,0xFF,0xFF,0xFE,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0xFF,0xFF,0xFF,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xE0,0xFF,0xFF,0xFF,0xFF,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x07,0x0F,0x0F,0x1F,0x1E,0x1E,0x1E,0x1E,0x1E,0x1F,0x0F,0x07,0xC3,0xFF,0xFF,0xFF,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xE0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xE0,0xF0,0xFC,0xFF,0x3F,0x1F,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x03,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x03,0x03,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 9 ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // : ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x7F,0x7F,0x7F,0x3F,0x0F,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ; ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xC0,0xC0,0xE0,0xE0,0xF0,0xF0,0xF8,0xF8,0x7C,0x00,0x00,0x00,0xE0,0xF0,0xF0,0xF8,0xF8,0x3C,0x3C,0x3E,0x1E,0x1F,0x0F,0x0F,0x07,0x07,0x03,0x03,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x03,0x07,0x07,0x0F,0x0F,0x1F,0x1E,0x3E,0x3C,0x7C,0x78,0xF8,0xF0,0xF0,0xE0,0xE0,0xC0,0xC0,0xC0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x03,0x03,0x07,0x07,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // < ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x00,0x00,0x00,0x78,0x78,0x78,0x78,0x78,0x78,0x78,0x78,0x78,0x78,0x78,0x78,0x78,0x78,0x78,0x78,0x78,0x78,0x78,0x78,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // = ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0xF8,0xF8,0xF0,0xE0,0xE0,0xC0,0xC0,0x80,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x03,0x03,0x07,0x07,0x0F,0x0F,0x1F,0x1E,0x3E,0x3C,0x7C,0xF8,0xF8,0xF0,0xF0,0xE0,0x00,0x00,0x00,0x80,0xC0,0xC0,0xE0,0xE0,0xF0,0xF0,0xF8,0xF8,0x78,0x7C,0x3C,0x3E,0x1E,0x1F,0x0F,0x0F,0x07,0x07,0x03,0x01,0x00,0x00,0x00,0x0F,0x07,0x07,0x03,0x03,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // > ++0x00,0x00,0x00,0x00,0x00,0xC0,0xE0,0xE0,0xF0,0xF0,0xF0,0xF8,0xF8,0xF8,0xF8,0xF0,0xF0,0xE0,0xC0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x03,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x87,0xFF,0xFF,0xFF,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xE0,0xF8,0xFC,0x7E,0x3F,0x1F,0x07,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0xF0,0xF0,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x03,0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ? ++0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xC0,0xE0,0xE0,0xE0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xE0,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00,0x80,0xE0,0xF8,0xFE,0x3F,0x0F,0x07,0x03,0x01,0x00,0x00,0x80,0x80,0x80,0x80,0x81,0x81,0x07,0x1F,0xFF,0xFC,0xF0,0x00,0xF0,0xFF,0xFF,0x7F,0x01,0x00,0x00,0x00,0xF0,0xFC,0xFE,0x3F,0x0F,0x07,0x07,0x07,0x07,0x07,0x1F,0x7E,0xFF,0xFF,0xFF,0x00,0xFF,0xFF,0xFF,0xF0,0x00,0x00,0x00,0x00,0x7F,0xFF,0xFF,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xE0,0xFF,0xFF,0xFF,0x00,0x00,0x0F,0x7F,0xFF,0xF8,0xE0,0x80,0x00,0x00,0x01,0x07,0x0F,0x0F,0x1F,0x1E,0x1E,0x1E,0x0F,0x0F,0x03,0x0F,0x0F,0x0F,0x00,0x00,0x00,0x00,0x00,0x03,0x07,0x0F,0x1F,0x3E,0x3C,0x78,0x78,0x78,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0x00,0x00, // @ ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0xF0,0xF0,0xF0,0xF0,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0xFF,0xFF,0x7F,0x03,0x0F,0xFF,0xFF,0xFE,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0xFF,0xFF,0xFF,0x0F,0x00,0x00,0x00,0x03,0x3F,0xFF,0xFF,0xFC,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xFF,0xFF,0xFF,0xFF,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF3,0xFF,0xFF,0xFF,0xFC,0x80,0x00,0x00,0x00,0x00,0xE0,0xFE,0xFF,0xFF,0x3F,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xFF,0xFF,0xFF,0xFC,0x80,0x00,0x02,0x03,0x03,0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x03,0x03,0x03,0x00, // A ++0x00,0x00,0x00,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xE0,0xE0,0xC0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x03,0x07,0xFF,0xFF,0xFF,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x78,0x78,0x78,0x78,0x78,0x78,0x7C,0xFC,0xFE,0xFF,0xEF,0xCF,0x87,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0F,0xFF,0xFF,0xFF,0xF8,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xE0,0xE0,0xF0,0xFC,0xFF,0x7F,0x3F,0x0F,0x00,0x00,0x00,0x00,0x00,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00, // B ++0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xC0,0xE0,0xF0,0xF0,0xF0,0xF8,0xF8,0xF8,0xF8,0xF0,0xF0,0xF0,0xE0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xFC,0xFF,0xFF,0x3F,0x07,0x03,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x03,0x03,0x00,0x00,0x00,0x00,0x00,0xFC,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0F,0x3F,0x7F,0xFF,0xF8,0xF0,0xE0,0xC0,0xC0,0x80,0x80,0xC0,0xC0,0xC0,0xE0,0xF0,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x03,0x07,0x07,0x07,0x07,0x07,0x07,0x03,0x03,0x03,0x01,0x00,0x00,0x00, // C ++0x00,0x00,0xE0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xE0,0xE0,0xE0,0xC0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x01,0x01,0x01,0x03,0x07,0x0F,0x7F,0xFF,0xFE,0xF8,0xC0,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xF0,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xFF,0xFF,0xFF,0xFF,0x03,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xC0,0xC0,0xC0,0xC0,0xE0,0xE0,0xF0,0xF0,0xFC,0xFF,0x7F,0x1F,0x07,0x01,0x00,0x00,0x00,0x00,0x00,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // D ++0x00,0x00,0x00,0xE0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0x7C,0x7C,0x7C,0x7C,0x7C,0x7C,0x7C,0x7C,0x7C,0x7C,0x7C,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x00,0x00,0x00, // E ++0x00,0x00,0x00,0x00,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x7C,0x7C,0x7C,0x7C,0x7C,0x7C,0x7C,0x7C,0x7C,0x7C,0x7C,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x03,0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // F ++0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xC0,0xE0,0xF0,0xF0,0xF0,0xF8,0xF8,0xF8,0xF8,0xF0,0xF0,0xE0,0xE0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0xFC,0xFF,0xFF,0x1F,0x07,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x07,0x07,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x00,0x7F,0xFF,0xFF,0xFF,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x07,0x07,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x07,0x1F,0x7F,0xFF,0xFC,0xF0,0xE0,0xC0,0xC0,0xC0,0x80,0x80,0xC0,0xC0,0xFF,0xFF,0xFF,0xFF,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x03,0x03,0x07,0x07,0x07,0x07,0x07,0x07,0x03,0x03,0x01,0x00,0x00,0x00,0x00, // G ++0x00,0x00,0xE0,0xF0,0xF0,0xF0,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0xF0,0xF0,0xF0,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0x7C,0x7C,0x7C,0x7C,0x7C,0x7C,0x7C,0x7C,0x7C,0x7C,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x03,0x03,0x03,0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x03,0x03,0x03,0x00,0x00,0x00, // H ++0x00,0x00,0x00,0xE0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0xFF,0xFF,0xFF,0xFF,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xE0,0xFF,0xFF,0xFF,0xFF,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x00,0x00,0x00,0x00, // I ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0xF0,0xE0,0xE0,0xC0,0xC0,0x80,0x80,0x80,0xC0,0xC0,0xF0,0xFF,0xFF,0xFF,0x3F,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x03,0x03,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x03,0x03,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // J ++0x00,0x00,0xE0,0xF0,0xF0,0xF0,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xC0,0xF0,0xF0,0xF0,0x70,0x30,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x80,0xC0,0xE0,0xF8,0xFC,0x7F,0x3F,0x0F,0x07,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xF7,0xF0,0xFC,0xFE,0xFF,0xFF,0xE7,0xC3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0x03,0x00,0x00,0x01,0x07,0x1F,0x7F,0xFF,0xFC,0xF0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x07,0x1F,0x7F,0xFF,0xFC,0xF0,0xC0,0x00,0x00,0x00,0x00,0x03,0x03,0x03,0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x03,0x03,0x03,0x02, // K ++0x00,0x00,0x00,0x00,0xF0,0xF0,0xF0,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x00,0x00, // L ++0xE0,0xF0,0xF0,0xF0,0xF0,0xF0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xF0,0xF0,0xF0,0xF0,0xF0,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x07,0x3F,0xFF,0xFC,0xC0,0x00,0x00,0x00,0x00,0xE0,0xFC,0xFF,0x1F,0x07,0xFF,0xFF,0xFF,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x03,0x3F,0xFF,0xFC,0xC0,0xC0,0xFE,0xFF,0x1F,0x03,0x00,0x00,0xFF,0xFF,0xFF,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x01,0x0F,0x1F,0x1F,0x0F,0x01,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x01,0x03,0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x03,0x03,0x00,0x00,0x00, // M ++0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0xF0,0xF0,0xF0,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x1F,0x3F,0xFF,0xFE,0xF0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x01,0x0F,0x3F,0xFF,0xFE,0xF0,0xC0,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x01,0x0F,0x7F,0xFF,0xFE,0xF0,0x80,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0F,0x7F,0xFF,0xFC,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x03,0x03,0x03,0x03,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x03,0x03,0x03,0x03,0x00,0x00,0x00, // N ++0x00,0x00,0x00,0x00,0x00,0x80,0xE0,0xE0,0xF0,0xF0,0xF8,0xF8,0xF8,0xF8,0xF0,0xF0,0xE0,0xC0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xF8,0xFF,0xFF,0xFF,0x0F,0x03,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x1F,0xFF,0xFF,0xFE,0xF0,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFE,0x00,0x00,0x00,0x00,0x7F,0xFF,0xFF,0xFF,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x1F,0x00,0x00,0x00,0x00,0x00,0x0F,0x3F,0xFF,0xFF,0xF8,0xE0,0xC0,0xC0,0x80,0x80,0xC0,0xC0,0xF0,0xFE,0xFF,0x7F,0x3F,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x03,0x07,0x07,0x07,0x07,0x07,0x07,0x03,0x03,0x01,0x00,0x00,0x00,0x00,0x00,0x00, // O ++0x00,0x00,0x00,0x00,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xE0,0xE0,0xC0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x03,0x0F,0xFF,0xFF,0xFF,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x80,0x80,0x80,0x80,0x80,0xC0,0xC0,0xC0,0xE0,0xF8,0xFF,0xFF,0x7F,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x03,0x03,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x03,0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // P ++0x00,0x00,0x00,0x00,0x00,0xC0,0xE0,0xF0,0xF0,0xF8,0xF8,0xF8,0xF8,0xF8,0xF0,0xF0,0xE0,0xE0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xFC,0xFF,0xFF,0xFF,0x07,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x1F,0xFF,0xFF,0xFF,0xF8,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x3F,0xFF,0xFF,0xFF,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x1F,0x00,0x00,0x00,0x00,0x00,0x07,0x1F,0x7F,0xFF,0xFC,0xF0,0xE0,0xE0,0xC0,0xC0,0xE0,0xE0,0xF8,0xFE,0xFF,0x3F,0x1F,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x03,0x03,0x03,0x03,0x07,0x0F,0x3F,0x7F,0xFC,0x78,0x30,0x00,0x00,0x00,0x00, // Q ++0x00,0x00,0x00,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xE0,0xE0,0xE0,0xC0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x03,0x07,0xFF,0xFF,0xFF,0xFE,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xE0,0xE0,0xF0,0xFF,0x7F,0x3F,0x1F,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x03,0x03,0x03,0x03,0x03,0x07,0x07,0x1F,0x7F,0xFE,0xFC,0xF0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x0F,0x7F,0xFF,0xFE,0xF8,0xC0,0x00,0x00,0x00,0x00,0x03,0x03,0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x03,0x03,0x03,0x02, // R ++0x00,0x00,0x00,0x00,0x80,0xC0,0xE0,0xF0,0xF0,0xF0,0xF8,0xF8,0xF8,0xF8,0xF0,0xF0,0xF0,0xF0,0xE0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xFE,0xFF,0xFF,0x9F,0x03,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x3F,0x7F,0x7F,0xFC,0xF8,0xF8,0xF0,0xF0,0xF0,0xE0,0xE0,0xE0,0xC0,0xC0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x03,0x03,0x03,0x07,0x0F,0xFF,0xFF,0xFE,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0xF0,0xE0,0xE0,0xC0,0xC0,0xC0,0x80,0x80,0xC0,0xC0,0xC0,0xE0,0xF0,0xFF,0xFF,0x7F,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x03,0x03,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x03,0x03,0x01,0x00,0x00,0x00,0x00,0x00,0x00, // S ++0x00,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0xFF,0xFF,0xFF,0xFF,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x03,0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // T ++0x00,0x00,0x00,0xF0,0xF0,0xF0,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0xF0,0xF0,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x7F,0xFF,0xFF,0xF0,0xE0,0xC0,0xC0,0x80,0x80,0xC0,0xC0,0xE0,0xF0,0xFF,0xFF,0x7F,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x03,0x07,0x07,0x07,0x07,0x07,0x07,0x03,0x03,0x01,0x00,0x00,0x00,0x00,0x00,0x00, // U ++0x00,0x30,0xF0,0xF0,0xF0,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xF0,0xF0,0xF0,0x70,0x00,0x00,0x00,0x03,0x7F,0xFF,0xFF,0xFC,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xF8,0xFF,0xFF,0xFF,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xFF,0xFF,0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0xFF,0xFF,0xFF,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0xFF,0xFF,0xFF,0xE0,0x00,0x00,0xC0,0xFE,0xFF,0xFF,0x1F,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x1F,0xFF,0xFF,0xF8,0xF0,0xFF,0xFF,0x3F,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x03,0x03,0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // V ++0xF0,0xF0,0xF0,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0xF0,0xF0,0xF0,0x01,0xFF,0xFF,0xFF,0xFE,0x00,0x00,0x00,0x00,0x00,0xC0,0xC0,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00,0xFC,0xFF,0xFF,0xFF,0x03,0x00,0x03,0xFF,0xFF,0xFF,0xE0,0x00,0x00,0x80,0xFE,0xFF,0x7F,0x3F,0xFF,0xFF,0xC0,0x00,0x00,0xE0,0xFF,0xFF,0xFF,0x07,0x00,0x00,0x00,0x03,0xFF,0xFF,0xFF,0x00,0xC0,0xFF,0xFF,0x1F,0x00,0x00,0x1F,0xFF,0xFF,0xE0,0x00,0xFF,0xFF,0xFF,0x0F,0x00,0x00,0x00,0x00,0x00,0x07,0xFF,0xFF,0xFF,0xFF,0xFF,0x07,0x00,0x00,0x00,0x00,0x03,0xFF,0xFF,0xFE,0xFF,0xFF,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x03,0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x03,0x03,0x03,0x00,0x00,0x00,0x00, // W ++0x00,0x00,0x30,0xF0,0xF0,0xF0,0xE0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xE0,0xF0,0xF0,0xF0,0x30,0x00,0x00,0x00,0x00,0x00,0x03,0x0F,0x3F,0xFF,0xFC,0xF0,0xC0,0x00,0x00,0x00,0xC0,0xF8,0xFE,0xFF,0x3F,0x0F,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x07,0x9F,0xFF,0xFF,0xFC,0xFF,0xFF,0x0F,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xE0,0xF8,0xFE,0xFF,0x3F,0x0F,0x03,0x1F,0x7F,0xFF,0xFC,0xF0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xF0,0xFC,0xFF,0x3F,0x0F,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x07,0x3F,0xFF,0xFE,0xF8,0xE0,0x80,0x00,0x00,0x03,0x03,0x03,0x03,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x03,0x03,0x03,0x02, // X ++0x00,0x30,0xF0,0xF0,0xF0,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xF0,0xF0,0xF0,0x30,0x00,0x00,0x00,0x01,0x07,0x1F,0x7F,0xFF,0xFC,0xF0,0x80,0x00,0x00,0x00,0x00,0x80,0xF0,0xFC,0xFF,0x7F,0x1F,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x0F,0x3F,0xFF,0xFE,0xF0,0xF0,0xFE,0xFF,0x3F,0x0F,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x03,0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // Y ++0x00,0x00,0x00,0xE0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xE0,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x81,0xE1,0xF9,0xFF,0xFF,0x3F,0x0F,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xE0,0xF8,0xFE,0xFF,0x3F,0x0F,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xE0,0xF8,0xFE,0x7F,0x3F,0x0F,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xF8,0xFE,0xFF,0xFF,0xC7,0xC1,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0x00,0x00,0x00,0x00,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x00, // Z ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x0F,0x0F,0x0F,0x0F,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x01,0x00,0x00,0x00,0x00, // [ ++0x00,0x00,0xC0,0xC0,0xC0,0xC0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x0F,0x3F,0xFF,0xFE,0xF0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x07,0x1F,0xFF,0xFF,0xF8,0xE0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x0F,0x7F,0xFF,0xFC,0xF0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x07,0x3F,0xFF,0xFE,0xF8,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x03,0x03,0x03,0x00,0x00,0x00, // ++0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x0F,0x0F,0x0F,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x80,0x80,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ] ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xE0,0xF0,0xF0,0xF0,0xF0,0xE0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xE0,0xF8,0xFC,0xFF,0x3F,0x1F,0x07,0x03,0x03,0x07,0x1F,0x3F,0x7F,0xFC,0xF8,0xE0,0xC0,0x00,0x00,0x00,0x00,0x04,0x07,0x07,0x07,0x03,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x07,0x07,0x07,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ^ ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03, // _ ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xE0,0xF8,0xF8,0xF8,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFC,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x03,0x03,0x03,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ` ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xC0,0xC0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xC0,0xC0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x03,0x03,0x01,0x01,0x01,0x01,0x01,0x01,0x03,0x07,0x3F,0xFF,0xFF,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xF0,0xF8,0xFC,0x7E,0x1E,0x1F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x8F,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x7F,0xFF,0xFF,0xF0,0xC0,0xC0,0x80,0x80,0x80,0xC0,0xC0,0xE0,0xF8,0x7F,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x03,0x07,0x07,0x07,0x07,0x07,0x03,0x03,0x01,0x00,0x00,0x03,0x03,0x03,0x00,0x00,0x00,0x00, // a ++0x00,0x00,0x00,0xF8,0xF8,0xF8,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x80,0xC0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xC0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x7F,0x0F,0x03,0x03,0x01,0x01,0x01,0x03,0x07,0x0F,0xFF,0xFF,0xFE,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0xFF,0xFF,0xFF,0x7E,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFE,0xF0,0xC0,0xC0,0x80,0x80,0x80,0xC0,0xE0,0xF8,0xFF,0xFF,0x3F,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x03,0x03,0x03,0x00,0x01,0x03,0x03,0x07,0x07,0x07,0x07,0x03,0x03,0x01,0x00,0x00,0x00,0x00,0x00,0x00, // b ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0xC0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xC0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0xFC,0xFE,0xFF,0x1F,0x07,0x03,0x03,0x01,0x01,0x01,0x01,0x01,0x03,0x07,0x07,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0xFF,0xFF,0xFF,0x81,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x3F,0x7F,0xFF,0xF8,0xE0,0xC0,0xC0,0x80,0x80,0x80,0x80,0xC0,0xC0,0xE0,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x03,0x07,0x07,0x07,0x07,0x07,0x07,0x03,0x03,0x01,0x00,0x00,0x00,0x00, // c ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0xF8,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xC0,0xC0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xC0,0x80,0x00,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xF8,0xFE,0xFF,0x7F,0x0F,0x03,0x01,0x01,0x01,0x01,0x03,0x07,0x0F,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x7F,0xFF,0xFF,0xF0,0xE0,0xC0,0x80,0x80,0x80,0xC0,0xE0,0xF8,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x07,0x07,0x07,0x07,0x07,0x03,0x03,0x00,0x00,0x03,0x03,0x03,0x00,0x00,0x00,0x00, // d ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xC0,0xC0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xC0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0xFC,0xFF,0xFF,0x1F,0x07,0x03,0x01,0x01,0x01,0x01,0x01,0x03,0x07,0x1F,0xFF,0xFE,0xF8,0xC0,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x8F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x00,0x00,0x00,0x00,0x00,0x0F,0x3F,0x7F,0xFF,0xF8,0xE0,0xC0,0xC0,0x80,0x80,0x80,0x80,0xC0,0xC0,0xC0,0xE0,0xE0,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x03,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x03,0x03,0x01,0x01,0x00,0x00,0x00, // e ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xF0,0xF8,0xF8,0x78,0x78,0x78,0x78,0x78,0x78,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xFE,0xFF,0xFF,0xFF,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0xFF,0xFF,0xFF,0xFF,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x03,0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // f ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xC0,0xC0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xC0,0x80,0x00,0xC0,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xFC,0xFE,0xFF,0x3F,0x07,0x03,0x01,0x01,0x01,0x01,0x01,0x03,0x07,0x7F,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0xFF,0xFF,0xFF,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x07,0x0F,0x1F,0x3E,0x3C,0x78,0x78,0x78,0x78,0x38,0x3C,0x1F,0x0F,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x78,0x78,0xF0,0xF0,0xF0,0xE0,0xE0,0xF0,0xF0,0xF0,0x78,0x7F,0x3F,0x1F,0x07,0x00,0x00,0x00,0x00, // g ++0x00,0x00,0x00,0xF8,0xF8,0xF8,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0xC0,0xC0,0xE0,0xE0,0xE0,0xE0,0xE0,0xC0,0xC0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x7E,0x0F,0x03,0x03,0x01,0x01,0x01,0x03,0x07,0x3F,0xFF,0xFF,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x03,0x03,0x00,0x00,0x00,0x00, // h ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0xF8,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC1,0xC1,0xC1,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x03,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xFF,0xFF,0xFF,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0x80,0x00,0x00,0x00,0x00,0x00,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x01,0x00, // i ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0xF0,0xF0,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC1,0xC1,0xC1,0xC1,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF8,0x7F,0x7F,0x1F,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // j ++0x00,0x00,0x00,0x00,0xF8,0xF8,0xF8,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xC0,0xC0,0xC0,0xC0,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0xC0,0xE0,0xF0,0xF8,0x7E,0x3F,0x1F,0x07,0x03,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x3E,0x1F,0x0F,0x1F,0x7F,0xFF,0xFC,0xF0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x0F,0x3F,0xFF,0xFE,0xF8,0xE0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x03,0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x03,0x03,0x03,0x03,0x00, // k ++0x00,0x00,0x00,0x00,0x38,0x3C,0x3C,0x3C,0x3C,0x3C,0xFC,0xFC,0xFC,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x3F,0xFF,0xFF,0xF0,0xE0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x00,0x00, // l ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xC0,0xC0,0x80,0xC0,0xE0,0xE0,0xE0,0xE0,0xC0,0x80,0x00,0xC0,0xE0,0xE0,0xE0,0xE0,0xC0,0x80,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0x0F,0x03,0x01,0x01,0x03,0xFF,0xFF,0xFF,0xFF,0x03,0x01,0x01,0x01,0x1F,0xFF,0xFF,0xFE,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x03,0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x03,0x03,0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x03,0x03,0x03,0x00,0x00, // m ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xC0,0xC0,0xC0,0x00,0x00,0xC0,0xC0,0xE0,0xE0,0xE0,0xE0,0xE0,0xC0,0xC0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x7E,0x0F,0x03,0x03,0x01,0x01,0x01,0x03,0x07,0x3F,0xFF,0xFF,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x03,0x03,0x00,0x00,0x00,0x00, // n ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xC0,0xC0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xC0,0xC0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0xFE,0xFF,0xFF,0x0F,0x07,0x03,0x01,0x01,0x01,0x01,0x03,0x07,0x1F,0xFF,0xFF,0xFC,0xE0,0x00,0x00,0x00,0x00,0x00,0x7E,0xFF,0xFF,0xFF,0xC1,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x3F,0xFF,0xFF,0xF8,0xE0,0xC0,0x80,0x80,0x80,0xC0,0xC0,0xE0,0xF8,0xFF,0xFF,0x3F,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x03,0x07,0x07,0x07,0x07,0x07,0x07,0x03,0x03,0x01,0x00,0x00,0x00,0x00,0x00,0x00, // o ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xC0,0xC0,0xC0,0x80,0x80,0xC0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xC0,0xC0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x7F,0x07,0x03,0x01,0x01,0x01,0x01,0x01,0x03,0x07,0xFF,0xFF,0xFE,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0xFF,0xFF,0xFF,0x1F,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x1F,0x1E,0x3C,0x78,0x78,0x70,0x78,0x78,0x7C,0x3E,0x3F,0x1F,0x07,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // p ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xC0,0xC0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xC0,0x80,0x00,0xC0,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0xFE,0xFF,0xFF,0x07,0x03,0x01,0x01,0x01,0x01,0x01,0x03,0x07,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0xFF,0xFF,0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x07,0x1F,0x3F,0x3E,0x7C,0x78,0x78,0x70,0x78,0x78,0x3C,0x1E,0x0F,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00, // q ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xC0,0xC0,0xC0,0x00,0x80,0xC0,0xC0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xC0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFE,0x3E,0x0F,0x07,0x03,0x03,0x01,0x01,0x01,0x03,0x03,0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x03,0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // r ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xC0,0xC0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFC,0xFF,0xFF,0xFF,0x87,0x03,0x01,0x01,0x01,0x01,0x01,0x01,0x03,0x03,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x07,0x0F,0x0F,0x1F,0x1F,0x1E,0x3E,0x3E,0x3C,0x7C,0xFC,0xF8,0xF8,0xF0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0xE0,0xE0,0xC0,0xC0,0x80,0x80,0x80,0x80,0xC0,0xC0,0xE0,0xFF,0xFF,0xFF,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x03,0x03,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x03,0x03,0x01,0x00,0x00,0x00,0x00,0x00,0x00, // s ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xC0,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xFF,0xFF,0xFF,0xFF,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0xFF,0xFF,0xFF,0xFF,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x7F,0xFF,0xFF,0xF0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x00,0x00,0x00,0x00, // t ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xC0,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xC0,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0xFF,0xFF,0xFE,0xE0,0xC0,0xC0,0x80,0x80,0xC0,0xE0,0xF0,0x7E,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x07,0x07,0x07,0x07,0x07,0x03,0x03,0x00,0x00,0x03,0x03,0x03,0x03,0x00,0x00,0x00, // u ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xC0,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xC0,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00,0x0F,0xFF,0xFF,0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0xFF,0xFF,0x7F,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x7F,0xFF,0xFF,0xF0,0x00,0x00,0x00,0x80,0xF0,0xFF,0xFF,0x7F,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x3F,0xFF,0xFF,0xF0,0xF0,0xFF,0xFF,0x3F,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x03,0x03,0x03,0x03,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // v ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xC0,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xC0,0xC0,0xC0,0x01,0x7F,0xFF,0xFF,0xFC,0x00,0x00,0x00,0x00,0x00,0xC0,0xC0,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00,0xF8,0xFF,0xFF,0x7F,0x01,0x00,0x00,0x0F,0xFF,0xFF,0xFE,0xC0,0x00,0x80,0xFC,0xFF,0x1F,0x0F,0xFF,0xFC,0xC0,0x00,0x80,0xFE,0xFF,0xFF,0x1F,0x00,0x00,0x00,0x00,0x00,0x03,0x7F,0xFF,0xFF,0xF8,0xFF,0x7F,0x03,0x00,0x00,0x03,0x3F,0xFF,0xF8,0xFF,0xFF,0xFF,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x03,0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x03,0x03,0x03,0x00,0x00,0x00,0x00,0x00, // w ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xC0,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xC0,0xC0,0xC0,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x07,0x1F,0x7F,0xFC,0xF8,0xE0,0x80,0x80,0xE0,0xF8,0xFC,0x7F,0x1F,0x0F,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC1,0xF3,0xFF,0xFF,0x7F,0xFF,0xF7,0xC1,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xE0,0xF8,0xFE,0x7F,0x1F,0x07,0x03,0x00,0x00,0x01,0x07,0x1F,0x7F,0xFE,0xF8,0xE0,0xC0,0x00,0x00,0x00,0x00,0x00,0x03,0x03,0x03,0x03,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x03,0x03,0x03,0x00,0x00, // x ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0xC0,0xC0,0xC0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xC0,0xC0,0xC0,0x40,0x00,0x00,0x00,0x00,0x03,0x1F,0xFF,0xFF,0xFC,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xF0,0xFE,0xFF,0x7F,0x0F,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x3F,0xFF,0xFF,0xF8,0xC0,0x00,0xE0,0xFC,0xFF,0xFF,0x1F,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x07,0xFF,0xFF,0xFF,0xFF,0x3F,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0xF0,0xF0,0xF0,0xF0,0xF8,0x7E,0x7F,0x1F,0x07,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // y ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0xC1,0xF1,0xF9,0xFF,0x7F,0x1F,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xE0,0xF8,0xFE,0x7F,0x1F,0x0F,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xF8,0xFC,0xFF,0xDF,0xCF,0xC3,0xC1,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x00,0x00,0x00,0x00, // z ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0xFC,0xFE,0xFE,0x0F,0x0F,0x0F,0x0F,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x70,0x70,0x70,0xF0,0xF8,0xF8,0xDF,0x9F,0x8F,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0F,0xFF,0xFF,0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0xFF,0xFF,0xFF,0xC0,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x03,0x03,0x03,0x03,0x03,0x03,0x00,0x00,0x00,0x00, // { ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x03,0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // | ++0x00,0x00,0x00,0x00,0x07,0x0F,0x0F,0x0F,0x0F,0x1E,0xFE,0xFE,0xFC,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x0F,0x9F,0xDF,0xDC,0xF8,0xF0,0xF0,0x70,0x70,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0xFF,0xFF,0xFF,0x03,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x80,0x80,0xC0,0xE0,0xFF,0xFF,0xFF,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x03,0x03,0x03,0x03,0x03,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // } ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xC0,0xC0,0xC0,0xC0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0xF8,0xFE,0xFF,0x1F,0x07,0x07,0x07,0x07,0x1F,0x3F,0xFE,0xF8,0xF0,0xC0,0x80,0x00,0x00,0x00,0xC0,0xF0,0xFC,0xF8,0x10,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x07,0x0F,0x0F,0x1F,0x1F,0x1F,0x0F,0x07,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ~ ++0x00,0x00,0x00,0x00,0xC0,0xC0,0xE0,0xF8,0xF8,0x38,0x38,0x38,0x38,0xF8,0xF8,0xE0,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0xFF,0xFF,0xC1,0x80,0x80,0x00,0x00,0x00,0x00,0x80,0x80,0xC1,0xFF,0xFF,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x03,0x0F,0x0F,0x0E,0x0E,0x0E,0x0E,0x0F,0x0F,0x03,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ° ++}; +diff -ruN main/drivers/auxdisplay/openvfd/controllers/fonts/Grotesk32x64_h.h mod/drivers/auxdisplay/openvfd/controllers/fonts/Grotesk32x64_h.h +--- main/drivers/auxdisplay/openvfd/controllers/fonts/Grotesk32x64_h.h 1970-01-01 01:00:00.000000000 +0100 ++++ mod/drivers/auxdisplay/openvfd/controllers/fonts/Grotesk32x64_h.h 2023-03-07 09:42:05.821566614 +0100 +@@ -0,0 +1,112 @@ ++// Grotesk32x64_h.h ++// Font type : Full (96 characters) ++// Font size : 32x64 pixels ++// Memory usage : 24580 bytes ++ ++// Origin: http://www.rinkydinkelectronics.com/r_fonts.php ++// Modified by Arthur Liberman for compatibility with the OpenVFD driver. ++ ++const unsigned char Grotesk32x64_H[24580] = { ++0x20,0x40,0x20,0x60, ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xE0,0x00,0x00,0x03,0xF0,0x00,0x00,0x03,0xF0,0x00,0x00,0x03,0xF0,0x00,0x00,0x03,0xF0,0x00,0x00,0x03,0xF0,0x00,0x00,0x03,0xF0,0x00,0x00,0x03,0xF0,0x00,0x00,0x03,0xF0,0x00,0x00,0x03,0xF0,0x00,0x00,0x03,0xF0,0x00,0x00,0x03,0xF0,0x00,0x00,0x03,0xF0,0x00,0x00,0x03,0xF0,0x00,0x00,0x03,0xF0,0x00,0x00,0x03,0xF0,0x00,0x00,0x03,0xF0,0x00,0x00,0x03,0xF0,0x00,0x00,0x03,0xF0,0x00,0x00,0x03,0xF0,0x00,0x00,0x03,0xF0,0x00,0x00,0x03,0xF0,0x00,0x00,0x03,0xF0,0x00,0x00,0x03,0xF0,0x00,0x00,0x03,0xF0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x01,0xE0,0x00,0x00,0x01,0xE0,0x00,0x00,0x01,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xF0,0x00,0x00,0x07,0xF0,0x00,0x00,0x07,0xF0,0x00,0x00,0x07,0xF0,0x00,0x00,0x07,0xF0,0x00,0x00,0x07,0xF0,0x00,0x00,0x07,0xF0,0x00,0x00,0x07,0xF0,0x00,0x00,0x07,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ! ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x01,0xE0,0x00,0x3E,0x03,0xE0,0x00,0x3E,0x03,0xE0,0x00,0x7C,0x07,0xC0,0x00,0x7C,0x07,0xC0,0x00,0x7C,0x07,0xC0,0x00,0xFC,0x0F,0xC0,0x00,0xFC,0x0F,0xC0,0x00,0xF8,0x0F,0x80,0x01,0xF8,0x1F,0x80,0x01,0xF8,0x1F,0x80,0x03,0xF8,0x3F,0x80,0x03,0xF8,0x3F,0x80,0x03,0xF0,0x3F,0x00,0x03,0xF0,0x3F,0x00,0x03,0xF0,0x3F,0x00,0x03,0xF0,0x3F,0x00,0x03,0xF0,0x3F,0x00,0x03,0xF0,0x3F,0x00,0x03,0xF0,0x3F,0x00,0x03,0xF0,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // " ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xC0,0xF0,0x00,0x07,0xC0,0xF0,0x00,0x07,0x80,0xF0,0x00,0x07,0x81,0xF0,0x00,0x07,0x81,0xF0,0x00,0x07,0x81,0xF0,0x00,0x0F,0x81,0xE0,0x00,0x0F,0x81,0xE0,0x00,0x0F,0x01,0xE0,0x00,0x0F,0x03,0xE0,0x00,0x0F,0x03,0xE0,0x00,0x1F,0x03,0xC0,0x0F,0xFF,0xFF,0xFF,0x1F,0xFF,0xFF,0xFF,0x1F,0xFF,0xFF,0xFF,0x1F,0xFF,0xFF,0xFF,0x1F,0xFF,0xFF,0xFF,0x0F,0xFF,0xFF,0xFF,0x00,0x3C,0x07,0x80,0x00,0x3C,0x0F,0x80,0x00,0x3C,0x0F,0x80,0x00,0x7C,0x0F,0x00,0x00,0x7C,0x0F,0x00,0x00,0x78,0x0F,0x00,0x00,0x78,0x1F,0x00,0x00,0x78,0x1F,0x00,0x00,0xF8,0x1E,0x00,0x00,0xF8,0x1E,0x00,0x00,0xF8,0x1E,0x00,0x00,0xF0,0x1E,0x00,0x01,0xF0,0x3E,0x00,0xFF,0xFF,0xFF,0xF8,0xFF,0xFF,0xFF,0xF8,0xFF,0xFF,0xFF,0xF8,0xFF,0xFF,0xFF,0xF8,0xFF,0xFF,0xFF,0xF8,0x01,0xE0,0x7C,0x00,0x03,0xE0,0x78,0x00,0x03,0xE0,0x78,0x00,0x03,0xC0,0xF8,0x00,0x03,0xC0,0xF8,0x00,0x03,0xC0,0xF8,0x00,0x07,0xC0,0xF0,0x00,0x07,0xC0,0xF0,0x00,0x07,0x80,0xF0,0x00,0x07,0x81,0xF0,0x00,0x07,0x81,0xF0,0x00,0x0F,0x81,0xE0,0x00,0x0F,0x81,0xE0,0x00,0x0F,0x01,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // # ++0x00,0x00,0xC0,0x00,0x00,0x01,0xC0,0x00,0x00,0x01,0xC0,0x00,0x00,0x01,0xC0,0x00,0x00,0x01,0xC0,0x00,0x00,0x01,0xC0,0x00,0x00,0x01,0xC0,0x00,0x00,0x01,0xC0,0x00,0x00,0x07,0xF8,0x00,0x00,0x1F,0xFF,0x80,0x00,0x7F,0xFF,0xE0,0x00,0xFF,0xFF,0xE0,0x01,0xFF,0xFF,0xE0,0x01,0xFD,0xC7,0xE0,0x03,0xF1,0xC0,0xE0,0x03,0xE1,0xC0,0x20,0x07,0xC1,0xC0,0x00,0x07,0xC1,0xC0,0x00,0x07,0xC1,0xC0,0x00,0x07,0xC1,0xC0,0x00,0x07,0xC1,0xC0,0x00,0x07,0xC1,0xC0,0x00,0x07,0xC1,0xC0,0x00,0x07,0xE1,0xC0,0x00,0x07,0xE1,0xC0,0x00,0x03,0xF1,0xC0,0x00,0x03,0xFD,0xC0,0x00,0x01,0xFF,0xE0,0x00,0x01,0xFF,0xFC,0x00,0x00,0xFF,0xFF,0x00,0x00,0x3F,0xFF,0x80,0x00,0x1F,0xFF,0xC0,0x00,0x03,0xFF,0xE0,0x00,0x01,0xFF,0xF0,0x00,0x01,0xC7,0xF0,0x00,0x01,0xC3,0xF8,0x00,0x01,0xC1,0xF8,0x00,0x01,0xC0,0xF8,0x00,0x01,0xC0,0xF8,0x00,0x01,0xC0,0xF8,0x00,0x01,0xC0,0xF8,0x00,0x01,0xC0,0xF8,0x00,0x01,0xC0,0xF8,0x00,0x01,0xC0,0xF8,0x04,0x01,0xC0,0xF8,0x06,0x01,0xC1,0xF0,0x07,0x81,0xC3,0xF0,0x07,0xF1,0xCF,0xF0,0x07,0xFF,0xFF,0xE0,0x07,0xFF,0xFF,0xC0,0x03,0xFF,0xFF,0x80,0x00,0xFF,0xFF,0x00,0x00,0x1F,0xF8,0x00,0x00,0x01,0xC0,0x00,0x00,0x01,0xC0,0x00,0x00,0x01,0xC0,0x00,0x00,0x01,0xC0,0x00,0x00,0x01,0xC0,0x00,0x00,0x01,0xC0,0x00,0x00,0x01,0xC0,0x00,0x00,0x01,0xC0,0x00,0x00,0x01,0xC0,0x00,0x00,0x01,0xC0,0x00,0x00,0x00,0x00,0x00, // $ ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xF0,0x00,0x00,0x0F,0xFC,0x00,0x00,0x1F,0xFE,0x00,0x00,0x1F,0xFF,0x00,0x00,0x3F,0x3F,0x00,0x00,0x3C,0x0F,0x80,0x00,0x78,0x07,0x80,0x00,0x78,0x07,0x80,0x00,0x78,0x03,0x80,0x00,0x70,0x03,0xC0,0x00,0x70,0x03,0xC0,0x00,0x70,0x03,0xC0,0x00,0x78,0x03,0xC0,0x00,0x78,0x07,0x80,0x00,0x78,0x07,0x80,0x04,0x3C,0x0F,0x80,0x1E,0x3F,0x3F,0x00,0x7E,0x1F,0xFF,0x01,0xFE,0x1F,0xFE,0x07,0xFE,0x0F,0xFC,0x0F,0xF8,0x03,0xF8,0x3F,0xE0,0x00,0x00,0xFF,0x80,0x00,0x03,0xFE,0x00,0x00,0x0F,0xF8,0x00,0x00,0x3F,0xE0,0x00,0x00,0xFF,0x80,0x00,0x03,0xFE,0x07,0x00,0x0F,0xF8,0x1F,0xE0,0x3F,0xE0,0x3F,0xF0,0x7F,0xC0,0x7F,0xF8,0x7F,0x00,0xFF,0xF8,0x3C,0x00,0xF8,0xFC,0x30,0x01,0xF0,0x3C,0x00,0x01,0xE0,0x1E,0x00,0x01,0xE0,0x1E,0x00,0x03,0xC0,0x1E,0x00,0x03,0xC0,0x0E,0x00,0x03,0xC0,0x0E,0x00,0x03,0xC0,0x0E,0x00,0x01,0xC0,0x1E,0x00,0x01,0xE0,0x1E,0x00,0x01,0xE0,0x3E,0x00,0x01,0xF0,0x7C,0x00,0x00,0xFF,0xFC,0x00,0x00,0xFF,0xF8,0x00,0x00,0x7F,0xF0,0x00,0x00,0x3F,0xE0,0x00,0x00,0x0F,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // % ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xC0,0x00,0x00,0x1F,0xFC,0x00,0x00,0x3F,0xFE,0x00,0x00,0x7F,0xFE,0x00,0x00,0xFF,0xFE,0x00,0x01,0xFF,0xFE,0x00,0x01,0xFC,0x0E,0x00,0x01,0xF8,0x06,0x00,0x03,0xF0,0x00,0x00,0x03,0xF0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xF0,0x00,0x00,0x03,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF8,0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0xFC,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0xFE,0x00,0x00,0x01,0xFE,0x00,0x00,0x03,0xFF,0x00,0x00,0x03,0xFF,0x00,0x00,0x07,0xEF,0x80,0x00,0x0F,0xCF,0xC0,0x1E,0x0F,0x87,0xC0,0x1E,0x1F,0x87,0xE0,0x1E,0x1F,0x03,0xE0,0x1E,0x3F,0x03,0xF0,0x1E,0x3E,0x01,0xF0,0x1E,0x3E,0x01,0xF8,0x1E,0x3E,0x00,0xF8,0x1E,0x7E,0x00,0x7C,0x1E,0x7E,0x00,0x7E,0x1E,0x7E,0x00,0x3E,0x3E,0x7E,0x00,0x3F,0x3C,0x7E,0x00,0x1F,0x3C,0x7E,0x00,0x1F,0xFC,0x3E,0x00,0x0F,0xF8,0x3F,0x00,0x0F,0xF8,0x3F,0x00,0x07,0xF0,0x3F,0x80,0x07,0xF0,0x1F,0x80,0x03,0xF0,0x1F,0xC0,0x07,0xF0,0x0F,0xE0,0x1F,0xF8,0x0F,0xFC,0x7F,0xF8,0x07,0xFF,0xFF,0xFC,0x03,0xFF,0xFE,0x7C,0x01,0xFF,0xFC,0x7E,0x00,0xFF,0xF8,0x3F,0x00,0x1F,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // & ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x78,0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0xF8,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x03,0xF0,0x00,0x00,0x03,0xF0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x0F,0xE0,0x00,0x00,0x0F,0xE0,0x00,0x00,0x0F,0xE0,0x00,0x00,0x0F,0xE0,0x00,0x00,0x0F,0xE0,0x00,0x00,0x0F,0xE0,0x00,0x00,0x0F,0xE0,0x00,0x00,0x0F,0xE0,0x00,0x00,0x0F,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ' ++0x00,0x00,0x3C,0x00,0x00,0x00,0x3C,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x78,0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x0F,0x80,0x00,0x00,0x0F,0x80,0x00,0x00,0x0F,0x80,0x00,0x00,0x0F,0x80,0x00,0x00,0x1F,0x80,0x00,0x00,0x1F,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x1F,0x80,0x00,0x00,0x0F,0x80,0x00,0x00,0x0F,0x80,0x00,0x00,0x0F,0x80,0x00,0x00,0x0F,0x80,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x00,0xF0,0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0x78,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ( ++0x00,0x3C,0x00,0x00,0x00,0x3C,0x00,0x00,0x00,0x3E,0x00,0x00,0x00,0x1E,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x0F,0x00,0x00,0x00,0x0F,0x80,0x00,0x00,0x0F,0x80,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF8,0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0x80,0x00,0x00,0x0F,0x80,0x00,0x00,0x0F,0x80,0x00,0x00,0x1F,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x1E,0x00,0x00,0x00,0x3E,0x00,0x00,0x00,0x3C,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ) ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xC0,0x00,0x00,0x03,0xC0,0x00,0x00,0x03,0xC0,0x00,0x00,0x03,0xC0,0x00,0x00,0x03,0xC0,0x00,0x00,0x03,0xC0,0x00,0x00,0x03,0xC0,0x00,0x00,0x03,0xC0,0x00,0x18,0x03,0xC0,0x0C,0x1C,0x03,0xC0,0x1C,0x3E,0x03,0xC0,0x7C,0x3F,0x83,0xC0,0xFE,0x3F,0xC3,0xC1,0xFE,0x0F,0xE3,0xC3,0xF8,0x07,0xF3,0xCF,0xF0,0x01,0xFB,0xDF,0xC0,0x00,0xFF,0xFF,0x80,0x00,0x7F,0xFE,0x00,0x00,0x1F,0xFC,0x00,0x00,0x07,0xF0,0x00,0x00,0x07,0xF0,0x00,0x00,0x1F,0xFC,0x00,0x00,0x3F,0xFE,0x00,0x00,0xFF,0xFF,0x00,0x01,0xFF,0xFF,0xC0,0x03,0xFB,0xCF,0xE0,0x0F,0xE3,0xC7,0xF8,0x1F,0xC3,0xC1,0xFC,0x3F,0x83,0xC0,0xFE,0x3F,0x03,0xC0,0x7E,0x1C,0x03,0xC0,0x3C,0x18,0x03,0xC0,0x0C,0x00,0x03,0xC0,0x00,0x00,0x03,0xC0,0x00,0x00,0x03,0xC0,0x00,0x00,0x03,0xC0,0x00,0x00,0x03,0xC0,0x00,0x00,0x03,0xC0,0x00,0x00,0x03,0xC0,0x00,0x00,0x01,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // * ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xE0,0x00,0x00,0x01,0xE0,0x00,0x00,0x01,0xE0,0x00,0x00,0x01,0xE0,0x00,0x00,0x01,0xE0,0x00,0x00,0x01,0xE0,0x00,0x00,0x01,0xE0,0x00,0x00,0x01,0xE0,0x00,0x00,0x01,0xE0,0x00,0x00,0x01,0xE0,0x00,0x00,0x01,0xE0,0x00,0x00,0x01,0xE0,0x00,0x00,0x01,0xE0,0x00,0x00,0x01,0xE0,0x00,0x00,0x03,0xE0,0x00,0x1F,0xFF,0xFF,0xFE,0x1F,0xFF,0xFF,0xFE,0x1F,0xFF,0xFF,0xFE,0x1F,0xFF,0xFF,0xFE,0x1F,0xFF,0xFF,0xFE,0x0F,0xFF,0xFF,0xFC,0x00,0x01,0xE0,0x00,0x00,0x01,0xE0,0x00,0x00,0x01,0xE0,0x00,0x00,0x01,0xE0,0x00,0x00,0x01,0xE0,0x00,0x00,0x01,0xE0,0x00,0x00,0x01,0xE0,0x00,0x00,0x01,0xE0,0x00,0x00,0x01,0xE0,0x00,0x00,0x01,0xE0,0x00,0x00,0x01,0xE0,0x00,0x00,0x01,0xE0,0x00,0x00,0x01,0xE0,0x00,0x00,0x01,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // + ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xF0,0x00,0x00,0x0F,0xF0,0x00,0x00,0x0F,0xF0,0x00,0x00,0x0F,0xF0,0x00,0x00,0x0F,0xF0,0x00,0x00,0x0F,0xF0,0x00,0x00,0x0F,0xF0,0x00,0x00,0x0F,0xF0,0x00,0x00,0x0F,0xF0,0x00,0x00,0x0F,0xF0,0x00,0x00,0x1F,0xE0,0x00,0x00,0x1F,0xE0,0x00,0x00,0x1F,0xE0,0x00,0x00,0x1F,0xC0,0x00,0x00,0x1F,0xC0,0x00,0x00,0x3F,0x80,0x00,0x00,0x3F,0x80,0x00,0x00,0x3F,0x80,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x7E,0x00,0x00,0x00,0x7E,0x00,0x00,0x00,0x7E,0x00,0x00,0x00,0x7C,0x00,0x00, // , ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0xFF,0xFF,0xFE,0x1F,0xFF,0xFF,0xFE,0x1F,0xFF,0xFF,0xFE,0x1F,0xFF,0xFF,0xFE,0x1F,0xFF,0xFF,0xFE,0x1F,0xFF,0xFF,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // - ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0xE0,0x00,0x00,0x3F,0xF0,0x00,0x00,0x3F,0xF0,0x00,0x00,0x3F,0xF0,0x00,0x00,0x3F,0xF0,0x00,0x00,0x3F,0xF0,0x00,0x00,0x3F,0xF0,0x00,0x00,0x3F,0xF0,0x00,0x00,0x3F,0xF0,0x00,0x00,0x3F,0xF0,0x00,0x00,0x3F,0xF0,0x00,0x00,0x3F,0xF0,0x00,0x00,0x3F,0xF0,0x00,0x00,0x3F,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // . ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF0,0x00,0x00,0x03,0xF0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xC0,0x00,0x00,0x0F,0xC0,0x00,0x00,0x0F,0x80,0x00,0x00,0x1F,0x80,0x00,0x00,0x1F,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3E,0x00,0x00,0x00,0x7E,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0xFC,0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF0,0x00,0x00,0x03,0xF0,0x00,0x00,0x03,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xC0,0x00,0x00,0x0F,0xC0,0x00,0x00,0x0F,0x80,0x00,0x00,0x1F,0x80,0x00,0x00,0x1F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3E,0x00,0x00,0x00,0x7E,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0xFC,0x00,0x00,0x00,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF0,0x00,0x00,0x03,0xF0,0x00,0x00,0x03,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xC0,0x00,0x00,0x0F,0xC0,0x00,0x00,0x0F,0xC0,0x00,0x00,0x0F,0x80,0x00,0x00,0x1F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // / ++ ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xF0,0x00,0x00,0x3F,0xFC,0x00,0x00,0x7F,0xFE,0x00,0x00,0x7F,0xFF,0x00,0x00,0xFF,0xFF,0x80,0x01,0xFE,0x7F,0x80,0x01,0xF8,0x1F,0xC0,0x03,0xF0,0x0F,0xC0,0x03,0xF0,0x07,0xE0,0x03,0xE0,0x07,0xE0,0x07,0xE0,0x07,0xE0,0x07,0xE0,0x07,0xF0,0x07,0xC0,0x0F,0xF0,0x07,0xC0,0x0F,0xF0,0x0F,0xC0,0x1F,0xF0,0x0F,0xC0,0x1F,0xF0,0x0F,0xC0,0x3F,0xF0,0x0F,0xC0,0x3D,0xF0,0x0F,0x80,0x7D,0xF8,0x0F,0x80,0x79,0xF8,0x0F,0x80,0xF9,0xF8,0x0F,0x80,0xF1,0xF8,0x0F,0x81,0xF1,0xF8,0x0F,0x81,0xE1,0xF8,0x0F,0x83,0xE1,0xF8,0x0F,0x83,0xC1,0xF8,0x0F,0x87,0xC1,0xF8,0x0F,0x87,0x81,0xF8,0x0F,0x8F,0x81,0xF8,0x0F,0x8F,0x01,0xF8,0x0F,0x8F,0x01,0xF8,0x0F,0x9E,0x01,0xF8,0x0F,0x9E,0x01,0xF8,0x0F,0xBC,0x01,0xF8,0x0F,0xFC,0x01,0xF0,0x0F,0xF8,0x01,0xF0,0x0F,0xF8,0x01,0xF0,0x0F,0xF0,0x01,0xF0,0x07,0xF0,0x03,0xF0,0x07,0xE0,0x03,0xF0,0x07,0xE0,0x03,0xE0,0x07,0xE0,0x03,0xE0,0x03,0xE0,0x07,0xE0,0x03,0xF0,0x07,0xC0,0x03,0xF8,0x0F,0xC0,0x01,0xFC,0x1F,0xC0,0x01,0xFF,0xFF,0x80,0x00,0xFF,0xFF,0x00,0x00,0x7F,0xFF,0x00,0x00,0x3F,0xFE,0x00,0x00,0x1F,0xFC,0x00,0x00,0x07,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 0 ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xF8,0x00,0x00,0x0F,0xF8,0x00,0x00,0x1F,0xF8,0x00,0x00,0x7F,0xF8,0x00,0x00,0xFF,0xF8,0x00,0x03,0xFF,0xF8,0x00,0x03,0xFF,0xF8,0x00,0x03,0xFC,0xF8,0x00,0x03,0xF1,0xF8,0x00,0x03,0xC1,0xF8,0x00,0x03,0x81,0xF8,0x00,0x02,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x01,0xFF,0xFF,0xF8,0x01,0xFF,0xFF,0xF8,0x01,0xFF,0xFF,0xF8,0x01,0xFF,0xFF,0xF8,0x01,0xFF,0xFF,0xF8,0x01,0xFF,0xFF,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 1 ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xC0,0x00,0x00,0x7F,0xFC,0x00,0x01,0xFF,0xFF,0x00,0x07,0xFF,0xFF,0x80,0x0F,0xFF,0xFF,0xC0,0x0F,0xFF,0xFF,0xE0,0x0F,0xFE,0x3F,0xE0,0x0F,0xE0,0x07,0xF0,0x0F,0x80,0x03,0xF0,0x0E,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0xFC,0x00,0x00,0x00,0xFC,0x00,0x00,0x00,0xFC,0x00,0x00,0x00,0xFC,0x00,0x00,0x00,0xFC,0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF0,0x00,0x00,0x03,0xF0,0x00,0x00,0x03,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x0F,0xC0,0x00,0x00,0x0F,0xC0,0x00,0x00,0x1F,0x80,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x7E,0x00,0x00,0x00,0xFC,0x00,0x00,0x01,0xF8,0x00,0x00,0x03,0xF8,0x00,0x00,0x03,0xF0,0x00,0x00,0x07,0xE0,0x00,0x00,0x0F,0xC0,0x00,0x00,0x1F,0xC0,0x00,0x00,0x3F,0x80,0x00,0x00,0x3F,0x00,0x00,0x00,0x7E,0x00,0x00,0x00,0xFC,0x00,0x00,0x01,0xFC,0x00,0x00,0x03,0xF8,0x00,0x00,0x03,0xF0,0x00,0x00,0x07,0xE0,0x00,0x00,0x0F,0xFF,0xFF,0xFC,0x0F,0xFF,0xFF,0xFC,0x0F,0xFF,0xFF,0xFC,0x0F,0xFF,0xFF,0xFC,0x0F,0xFF,0xFF,0xFC,0x0F,0xFF,0xFF,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 2 ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x80,0x00,0x00,0xFF,0xF8,0x00,0x07,0xFF,0xFE,0x00,0x07,0xFF,0xFF,0x00,0x07,0xFF,0xFF,0x80,0x07,0xFF,0xFF,0xC0,0x07,0xF8,0x7F,0xC0,0x07,0x80,0x0F,0xE0,0x04,0x00,0x07,0xE0,0x00,0x00,0x03,0xF0,0x00,0x00,0x03,0xF0,0x00,0x00,0x03,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x03,0xF0,0x00,0x00,0x03,0xF0,0x00,0x00,0x03,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x0F,0xE0,0x00,0x00,0x3F,0xC0,0x00,0x1F,0xFF,0x80,0x00,0x3F,0xFF,0x00,0x00,0x3F,0xFC,0x00,0x00,0x3F,0xFC,0x00,0x00,0x3F,0xFF,0x00,0x00,0x1F,0xFF,0x80,0x00,0x00,0x3F,0xC0,0x00,0x00,0x0F,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x03,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x03,0xF0,0x08,0x00,0x07,0xF0,0x0E,0x00,0x0F,0xF0,0x0F,0xC0,0x3F,0xE0,0x0F,0xFF,0xFF,0xE0,0x0F,0xFF,0xFF,0xC0,0x0F,0xFF,0xFF,0x80,0x0F,0xFF,0xFF,0x00,0x03,0xFF,0xFC,0x00,0x00,0x7F,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 3 ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x3F,0x80,0x00,0x00,0x7F,0x80,0x00,0x00,0x7F,0x80,0x00,0x00,0xFF,0x80,0x00,0x00,0xFF,0x80,0x00,0x01,0xFF,0x80,0x00,0x01,0xFF,0x80,0x00,0x01,0xDF,0x80,0x00,0x03,0xDF,0x80,0x00,0x03,0xDF,0x80,0x00,0x07,0x9F,0x80,0x00,0x07,0x9F,0x80,0x00,0x0F,0x1F,0x80,0x00,0x0F,0x1F,0x80,0x00,0x1E,0x1F,0x80,0x00,0x1E,0x1F,0x80,0x00,0x3C,0x1F,0x80,0x00,0x3C,0x1F,0x80,0x00,0x7C,0x1F,0x80,0x00,0x78,0x1F,0x80,0x00,0xF8,0x1F,0x80,0x00,0xF0,0x1F,0x80,0x01,0xF0,0x1F,0x80,0x01,0xE0,0x1F,0x80,0x03,0xE0,0x1F,0x80,0x03,0xC0,0x1F,0x80,0x07,0xC0,0x1F,0x80,0x07,0xC0,0x1F,0x80,0x0F,0x80,0x1F,0x80,0x0F,0x80,0x1F,0x80,0x1F,0x00,0x1F,0x80,0x1F,0x00,0x1F,0x80,0x1F,0xFF,0xFF,0xF8,0x1F,0xFF,0xFF,0xFC,0x1F,0xFF,0xFF,0xFC,0x1F,0xFF,0xFF,0xFC,0x1F,0xFF,0xFF,0xFC,0x1F,0xFF,0xFF,0xFC,0x00,0x00,0x1F,0x80,0x00,0x00,0x1F,0x80,0x00,0x00,0x1F,0x80,0x00,0x00,0x1F,0x80,0x00,0x00,0x1F,0x80,0x00,0x00,0x1F,0x80,0x00,0x00,0x1F,0x80,0x00,0x00,0x1F,0x80,0x00,0x00,0x1F,0x80,0x00,0x00,0x1F,0x80,0x00,0x00,0x1F,0x80,0x00,0x00,0x1F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 4 ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xFF,0xFF,0xC0,0x03,0xFF,0xFF,0xE0,0x03,0xFF,0xFF,0xE0,0x03,0xFF,0xFF,0xE0,0x03,0xFF,0xFF,0xE0,0x03,0xFF,0xFF,0xE0,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE3,0xC0,0x00,0x03,0xFF,0xF8,0x00,0x03,0xFF,0xFE,0x00,0x03,0xFF,0xFF,0x00,0x03,0xFF,0xFF,0x80,0x03,0xFF,0xFF,0xC0,0x03,0xF0,0xFF,0xE0,0x03,0x00,0x1F,0xE0,0x00,0x00,0x0F,0xF0,0x00,0x00,0x07,0xF0,0x00,0x00,0x03,0xF0,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x03,0xF0,0x08,0x00,0x07,0xF0,0x0E,0x00,0x0F,0xE0,0x0F,0xC0,0x3F,0xE0,0x0F,0xFF,0xFF,0xC0,0x0F,0xFF,0xFF,0x80,0x0F,0xFF,0xFF,0x80,0x0F,0xFF,0xFE,0x00,0x07,0xFF,0xFC,0x00,0x00,0xFF,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 5 ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x78,0x00,0x00,0x07,0xFF,0x00,0x00,0x0F,0xFF,0xC0,0x00,0x3F,0xFF,0xC0,0x00,0x7F,0xFF,0xC0,0x00,0x7F,0xFF,0xC0,0x00,0xFF,0x8F,0xC0,0x01,0xFE,0x00,0xC0,0x01,0xF8,0x00,0x00,0x03,0xF0,0x00,0x00,0x03,0xF0,0x00,0x00,0x03,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x0F,0x80,0x00,0x00,0x0F,0x80,0x00,0x00,0x0F,0x80,0xE0,0x00,0x0F,0x87,0xFC,0x00,0x0F,0x8F,0xFF,0x00,0x0F,0x9F,0xFF,0x80,0x0F,0x3F,0xFF,0xC0,0x0F,0x7F,0xFF,0xC0,0x0F,0xFC,0x1F,0xE0,0x0F,0xF8,0x07,0xE0,0x0F,0xF0,0x03,0xF0,0x0F,0xE0,0x03,0xF0,0x0F,0xE0,0x01,0xF0,0x0F,0xC0,0x01,0xF8,0x0F,0xC0,0x01,0xF8,0x0F,0xC0,0x01,0xF8,0x0F,0xC0,0x01,0xF8,0x0F,0xC0,0x00,0xF8,0x0F,0xC0,0x00,0xF8,0x0F,0xC0,0x00,0xF8,0x0F,0xC0,0x00,0xF8,0x0F,0xC0,0x00,0xF8,0x0F,0xC0,0x00,0xF8,0x07,0xC0,0x01,0xF8,0x07,0xC0,0x01,0xF8,0x07,0xC0,0x01,0xF8,0x07,0xE0,0x01,0xF0,0x03,0xE0,0x03,0xF0,0x03,0xF0,0x03,0xF0,0x03,0xF0,0x07,0xF0,0x01,0xF8,0x0F,0xE0,0x01,0xFF,0x3F,0xE0,0x00,0xFF,0xFF,0xC0,0x00,0x7F,0xFF,0x80,0x00,0x3F,0xFF,0x00,0x00,0x1F,0xFE,0x00,0x00,0x07,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 6 ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xFF,0xFF,0xF8,0x0F,0xFF,0xFF,0xF8,0x0F,0xFF,0xFF,0xF8,0x0F,0xFF,0xFF,0xF8,0x0F,0xFF,0xFF,0xF8,0x0F,0xFF,0xFF,0xF8,0x00,0x00,0x03,0xF0,0x00,0x00,0x03,0xF0,0x00,0x00,0x03,0xF0,0x00,0x00,0x03,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xC0,0x00,0x00,0x0F,0xC0,0x00,0x00,0x0F,0xC0,0x00,0x00,0x0F,0x80,0x00,0x00,0x1F,0x80,0x00,0x00,0x1F,0x80,0x00,0x00,0x1F,0x80,0x00,0x00,0x1F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3E,0x00,0x00,0x00,0x7E,0x00,0x00,0x00,0x7E,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0xFC,0x00,0x00,0x00,0xFC,0x00,0x00,0x00,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x03,0xF0,0x00,0x00,0x03,0xF0,0x00,0x00,0x03,0xF0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xC0,0x00,0x00,0x0F,0xC0,0x00,0x00,0x0F,0xC0,0x00,0x00,0x0F,0x80,0x00,0x00,0x1F,0x80,0x00,0x00,0x1F,0x80,0x00,0x00,0x1F,0x80,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x7E,0x00,0x00,0x00,0x7E,0x00,0x00,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 7 ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xC0,0x00,0x00,0x1F,0xFC,0x00,0x00,0x7F,0xFE,0x00,0x00,0xFF,0xFF,0x80,0x01,0xFF,0xFF,0x80,0x01,0xFF,0xFF,0xC0,0x03,0xFC,0x1F,0xE0,0x03,0xF0,0x07,0xE0,0x07,0xE0,0x07,0xE0,0x07,0xE0,0x03,0xF0,0x07,0xE0,0x03,0xF0,0x07,0xC0,0x03,0xF0,0x07,0xC0,0x01,0xF0,0x07,0xC0,0x01,0xF0,0x07,0xC0,0x01,0xF0,0x07,0xC0,0x01,0xF0,0x07,0xC0,0x01,0xF0,0x07,0xC0,0x03,0xF0,0x07,0xE0,0x03,0xE0,0x03,0xE0,0x03,0xE0,0x03,0xF0,0x07,0xE0,0x01,0xF8,0x0F,0xC0,0x01,0xFE,0x3F,0x80,0x00,0xFF,0xFF,0x00,0x00,0x3F,0xFE,0x00,0x00,0x1F,0xFC,0x00,0x00,0x7F,0xFF,0x00,0x00,0xFF,0xFF,0x80,0x01,0xFE,0x3F,0xC0,0x03,0xF0,0x0F,0xE0,0x07,0xE0,0x07,0xE0,0x07,0xE0,0x03,0xF0,0x0F,0xC0,0x01,0xF0,0x0F,0xC0,0x01,0xF8,0x0F,0x80,0x01,0xF8,0x0F,0x80,0x01,0xF8,0x0F,0x80,0x00,0xF8,0x0F,0x80,0x00,0xF8,0x0F,0x80,0x00,0xF8,0x0F,0x80,0x00,0xF8,0x0F,0x80,0x01,0xF8,0x0F,0x80,0x01,0xF8,0x0F,0xC0,0x01,0xF8,0x0F,0xC0,0x01,0xF8,0x0F,0xE0,0x03,0xF0,0x07,0xE0,0x07,0xF0,0x07,0xF0,0x0F,0xE0,0x03,0xFE,0x3F,0xE0,0x03,0xFF,0xFF,0xC0,0x01,0xFF,0xFF,0xC0,0x00,0xFF,0xFF,0x00,0x00,0x3F,0xFE,0x00,0x00,0x0F,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 8 ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xC0,0x00,0x00,0x3F,0xF8,0x00,0x00,0x7F,0xFC,0x00,0x00,0xFF,0xFE,0x00,0x01,0xFF,0xFF,0x00,0x03,0xFF,0xFF,0x80,0x03,0xF8,0x3F,0x80,0x07,0xF0,0x0F,0xC0,0x07,0xE0,0x07,0xC0,0x0F,0xC0,0x07,0xE0,0x0F,0xC0,0x03,0xE0,0x0F,0xC0,0x03,0xE0,0x0F,0x80,0x03,0xF0,0x0F,0x80,0x01,0xF0,0x1F,0x80,0x01,0xF0,0x1F,0x80,0x01,0xF0,0x1F,0x80,0x01,0xF0,0x1F,0x80,0x01,0xF0,0x1F,0x80,0x01,0xF8,0x1F,0x80,0x01,0xF8,0x1F,0x80,0x01,0xF8,0x0F,0x80,0x01,0xF8,0x0F,0x80,0x03,0xF8,0x0F,0x80,0x03,0xF8,0x0F,0xC0,0x03,0xF8,0x0F,0xC0,0x03,0xF8,0x07,0xC0,0x07,0xF8,0x07,0xE0,0x0F,0xF8,0x07,0xF0,0x1F,0xF8,0x03,0xFE,0x7F,0xF8,0x01,0xFF,0xFE,0xF8,0x01,0xFF,0xFC,0xF8,0x00,0xFF,0xFC,0xF8,0x00,0x3F,0xF0,0xF8,0x00,0x0F,0xE1,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xC0,0x00,0x00,0x0F,0xC0,0x03,0x00,0x1F,0x80,0x03,0xC0,0x7F,0x80,0x03,0xFF,0xFF,0x00,0x03,0xFF,0xFF,0x00,0x03,0xFF,0xFE,0x00,0x03,0xFF,0xFC,0x00,0x01,0xFF,0xF0,0x00,0x00,0x7F,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 9 ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xF0,0x00,0x00,0x0F,0xF0,0x00,0x00,0x0F,0xF0,0x00,0x00,0x0F,0xF0,0x00,0x00,0x0F,0xF0,0x00,0x00,0x0F,0xF0,0x00,0x00,0x0F,0xF0,0x00,0x00,0x0F,0xF0,0x00,0x00,0x0F,0xF0,0x00,0x00,0x0F,0xF0,0x00,0x00,0x0F,0xF0,0x00,0x00,0x0F,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xF0,0x00,0x00,0x0F,0xF0,0x00,0x00,0x0F,0xF0,0x00,0x00,0x0F,0xF0,0x00,0x00,0x0F,0xF0,0x00,0x00,0x0F,0xF0,0x00,0x00,0x0F,0xF0,0x00,0x00,0x0F,0xF0,0x00,0x00,0x0F,0xF0,0x00,0x00,0x0F,0xF0,0x00,0x00,0x0F,0xF0,0x00,0x00,0x0F,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // : ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xF0,0x00,0x00,0x0F,0xF0,0x00,0x00,0x0F,0xF0,0x00,0x00,0x0F,0xF0,0x00,0x00,0x0F,0xF0,0x00,0x00,0x0F,0xF0,0x00,0x00,0x0F,0xF0,0x00,0x00,0x0F,0xF0,0x00,0x00,0x0F,0xF0,0x00,0x00,0x0F,0xF0,0x00,0x00,0x0F,0xF0,0x00,0x00,0x0F,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xF0,0x00,0x00,0x0F,0xF0,0x00,0x00,0x0F,0xF0,0x00,0x00,0x0F,0xF0,0x00,0x00,0x0F,0xF0,0x00,0x00,0x0F,0xF0,0x00,0x00,0x0F,0xF0,0x00,0x00,0x0F,0xF0,0x00,0x00,0x0F,0xF0,0x00,0x00,0x0F,0xF0,0x00,0x00,0x0F,0xF0,0x00,0x00,0x1F,0xE0,0x00,0x00,0x1F,0xE0,0x00,0x00,0x1F,0xC0,0x00,0x00,0x1F,0xC0,0x00,0x00,0x1F,0xC0,0x00,0x00,0x3F,0x80,0x00,0x00,0x3F,0x80,0x00,0x00,0x3F,0x80,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ; ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x1C,0x00,0x00,0x00,0x7C,0x00,0x00,0x01,0xFC,0x00,0x00,0x07,0xFC,0x00,0x00,0x1F,0xFC,0x00,0x00,0x7F,0xF8,0x00,0x01,0xFF,0xE0,0x00,0x07,0xFF,0x80,0x00,0x1F,0xFE,0x00,0x00,0x7F,0xF8,0x00,0x01,0xFF,0xE0,0x00,0x07,0xFF,0x80,0x00,0x1F,0xFE,0x00,0x00,0x1F,0xF8,0x00,0x00,0x1F,0xE0,0x00,0x00,0x1F,0x80,0x00,0x00,0x1F,0xC0,0x00,0x00,0x1F,0xF0,0x00,0x00,0x1F,0xFC,0x00,0x00,0x0F,0xFF,0x00,0x00,0x03,0xFF,0xC0,0x00,0x00,0xFF,0xF0,0x00,0x00,0x3F,0xFC,0x00,0x00,0x0F,0xFF,0x00,0x00,0x03,0xFF,0xC0,0x00,0x00,0xFF,0xF0,0x00,0x00,0x3F,0xFC,0x00,0x00,0x0F,0xFC,0x00,0x00,0x03,0xFC,0x00,0x00,0x00,0xFC,0x00,0x00,0x00,0x3C,0x00,0x00,0x00,0x1C,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // < ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0xFF,0xFF,0xFC,0x1F,0xFF,0xFF,0xFC,0x1F,0xFF,0xFF,0xFC,0x1F,0xFF,0xFF,0xFC,0x1F,0xFF,0xFF,0xFC,0x1F,0xFF,0xFF,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0xFF,0xFF,0xFC,0x1F,0xFF,0xFF,0xFC,0x1F,0xFF,0xFF,0xFC,0x1F,0xFF,0xFF,0xFC,0x1F,0xFF,0xFF,0xFC,0x1F,0xFF,0xFF,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // = ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x1C,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x1F,0xC0,0x00,0x00,0x1F,0xF0,0x00,0x00,0x1F,0xFC,0x00,0x00,0x0F,0xFF,0x00,0x00,0x03,0xFF,0xC0,0x00,0x00,0xFF,0xF0,0x00,0x00,0x3F,0xFC,0x00,0x00,0x0F,0xFF,0x00,0x00,0x03,0xFF,0xC0,0x00,0x00,0xFF,0xF0,0x00,0x00,0x3F,0xFC,0x00,0x00,0x0F,0xFC,0x00,0x00,0x03,0xFC,0x00,0x00,0x00,0xFC,0x00,0x00,0x01,0xFC,0x00,0x00,0x07,0xFC,0x00,0x00,0x1F,0xFC,0x00,0x00,0x7F,0xF8,0x00,0x01,0xFF,0xE0,0x00,0x07,0xFF,0x80,0x00,0x1F,0xFE,0x00,0x00,0x7F,0xF8,0x00,0x01,0xFF,0xE0,0x00,0x07,0xFF,0x80,0x00,0x1F,0xFE,0x00,0x00,0x1F,0xF8,0x00,0x00,0x1F,0xE0,0x00,0x00,0x1F,0x80,0x00,0x00,0x1E,0x00,0x00,0x00,0x1C,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // > ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xE0,0x00,0x00,0x0F,0xFC,0x00,0x00,0x3F,0xFF,0x00,0x00,0xFF,0xFF,0x80,0x01,0xFF,0xFF,0xC0,0x01,0xFF,0xFF,0xC0,0x01,0xFC,0x3F,0xE0,0x01,0xF0,0x0F,0xE0,0x01,0xC0,0x07,0xE0,0x01,0x80,0x03,0xF0,0x00,0x00,0x03,0xF0,0x00,0x00,0x03,0xF0,0x00,0x00,0x03,0xF0,0x00,0x00,0x03,0xF0,0x00,0x00,0x03,0xF0,0x00,0x00,0x03,0xF0,0x00,0x00,0x03,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x0F,0xC0,0x00,0x00,0x1F,0xC0,0x00,0x00,0x1F,0x80,0x00,0x00,0x3F,0x80,0x00,0x00,0x7F,0x00,0x00,0x00,0x7E,0x00,0x00,0x00,0xFC,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x03,0xF0,0x00,0x00,0x03,0xF0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x03,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xC0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ? ++ ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0x00,0x00,0x07,0xFE,0x00,0x00,0x1F,0xFF,0x80,0x00,0x7F,0xFF,0xC0,0x00,0xFF,0xFF,0xE0,0x01,0xFF,0x9F,0xE0,0x03,0xF8,0x03,0xF0,0x03,0xF0,0x01,0xF0,0x07,0xE0,0x00,0xF8,0x0F,0xC0,0x00,0x78,0x0F,0x80,0x00,0x7C,0x1F,0x00,0x00,0x3C,0x1F,0x00,0x00,0x3C,0x1E,0x00,0x00,0x3C,0x3E,0x00,0x00,0x3C,0x3C,0x00,0xFE,0x3C,0x3C,0x01,0xFF,0xBC,0x7C,0x03,0xFF,0x9C,0x78,0x07,0xFF,0xFC,0x78,0x07,0xFF,0xFC,0x78,0x0F,0xC1,0xFC,0x78,0x0F,0x80,0xFC,0xF8,0x1F,0x00,0x7C,0xF8,0x1E,0x00,0x7C,0xF8,0x1E,0x00,0x3C,0xF8,0x3E,0x00,0x3C,0xF0,0x3E,0x00,0x3C,0xF0,0x3C,0x00,0x3C,0xF0,0x3C,0x00,0x3C,0xF0,0x3C,0x00,0x3C,0xF0,0x3C,0x00,0x3C,0xF0,0x3C,0x00,0x3C,0xF0,0x3E,0x00,0x3C,0xF8,0x3E,0x00,0x3C,0xF8,0x1E,0x00,0x3C,0xF8,0x1F,0x00,0x7C,0x78,0x1F,0x00,0x7C,0x78,0x0F,0x80,0xFC,0x78,0x0F,0xE3,0xFC,0x78,0x07,0xFF,0xFC,0x7C,0x07,0xFF,0xFC,0x3C,0x03,0xFF,0x9C,0x3C,0x01,0xFF,0x3C,0x3E,0x00,0x7E,0x00,0x1E,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x0F,0x80,0x00,0x00,0x0F,0xC0,0x00,0x00,0x07,0xE0,0x00,0x00,0x03,0xF0,0x00,0x00,0x03,0xF8,0x00,0x00,0x01,0xFE,0x00,0x00,0x00,0xFF,0xF8,0x00,0x00,0x7F,0xFF,0xF8,0x00,0x3F,0xFF,0xF8,0x00,0x0F,0xFF,0xF8,0x00,0x03,0xFF,0xF8,0x00,0x00,0x3F,0xF8, // @ ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xE0,0x00,0x00,0x0F,0xE0,0x00,0x00,0x0F,0xE0,0x00,0x00,0x0F,0xF0,0x00,0x00,0x1F,0xF0,0x00,0x00,0x1F,0xF0,0x00,0x00,0x1F,0xF0,0x00,0x00,0x1F,0xF8,0x00,0x00,0x3E,0xF8,0x00,0x00,0x3E,0xF8,0x00,0x00,0x3E,0xF8,0x00,0x00,0x3E,0x7C,0x00,0x00,0x7C,0x7C,0x00,0x00,0x7C,0x7C,0x00,0x00,0x7C,0x7C,0x00,0x00,0x7C,0x7E,0x00,0x00,0xFC,0x3E,0x00,0x00,0xF8,0x3E,0x00,0x00,0xF8,0x3E,0x00,0x00,0xF8,0x3E,0x00,0x00,0xF8,0x3F,0x00,0x01,0xF8,0x1F,0x00,0x01,0xF0,0x1F,0x00,0x01,0xF0,0x1F,0x00,0x01,0xF0,0x1F,0x80,0x03,0xF0,0x0F,0x80,0x03,0xE0,0x0F,0x80,0x03,0xE0,0x0F,0x80,0x03,0xE0,0x0F,0xC0,0x07,0xE0,0x0F,0xC0,0x07,0xE0,0x07,0xC0,0x07,0xC0,0x07,0xC0,0x07,0xFF,0xFF,0xE0,0x0F,0xFF,0xFF,0xE0,0x0F,0xFF,0xFF,0xE0,0x0F,0xFF,0xFF,0xE0,0x0F,0xFF,0xFF,0xE0,0x0F,0xFF,0xFF,0xF0,0x1F,0x80,0x03,0xF0,0x1F,0x00,0x01,0xF0,0x1F,0x00,0x01,0xF0,0x1F,0x00,0x01,0xF8,0x3F,0x00,0x01,0xF8,0x3F,0x00,0x00,0xF8,0x3E,0x00,0x00,0xF8,0x3E,0x00,0x00,0xFC,0x7E,0x00,0x00,0xFC,0x7E,0x00,0x00,0xFC,0x7E,0x00,0x00,0x7C,0x7C,0x00,0x00,0x7E,0xFC,0x00,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // A ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xFF,0xC0,0x00,0x0F,0xFF,0xF8,0x00,0x0F,0xFF,0xFE,0x00,0x0F,0xFF,0xFF,0x00,0x0F,0xFF,0xFF,0x80,0x0F,0xFF,0xFF,0xC0,0x0F,0x80,0x3F,0xC0,0x0F,0x80,0x0F,0xE0,0x0F,0x80,0x07,0xE0,0x0F,0x80,0x03,0xF0,0x0F,0x80,0x03,0xF0,0x0F,0x80,0x03,0xF0,0x0F,0x80,0x03,0xF0,0x0F,0x80,0x03,0xF0,0x0F,0x80,0x03,0xF0,0x0F,0x80,0x03,0xF0,0x0F,0x80,0x03,0xE0,0x0F,0x80,0x07,0xE0,0x0F,0x80,0x0F,0xE0,0x0F,0x80,0x3F,0xC0,0x0F,0xFF,0xFF,0x80,0x0F,0xFF,0xFF,0x00,0x0F,0xFF,0xFC,0x00,0x0F,0xFF,0xFE,0x00,0x0F,0xFF,0xFF,0x80,0x0F,0xFF,0xFF,0xC0,0x0F,0x80,0x0F,0xE0,0x0F,0x80,0x07,0xE0,0x0F,0x80,0x03,0xF0,0x0F,0x80,0x01,0xF0,0x0F,0x80,0x01,0xF0,0x0F,0x80,0x01,0xF8,0x0F,0x80,0x01,0xF8,0x0F,0x80,0x01,0xF8,0x0F,0x80,0x00,0xF8,0x0F,0x80,0x00,0xF8,0x0F,0x80,0x00,0xF8,0x0F,0x80,0x00,0xF8,0x0F,0x80,0x00,0xF8,0x0F,0x80,0x01,0xF8,0x0F,0x80,0x01,0xF8,0x0F,0x80,0x01,0xF8,0x0F,0x80,0x03,0xF0,0x0F,0x80,0x07,0xF0,0x0F,0x80,0x0F,0xF0,0x0F,0xFF,0xFF,0xE0,0x0F,0xFF,0xFF,0xC0,0x0F,0xFF,0xFF,0xC0,0x0F,0xFF,0xFF,0x80,0x0F,0xFF,0xFE,0x00,0x0F,0xFF,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // B ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x78,0x00,0x00,0x07,0xFF,0x00,0x00,0x1F,0xFF,0xC0,0x00,0x3F,0xFF,0xE0,0x00,0x7F,0xFF,0xE0,0x00,0xFF,0xFF,0xE0,0x00,0xFF,0x07,0xE0,0x01,0xFC,0x00,0xE0,0x03,0xF8,0x00,0x60,0x03,0xF0,0x00,0x20,0x03,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x0F,0xC0,0x00,0x00,0x0F,0xC0,0x00,0x00,0x0F,0xC0,0x00,0x00,0x0F,0x80,0x00,0x00,0x0F,0x80,0x00,0x00,0x1F,0x80,0x00,0x00,0x1F,0x80,0x00,0x00,0x1F,0x80,0x00,0x00,0x1F,0x80,0x00,0x00,0x1F,0x80,0x00,0x00,0x1F,0x80,0x00,0x00,0x1F,0x80,0x00,0x00,0x1F,0x80,0x00,0x00,0x1F,0x80,0x00,0x00,0x1F,0x80,0x00,0x00,0x1F,0x80,0x00,0x00,0x1F,0x80,0x00,0x00,0x1F,0x80,0x00,0x00,0x1F,0x80,0x00,0x00,0x1F,0x80,0x00,0x00,0x1F,0x80,0x00,0x00,0x1F,0x80,0x00,0x00,0x1F,0x80,0x00,0x00,0x0F,0x80,0x00,0x00,0x0F,0xC0,0x00,0x00,0x0F,0xC0,0x00,0x00,0x0F,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x03,0xF0,0x00,0x00,0x03,0xF8,0x00,0x30,0x01,0xFC,0x00,0x60,0x01,0xFE,0x01,0xE0,0x00,0xFF,0xFF,0xE0,0x00,0x7F,0xFF,0xE0,0x00,0x3F,0xFF,0xE0,0x00,0x1F,0xFF,0xE0,0x00,0x0F,0xFF,0x80,0x00,0x03,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // C ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xFC,0x00,0x00,0x1F,0xFF,0xC0,0x00,0x1F,0xFF,0xF0,0x00,0x1F,0xFF,0xF8,0x00,0x1F,0xFF,0xFE,0x00,0x1F,0xFF,0xFF,0x00,0x1F,0x81,0xFF,0x00,0x1F,0x80,0x7F,0x80,0x1F,0x80,0x1F,0x80,0x1F,0x80,0x0F,0xC0,0x1F,0x80,0x0F,0xC0,0x1F,0x80,0x07,0xE0,0x1F,0x80,0x07,0xE0,0x1F,0x80,0x03,0xE0,0x1F,0x80,0x03,0xF0,0x1F,0x80,0x03,0xF0,0x1F,0x80,0x03,0xF0,0x1F,0x80,0x03,0xF0,0x1F,0x80,0x01,0xF0,0x1F,0x80,0x01,0xF0,0x1F,0x80,0x01,0xF0,0x1F,0x80,0x01,0xF8,0x1F,0x80,0x01,0xF8,0x1F,0x80,0x01,0xF8,0x1F,0x80,0x01,0xF8,0x1F,0x80,0x01,0xF8,0x1F,0x80,0x01,0xF8,0x1F,0x80,0x01,0xF8,0x1F,0x80,0x01,0xF8,0x1F,0x80,0x01,0xF8,0x1F,0x80,0x01,0xF0,0x1F,0x80,0x01,0xF0,0x1F,0x80,0x01,0xF0,0x1F,0x80,0x03,0xF0,0x1F,0x80,0x03,0xF0,0x1F,0x80,0x03,0xF0,0x1F,0x80,0x03,0xF0,0x1F,0x80,0x03,0xE0,0x1F,0x80,0x07,0xE0,0x1F,0x80,0x07,0xE0,0x1F,0x80,0x07,0xE0,0x1F,0x80,0x0F,0xC0,0x1F,0x80,0x1F,0xC0,0x1F,0x80,0x3F,0x80,0x1F,0x80,0xFF,0x80,0x1F,0xFF,0xFF,0x00,0x1F,0xFF,0xFE,0x00,0x1F,0xFF,0xFC,0x00,0x1F,0xFF,0xF8,0x00,0x1F,0xFF,0xE0,0x00,0x1F,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // D ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xFF,0xFF,0xE0,0x07,0xFF,0xFF,0xF0,0x07,0xFF,0xFF,0xF0,0x07,0xFF,0xFF,0xF0,0x07,0xFF,0xFF,0xF0,0x07,0xFF,0xFF,0xF0,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xFF,0xFF,0xE0,0x07,0xFF,0xFF,0xE0,0x07,0xFF,0xFF,0xE0,0x07,0xFF,0xFF,0xE0,0x07,0xFF,0xFF,0xE0,0x07,0xFF,0xFF,0xE0,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xFF,0xFF,0xF0,0x07,0xFF,0xFF,0xF0,0x07,0xFF,0xFF,0xF0,0x07,0xFF,0xFF,0xF0,0x07,0xFF,0xFF,0xF0,0x07,0xFF,0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // E ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xFF,0xFF,0xF0,0x03,0xFF,0xFF,0xF8,0x03,0xFF,0xFF,0xF8,0x03,0xFF,0xFF,0xF8,0x03,0xFF,0xFF,0xF8,0x03,0xFF,0xFF,0xF8,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xFF,0xFF,0xE0,0x03,0xFF,0xFF,0xE0,0x03,0xFF,0xFF,0xE0,0x03,0xFF,0xFF,0xE0,0x03,0xFF,0xFF,0xE0,0x03,0xFF,0xFF,0xE0,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // F ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0x00,0x00,0x07,0xFF,0x00,0x00,0x1F,0xFF,0x80,0x00,0x3F,0xFF,0xE0,0x00,0x7F,0xFF,0xE0,0x00,0xFF,0xFF,0xE0,0x01,0xFF,0x07,0xE0,0x01,0xFC,0x01,0xE0,0x03,0xF8,0x00,0x60,0x07,0xF0,0x00,0x20,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x0F,0xC0,0x00,0x00,0x0F,0xC0,0x00,0x00,0x0F,0x80,0x00,0x00,0x1F,0x80,0x00,0x00,0x1F,0x80,0x00,0x00,0x1F,0x80,0x00,0x00,0x1F,0x80,0x00,0x00,0x1F,0x80,0x00,0x00,0x1F,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x3F,0xF0,0x3F,0x00,0x7F,0xF8,0x3F,0x00,0x7F,0xF8,0x3F,0x00,0x7F,0xF8,0x3F,0x00,0x7F,0xF8,0x1F,0x00,0x3F,0xF8,0x1F,0x00,0x01,0xF8,0x1F,0x00,0x01,0xF8,0x1F,0x80,0x01,0xF8,0x1F,0x80,0x01,0xF8,0x1F,0x80,0x01,0xF8,0x1F,0x80,0x01,0xF8,0x0F,0x80,0x01,0xF8,0x0F,0xC0,0x01,0xF8,0x0F,0xC0,0x01,0xF8,0x0F,0xC0,0x01,0xF8,0x07,0xE0,0x01,0xF8,0x07,0xE0,0x01,0xF8,0x03,0xF0,0x01,0xF8,0x03,0xF8,0x01,0xF8,0x01,0xFC,0x03,0xF8,0x01,0xFF,0xFF,0xF8,0x00,0xFF,0xFF,0xF0,0x00,0x7F,0xFF,0xE0,0x00,0x3F,0xFF,0xC0,0x00,0x0F,0xFF,0x00,0x00,0x03,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // G ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x00,0x01,0xF0,0x1F,0x80,0x01,0xF0,0x1F,0x80,0x01,0xF0,0x1F,0x80,0x01,0xF0,0x1F,0x80,0x01,0xF0,0x1F,0x80,0x01,0xF0,0x1F,0x80,0x01,0xF0,0x1F,0x80,0x01,0xF0,0x1F,0x80,0x01,0xF0,0x1F,0x80,0x01,0xF0,0x1F,0x80,0x01,0xF0,0x1F,0x80,0x01,0xF0,0x1F,0x80,0x01,0xF0,0x1F,0x80,0x01,0xF0,0x1F,0x80,0x01,0xF0,0x1F,0x80,0x01,0xF0,0x1F,0x80,0x01,0xF0,0x1F,0x80,0x01,0xF0,0x1F,0x80,0x01,0xF0,0x1F,0x80,0x01,0xF0,0x1F,0xFF,0xFF,0xF0,0x1F,0xFF,0xFF,0xF0,0x1F,0xFF,0xFF,0xF0,0x1F,0xFF,0xFF,0xF0,0x1F,0xFF,0xFF,0xF0,0x1F,0xFF,0xFF,0xF0,0x1F,0x80,0x01,0xF0,0x1F,0x80,0x01,0xF0,0x1F,0x80,0x01,0xF0,0x1F,0x80,0x01,0xF0,0x1F,0x80,0x01,0xF0,0x1F,0x80,0x01,0xF0,0x1F,0x80,0x01,0xF0,0x1F,0x80,0x01,0xF0,0x1F,0x80,0x01,0xF0,0x1F,0x80,0x01,0xF0,0x1F,0x80,0x01,0xF0,0x1F,0x80,0x01,0xF0,0x1F,0x80,0x01,0xF0,0x1F,0x80,0x01,0xF0,0x1F,0x80,0x01,0xF0,0x1F,0x80,0x01,0xF0,0x1F,0x80,0x01,0xF0,0x1F,0x80,0x01,0xF0,0x1F,0x80,0x01,0xF0,0x1F,0x80,0x01,0xF0,0x1F,0x80,0x01,0xF0,0x1F,0x80,0x01,0xF0,0x1F,0x80,0x01,0xF0,0x1F,0x80,0x01,0xF0,0x1F,0x80,0x01,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // H ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xFF,0xFF,0xC0,0x07,0xFF,0xFF,0xE0,0x07,0xFF,0xFF,0xE0,0x07,0xFF,0xFF,0xE0,0x07,0xFF,0xFF,0xE0,0x07,0xFF,0xFF,0xE0,0x00,0x07,0xE0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x07,0xFF,0xFF,0xC0,0x07,0xFF,0xFF,0xE0,0x07,0xFF,0xFF,0xE0,0x07,0xFF,0xFF,0xE0,0x07,0xFF,0xFF,0xE0,0x07,0xFF,0xFF,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // I ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0xFF,0x00,0x00,0x7F,0xFF,0x80,0x00,0x7F,0xFF,0x80,0x00,0x7F,0xFF,0x80,0x00,0x7F,0xFF,0x80,0x00,0x7F,0xFF,0x80,0x00,0x00,0x1F,0x80,0x00,0x00,0x1F,0x80,0x00,0x00,0x1F,0x80,0x00,0x00,0x1F,0x80,0x00,0x00,0x1F,0x80,0x00,0x00,0x1F,0x80,0x00,0x00,0x1F,0x80,0x00,0x00,0x1F,0x80,0x00,0x00,0x1F,0x80,0x00,0x00,0x1F,0x80,0x00,0x00,0x1F,0x80,0x00,0x00,0x1F,0x80,0x00,0x00,0x1F,0x80,0x00,0x00,0x1F,0x80,0x00,0x00,0x1F,0x80,0x00,0x00,0x1F,0x80,0x00,0x00,0x1F,0x80,0x00,0x00,0x1F,0x80,0x00,0x00,0x1F,0x80,0x00,0x00,0x1F,0x80,0x00,0x00,0x1F,0x80,0x00,0x00,0x1F,0x80,0x00,0x00,0x1F,0x80,0x00,0x00,0x1F,0x80,0x00,0x00,0x1F,0x80,0x00,0x00,0x1F,0x80,0x00,0x00,0x1F,0x80,0x00,0x00,0x1F,0x80,0x00,0x00,0x1F,0x80,0x00,0x00,0x1F,0x80,0x00,0x00,0x1F,0x80,0x00,0x00,0x1F,0x80,0x00,0x00,0x1F,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x1F,0x00,0x30,0x00,0x3F,0x00,0x38,0x00,0x3F,0x00,0x3E,0x00,0x7E,0x00,0x3F,0x00,0xFE,0x00,0x3F,0xFF,0xFE,0x00,0x3F,0xFF,0xFC,0x00,0x3F,0xFF,0xF8,0x00,0x1F,0xFF,0xF8,0x00,0x07,0xFF,0xE0,0x00,0x00,0xFF,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // J ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x00,0x00,0x7E,0x1F,0x80,0x00,0xFE,0x1F,0x80,0x01,0xFC,0x1F,0x80,0x01,0xF8,0x1F,0x80,0x03,0xF0,0x1F,0x80,0x07,0xF0,0x1F,0x80,0x0F,0xE0,0x1F,0x80,0x0F,0xC0,0x1F,0x80,0x1F,0x80,0x1F,0x80,0x3F,0x80,0x1F,0x80,0x3F,0x00,0x1F,0x80,0x7E,0x00,0x1F,0x80,0xFC,0x00,0x1F,0x81,0xFC,0x00,0x1F,0x81,0xF8,0x00,0x1F,0x83,0xF0,0x00,0x1F,0x87,0xE0,0x00,0x1F,0x8F,0xE0,0x00,0x1F,0x8F,0xC0,0x00,0x1F,0x9F,0x80,0x00,0x1F,0xBF,0x80,0x00,0x1F,0x3F,0x00,0x00,0x1F,0xFF,0x80,0x00,0x1F,0xFF,0x80,0x00,0x1F,0xFF,0xC0,0x00,0x1F,0xFF,0xC0,0x00,0x1F,0xF7,0xE0,0x00,0x1F,0xE7,0xE0,0x00,0x1F,0xE3,0xF0,0x00,0x1F,0xC3,0xF0,0x00,0x1F,0x81,0xF8,0x00,0x1F,0x81,0xF8,0x00,0x1F,0x80,0xFC,0x00,0x1F,0x80,0xFC,0x00,0x1F,0x80,0x7E,0x00,0x1F,0x80,0x7F,0x00,0x1F,0x80,0x3F,0x00,0x1F,0x80,0x3F,0x80,0x1F,0x80,0x1F,0x80,0x1F,0x80,0x1F,0xC0,0x1F,0x80,0x0F,0xC0,0x1F,0x80,0x0F,0xE0,0x1F,0x80,0x07,0xE0,0x1F,0x80,0x07,0xF0,0x1F,0x80,0x03,0xF0,0x1F,0x80,0x03,0xF8,0x1F,0x80,0x01,0xF8,0x1F,0x80,0x01,0xFC,0x1F,0x80,0x00,0xFC,0x1F,0x80,0x00,0xFE,0x1F,0x80,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // K ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xC0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xFF,0xFF,0xF8,0x07,0xFF,0xFF,0xF8,0x07,0xFF,0xFF,0xF8,0x07,0xFF,0xFF,0xF8,0x07,0xFF,0xFF,0xF8,0x07,0xFF,0xFF,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // L ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x07,0xF0,0x7F,0x00,0x07,0xF0,0x7F,0x80,0x0F,0xF0,0x7F,0x80,0x0F,0xF0,0x7F,0x80,0x0F,0xF0,0x7F,0x80,0x0F,0xF0,0x7F,0xC0,0x1F,0xF0,0x7F,0xC0,0x1F,0xF0,0x7F,0xC0,0x1F,0xF0,0x79,0xC0,0x3C,0xF0,0x79,0xE0,0x3C,0xF0,0x7D,0xE0,0x3D,0xF0,0x7D,0xE0,0x3D,0xF0,0x7D,0xF0,0x7D,0xF0,0x7C,0xF0,0x79,0xF0,0x7C,0xF0,0x79,0xF0,0x7C,0xF0,0x79,0xF0,0x7C,0x78,0xF9,0xF0,0x7C,0x78,0xF1,0xF0,0x7C,0x78,0xF1,0xF0,0x7C,0x78,0xF1,0xF0,0x7C,0x3D,0xE1,0xF0,0x7C,0x3D,0xE1,0xF0,0x7C,0x3D,0xE1,0xF0,0x7C,0x3F,0xE1,0xF0,0x7C,0x1F,0xC1,0xF0,0x7C,0x1F,0xC1,0xF0,0x7C,0x1F,0xC1,0xF0,0x7C,0x1F,0xC1,0xF0,0x7C,0x0F,0x81,0xF0,0x7C,0x0F,0x81,0xF0,0x7C,0x0F,0x81,0xF0,0x7C,0x00,0x01,0xF0,0x7C,0x00,0x01,0xF0,0x7C,0x00,0x01,0xF0,0x7C,0x00,0x01,0xF0,0x7C,0x00,0x01,0xF0,0x7C,0x00,0x01,0xF0,0x7C,0x00,0x01,0xF0,0x7C,0x00,0x01,0xF0,0x7C,0x00,0x01,0xF0,0x7C,0x00,0x01,0xF0,0x7C,0x00,0x01,0xF0,0x7C,0x00,0x01,0xF0,0x7C,0x00,0x01,0xF0,0x7C,0x00,0x01,0xF0,0x7C,0x00,0x01,0xF0,0x7C,0x00,0x01,0xF0,0x7C,0x00,0x01,0xF0,0x7C,0x00,0x01,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // M ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x01,0xF0,0xFF,0x00,0x01,0xF0,0xFF,0x80,0x01,0xF0,0xFF,0x80,0x01,0xF0,0xFF,0x80,0x01,0xF0,0xFF,0xC0,0x01,0xF0,0xFF,0xC0,0x01,0xF0,0xFF,0xC0,0x01,0xF0,0xFF,0xE0,0x01,0xF0,0xFF,0xE0,0x01,0xF0,0xFF,0xF0,0x01,0xF0,0xFD,0xF0,0x01,0xF0,0xFD,0xF0,0x01,0xF0,0xFD,0xF8,0x01,0xF0,0xFC,0xF8,0x01,0xF0,0xFC,0xF8,0x01,0xF0,0xFC,0x7C,0x01,0xF0,0xFC,0x7C,0x01,0xF0,0xFC,0x7E,0x01,0xF0,0xFC,0x3E,0x01,0xF0,0xFC,0x3E,0x01,0xF0,0xFC,0x3F,0x01,0xF0,0xFC,0x1F,0x01,0xF0,0xFC,0x1F,0x01,0xF0,0xFC,0x0F,0x81,0xF0,0xFC,0x0F,0x81,0xF0,0xFC,0x0F,0x81,0xF0,0xFC,0x07,0xC1,0xF0,0xFC,0x07,0xC1,0xF0,0xFC,0x07,0xE1,0xF0,0xFC,0x03,0xE1,0xF0,0xFC,0x03,0xE1,0xF0,0xFC,0x03,0xF1,0xF0,0xFC,0x01,0xF1,0xF0,0xFC,0x01,0xF1,0xF0,0xFC,0x00,0xF9,0xF0,0xFC,0x00,0xF9,0xF0,0xFC,0x00,0xF9,0xF0,0xFC,0x00,0x7D,0xF0,0xFC,0x00,0x7F,0xF0,0xFC,0x00,0x7F,0xF0,0xFC,0x00,0x3F,0xF0,0xFC,0x00,0x3F,0xF0,0xFC,0x00,0x1F,0xF0,0xFC,0x00,0x1F,0xF0,0xFC,0x00,0x1F,0xF0,0xFC,0x00,0x0F,0xF0,0xFC,0x00,0x0F,0xF0,0xFC,0x00,0x0F,0xF0,0xFC,0x00,0x07,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // N ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xC0,0x00,0x00,0x1F,0xF8,0x00,0x00,0x7F,0xFC,0x00,0x00,0xFF,0xFE,0x00,0x01,0xFF,0xFF,0x00,0x01,0xFF,0xFF,0x80,0x03,0xFC,0x3F,0x80,0x03,0xF0,0x1F,0xC0,0x07,0xE0,0x0F,0xC0,0x07,0xE0,0x07,0xE0,0x0F,0xC0,0x07,0xE0,0x0F,0xC0,0x03,0xE0,0x0F,0xC0,0x03,0xF0,0x0F,0x80,0x03,0xF0,0x0F,0x80,0x03,0xF0,0x1F,0x80,0x03,0xF0,0x1F,0x80,0x01,0xF0,0x1F,0x80,0x01,0xF0,0x1F,0x80,0x01,0xF8,0x1F,0x80,0x01,0xF8,0x1F,0x80,0x01,0xF8,0x1F,0x00,0x01,0xF8,0x1F,0x00,0x01,0xF8,0x1F,0x00,0x01,0xF8,0x1F,0x00,0x01,0xF8,0x1F,0x00,0x01,0xF8,0x1F,0x00,0x01,0xF8,0x1F,0x00,0x01,0xF8,0x1F,0x00,0x01,0xF8,0x1F,0x00,0x01,0xF8,0x1F,0x00,0x01,0xF8,0x1F,0x00,0x01,0xF8,0x1F,0x80,0x01,0xF8,0x1F,0x80,0x01,0xF8,0x1F,0x80,0x01,0xF8,0x1F,0x80,0x01,0xF0,0x1F,0x80,0x01,0xF0,0x1F,0x80,0x01,0xF0,0x1F,0x80,0x03,0xF0,0x0F,0x80,0x03,0xF0,0x0F,0x80,0x03,0xF0,0x0F,0xC0,0x03,0xE0,0x0F,0xC0,0x07,0xE0,0x07,0xC0,0x07,0xE0,0x07,0xE0,0x07,0xC0,0x07,0xF0,0x0F,0xC0,0x03,0xF8,0x1F,0xC0,0x03,0xFF,0xFF,0x80,0x01,0xFF,0xFF,0x00,0x00,0xFF,0xFF,0x00,0x00,0x7F,0xFE,0x00,0x00,0x3F,0xF8,0x00,0x00,0x0F,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // O ++ ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xFF,0xE0,0x00,0x07,0xFF,0xFC,0x00,0x07,0xFF,0xFF,0x00,0x07,0xFF,0xFF,0xC0,0x07,0xFF,0xFF,0xC0,0x07,0xFF,0xFF,0xE0,0x07,0xC0,0x1F,0xF0,0x07,0xC0,0x07,0xF0,0x07,0xC0,0x03,0xF8,0x07,0xC0,0x01,0xF8,0x07,0xC0,0x01,0xF8,0x07,0xC0,0x01,0xF8,0x07,0xC0,0x00,0xF8,0x07,0xC0,0x00,0xFC,0x07,0xC0,0x00,0xFC,0x07,0xC0,0x00,0xFC,0x07,0xC0,0x00,0xFC,0x07,0xC0,0x00,0xFC,0x07,0xC0,0x00,0xF8,0x07,0xC0,0x01,0xF8,0x07,0xC0,0x01,0xF8,0x07,0xC0,0x01,0xF8,0x07,0xC0,0x03,0xF8,0x07,0xC0,0x07,0xF0,0x07,0xC0,0x1F,0xF0,0x07,0xFF,0xFF,0xE0,0x07,0xFF,0xFF,0xE0,0x07,0xFF,0xFF,0xC0,0x07,0xFF,0xFF,0x80,0x07,0xFF,0xFE,0x00,0x07,0xFF,0xF0,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // P ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xE0,0x00,0x00,0x3F,0xF8,0x00,0x00,0x7F,0xFE,0x00,0x00,0xFF,0xFF,0x00,0x01,0xFF,0xFF,0x00,0x01,0xFF,0xFF,0x80,0x03,0xF8,0x3F,0xC0,0x07,0xF0,0x0F,0xC0,0x07,0xE0,0x0F,0xC0,0x07,0xC0,0x07,0xE0,0x0F,0xC0,0x07,0xE0,0x0F,0xC0,0x03,0xE0,0x0F,0x80,0x03,0xF0,0x0F,0x80,0x03,0xF0,0x1F,0x80,0x03,0xF0,0x1F,0x80,0x01,0xF0,0x1F,0x80,0x01,0xF0,0x1F,0x80,0x01,0xF0,0x1F,0x80,0x01,0xF8,0x1F,0x80,0x01,0xF8,0x1F,0x80,0x01,0xF8,0x1F,0x00,0x01,0xF8,0x1F,0x00,0x01,0xF8,0x1F,0x00,0x01,0xF8,0x1F,0x00,0x01,0xF8,0x1F,0x00,0x01,0xF8,0x1F,0x00,0x01,0xF8,0x1F,0x00,0x01,0xF8,0x1F,0x00,0x01,0xF8,0x1F,0x00,0x01,0xF8,0x1F,0x00,0x01,0xF8,0x1F,0x80,0x01,0xF8,0x1F,0x80,0x01,0xF8,0x1F,0x80,0x01,0xF8,0x1F,0x80,0x01,0xF0,0x1F,0x80,0x01,0xF0,0x1F,0x80,0x01,0xF0,0x1F,0x80,0x03,0xF0,0x0F,0x80,0x03,0xF0,0x0F,0x80,0x03,0xF0,0x0F,0xC0,0x03,0xE0,0x0F,0xC0,0x07,0xE0,0x07,0xC0,0x07,0xE0,0x07,0xE0,0x0F,0xC0,0x07,0xF0,0x0F,0xC0,0x03,0xF8,0x3F,0xC0,0x01,0xFF,0xFF,0x80,0x01,0xFF,0xFF,0x00,0x00,0xFF,0xFF,0x00,0x00,0x7F,0xFC,0x00,0x00,0x3F,0xFC,0x00,0x00,0x07,0xFE,0x00,0x00,0x00,0x7F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x1F,0x80,0x00,0x00,0x0F,0xC0,0x00,0x00,0x0F,0xE0,0x00,0x00,0x07,0xC0,0x00,0x00,0x03,0x80,0x00,0x00,0x02,0x00, // Q ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xFF,0x80,0x00,0x1F,0xFF,0xF0,0x00,0x1F,0xFF,0xFC,0x00,0x1F,0xFF,0xFF,0x00,0x1F,0xFF,0xFF,0x00,0x1F,0xFF,0xFF,0x80,0x1F,0x80,0x7F,0xC0,0x1F,0x80,0x1F,0xC0,0x1F,0x80,0x0F,0xE0,0x1F,0x80,0x07,0xE0,0x1F,0x80,0x07,0xE0,0x1F,0x80,0x07,0xE0,0x1F,0x80,0x03,0xF0,0x1F,0x80,0x03,0xF0,0x1F,0x80,0x03,0xF0,0x1F,0x80,0x03,0xF0,0x1F,0x80,0x03,0xF0,0x1F,0x80,0x03,0xF0,0x1F,0x80,0x03,0xE0,0x1F,0x80,0x07,0xE0,0x1F,0x80,0x07,0xE0,0x1F,0x80,0x0F,0xE0,0x1F,0x80,0x1F,0xC0,0x1F,0x80,0x3F,0x80,0x1F,0xFF,0xFF,0x80,0x1F,0xFF,0xFF,0x00,0x1F,0xFF,0xFC,0x00,0x1F,0xFF,0xF0,0x00,0x1F,0xFF,0xFC,0x00,0x1F,0xFF,0xFE,0x00,0x1F,0x80,0x7F,0x00,0x1F,0x80,0x3F,0x00,0x1F,0x80,0x1F,0x80,0x1F,0x80,0x1F,0x80,0x1F,0x80,0x0F,0xC0,0x1F,0x80,0x0F,0xC0,0x1F,0x80,0x07,0xC0,0x1F,0x80,0x07,0xE0,0x1F,0x80,0x03,0xE0,0x1F,0x80,0x03,0xF0,0x1F,0x80,0x03,0xF0,0x1F,0x80,0x01,0xF0,0x1F,0x80,0x01,0xF8,0x1F,0x80,0x01,0xF8,0x1F,0x80,0x00,0xF8,0x1F,0x80,0x00,0xFC,0x1F,0x80,0x00,0xFC,0x1F,0x80,0x00,0x7E,0x1F,0x80,0x00,0x7E,0x1F,0x80,0x00,0x3E,0x1F,0x80,0x00,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // R ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xC0,0x00,0x00,0x1F,0xFC,0x00,0x00,0x7F,0xFF,0x80,0x00,0xFF,0xFF,0xC0,0x01,0xFF,0xFF,0xC0,0x03,0xFF,0xFF,0xC0,0x07,0xFC,0x1F,0xC0,0x07,0xF0,0x03,0xC0,0x0F,0xC0,0x00,0xC0,0x0F,0xC0,0x00,0x40,0x0F,0x80,0x00,0x00,0x1F,0x80,0x00,0x00,0x1F,0x80,0x00,0x00,0x1F,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x1F,0x80,0x00,0x00,0x1F,0x80,0x00,0x00,0x1F,0x80,0x00,0x00,0x1F,0xC0,0x00,0x00,0x0F,0xE0,0x00,0x00,0x0F,0xF8,0x00,0x00,0x07,0xFE,0x00,0x00,0x07,0xFF,0xE0,0x00,0x03,0xFF,0xF8,0x00,0x01,0xFF,0xFE,0x00,0x00,0xFF,0xFF,0x00,0x00,0x7F,0xFF,0x80,0x00,0x0F,0xFF,0xC0,0x00,0x01,0xFF,0xC0,0x00,0x00,0x3F,0xE0,0x00,0x00,0x0F,0xE0,0x00,0x00,0x07,0xF0,0x00,0x00,0x03,0xF0,0x00,0x00,0x03,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x18,0x00,0x03,0xF0,0x0C,0x00,0x07,0xF0,0x0F,0x00,0x0F,0xE0,0x0F,0xC0,0x1F,0xE0,0x0F,0xFF,0xFF,0xC0,0x0F,0xFF,0xFF,0x80,0x0F,0xFF,0xFF,0x80,0x0F,0xFF,0xFF,0x00,0x01,0xFF,0xFC,0x00,0x00,0x3F,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // S ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0xFF,0xFF,0xFC,0x7F,0xFF,0xFF,0xFE,0x7F,0xFF,0xFF,0xFE,0x7F,0xFF,0xFF,0xFE,0x7F,0xFF,0xFF,0xFE,0x7F,0xFF,0xFF,0xFE,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // T ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x80,0x01,0xF0,0x0F,0x80,0x01,0xF0,0x0F,0x80,0x01,0xF0,0x0F,0x80,0x01,0xF0,0x0F,0x80,0x01,0xF0,0x0F,0x80,0x01,0xF0,0x0F,0x80,0x01,0xF0,0x0F,0x80,0x01,0xF0,0x0F,0x80,0x01,0xF0,0x0F,0x80,0x01,0xF0,0x0F,0x80,0x01,0xF0,0x0F,0x80,0x01,0xF0,0x0F,0x80,0x01,0xF0,0x0F,0x80,0x01,0xF0,0x0F,0x80,0x01,0xF0,0x0F,0x80,0x01,0xF0,0x0F,0x80,0x01,0xF0,0x0F,0x80,0x01,0xF0,0x0F,0x80,0x01,0xF0,0x0F,0x80,0x01,0xF0,0x0F,0x80,0x01,0xF0,0x0F,0x80,0x01,0xF0,0x0F,0x80,0x01,0xF0,0x0F,0x80,0x01,0xF0,0x0F,0x80,0x01,0xF0,0x0F,0x80,0x01,0xF0,0x0F,0x80,0x01,0xF0,0x0F,0x80,0x01,0xF0,0x0F,0x80,0x01,0xF0,0x0F,0x80,0x01,0xF0,0x0F,0x80,0x01,0xF0,0x0F,0x80,0x01,0xF0,0x0F,0x80,0x01,0xF0,0x0F,0x80,0x01,0xF0,0x0F,0x80,0x01,0xF0,0x0F,0x80,0x01,0xF0,0x0F,0x80,0x01,0xF0,0x0F,0x80,0x01,0xF0,0x0F,0x80,0x01,0xF0,0x0F,0x80,0x01,0xF0,0x0F,0x80,0x01,0xF0,0x0F,0x80,0x01,0xF0,0x0F,0xC0,0x03,0xF0,0x07,0xC0,0x03,0xE0,0x07,0xE0,0x07,0xE0,0x07,0xF0,0x0F,0xE0,0x03,0xFF,0xFF,0xC0,0x01,0xFF,0xFF,0x80,0x01,0xFF,0xFF,0x80,0x00,0xFF,0xFF,0x00,0x00,0x3F,0xFC,0x00,0x00,0x0F,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // U ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x00,0x7C,0x7E,0x00,0x00,0x7C,0x3E,0x00,0x00,0x7C,0x3F,0x00,0x00,0xFC,0x3F,0x00,0x00,0xFC,0x1F,0x00,0x00,0xF8,0x1F,0x00,0x00,0xF8,0x1F,0x00,0x00,0xF8,0x1F,0x80,0x01,0xF8,0x1F,0x80,0x01,0xF8,0x0F,0x80,0x01,0xF0,0x0F,0x80,0x01,0xF0,0x0F,0xC0,0x03,0xF0,0x0F,0xC0,0x03,0xF0,0x0F,0xC0,0x03,0xF0,0x07,0xC0,0x03,0xE0,0x07,0xC0,0x03,0xE0,0x07,0xE0,0x07,0xE0,0x07,0xE0,0x07,0xE0,0x03,0xE0,0x07,0xC0,0x03,0xE0,0x07,0xC0,0x03,0xE0,0x07,0xC0,0x03,0xF0,0x0F,0xC0,0x01,0xF0,0x0F,0x80,0x01,0xF0,0x0F,0x80,0x01,0xF0,0x0F,0x80,0x01,0xF0,0x0F,0x80,0x01,0xF8,0x1F,0x80,0x00,0xF8,0x1F,0x00,0x00,0xF8,0x1F,0x00,0x00,0xF8,0x1F,0x00,0x00,0xF8,0x1F,0x00,0x00,0x7C,0x3E,0x00,0x00,0x7C,0x3E,0x00,0x00,0x7C,0x3E,0x00,0x00,0x7C,0x3E,0x00,0x00,0x7C,0x3E,0x00,0x00,0x3E,0x7C,0x00,0x00,0x3E,0x7C,0x00,0x00,0x3E,0x7C,0x00,0x00,0x3E,0x7C,0x00,0x00,0x1E,0x78,0x00,0x00,0x1E,0x78,0x00,0x00,0x1F,0xF8,0x00,0x00,0x1F,0xF8,0x00,0x00,0x1F,0xF8,0x00,0x00,0x0F,0xF0,0x00,0x00,0x0F,0xF0,0x00,0x00,0x0F,0xF0,0x00,0x00,0x0F,0xF0,0x00,0x00,0x07,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // V ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x00,0x00,0x1F,0xF8,0x00,0x00,0x1F,0xF8,0x00,0x00,0x1F,0xFC,0x00,0x00,0x3F,0xFC,0x00,0x00,0x3F,0xFC,0x00,0x00,0x3F,0x7C,0x00,0x00,0x3E,0x7C,0x00,0x00,0x3E,0x7C,0x00,0x00,0x3E,0x7C,0x00,0x00,0x3E,0x7C,0x00,0x00,0x3E,0x7C,0x00,0x00,0x3E,0x7C,0x00,0x00,0x3E,0x7C,0x00,0x00,0x3E,0x7E,0x07,0xE0,0x7E,0x3E,0x07,0xE0,0x7C,0x3E,0x07,0xE0,0x7C,0x3E,0x07,0xE0,0x7C,0x3E,0x0F,0xF0,0x7C,0x3E,0x0F,0xF0,0x7C,0x3E,0x0F,0xF0,0x7C,0x3E,0x0F,0xF0,0x7C,0x3E,0x0F,0xF0,0x7C,0x3E,0x0E,0x70,0x7C,0x1E,0x1E,0x78,0x78,0x1F,0x1E,0x78,0xF8,0x1F,0x1E,0x78,0xF8,0x1F,0x1E,0x78,0xF8,0x1F,0x1E,0x78,0xF8,0x1F,0x1E,0x78,0xF8,0x1F,0x3C,0x3C,0xF8,0x1F,0x3C,0x3C,0xF8,0x0F,0x3C,0x3C,0xF0,0x0F,0x3C,0x3C,0xF0,0x0F,0x3C,0x3C,0xF0,0x0F,0x3C,0x3C,0xF0,0x0F,0x38,0x1C,0xF0,0x0F,0x38,0x1C,0xF0,0x0F,0x78,0x1E,0xF0,0x0F,0xF8,0x1F,0xF0,0x0F,0xF8,0x1F,0xF0,0x07,0xF8,0x1F,0xE0,0x07,0xF0,0x0F,0xE0,0x07,0xF0,0x0F,0xE0,0x07,0xF0,0x0F,0xE0,0x07,0xF0,0x0F,0xE0,0x07,0xF0,0x0F,0xE0,0x07,0xF0,0x0F,0xE0,0x07,0xE0,0x07,0xE0,0x07,0xE0,0x07,0xE0,0x03,0xE0,0x07,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // W ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x00,0x7C,0x3F,0x00,0x00,0x7E,0x1F,0x80,0x00,0xFC,0x0F,0x80,0x00,0xF8,0x0F,0xC0,0x01,0xF8,0x07,0xC0,0x01,0xF0,0x07,0xE0,0x03,0xF0,0x07,0xE0,0x03,0xE0,0x03,0xF0,0x07,0xE0,0x03,0xF0,0x07,0xC0,0x01,0xF0,0x0F,0xC0,0x01,0xF8,0x0F,0x80,0x00,0xF8,0x0F,0x80,0x00,0xFC,0x1F,0x00,0x00,0x7C,0x1F,0x00,0x00,0x7E,0x3E,0x00,0x00,0x3E,0x3E,0x00,0x00,0x3F,0x7C,0x00,0x00,0x1F,0x7C,0x00,0x00,0x1F,0xFC,0x00,0x00,0x0F,0xF8,0x00,0x00,0x0F,0xF8,0x00,0x00,0x07,0xF0,0x00,0x00,0x07,0xF0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xF0,0x00,0x00,0x0F,0xF0,0x00,0x00,0x0F,0xF8,0x00,0x00,0x1F,0xF8,0x00,0x00,0x1F,0xFC,0x00,0x00,0x3F,0x7C,0x00,0x00,0x3E,0x7E,0x00,0x00,0x7E,0x3E,0x00,0x00,0x7C,0x3E,0x00,0x00,0xFC,0x1F,0x00,0x00,0xFC,0x1F,0x00,0x01,0xF8,0x1F,0x80,0x01,0xF8,0x0F,0x80,0x03,0xF0,0x0F,0xC0,0x03,0xF0,0x07,0xC0,0x03,0xE0,0x07,0xE0,0x07,0xE0,0x03,0xE0,0x07,0xC0,0x03,0xF0,0x0F,0xC0,0x01,0xF0,0x0F,0x80,0x01,0xF8,0x1F,0x80,0x01,0xF8,0x1F,0x00,0x00,0xFC,0x3F,0x00,0x00,0xFC,0x3E,0x00,0x00,0x7C,0x7E,0x00,0x00,0x7E,0x7C,0x00,0x00,0x3E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // X ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x00,0x3E,0x7E,0x00,0x00,0x7E,0x3E,0x00,0x00,0xFC,0x3F,0x00,0x00,0xFC,0x3F,0x00,0x00,0xF8,0x1F,0x80,0x01,0xF8,0x1F,0x80,0x01,0xF0,0x0F,0x80,0x03,0xF0,0x0F,0xC0,0x03,0xF0,0x07,0xC0,0x07,0xE0,0x07,0xE0,0x07,0xE0,0x03,0xE0,0x07,0xC0,0x03,0xF0,0x0F,0xC0,0x03,0xF0,0x0F,0x80,0x01,0xF0,0x1F,0x80,0x01,0xF8,0x1F,0x00,0x00,0xF8,0x3F,0x00,0x00,0xFC,0x3E,0x00,0x00,0x7C,0x3E,0x00,0x00,0x7E,0x7E,0x00,0x00,0x3E,0x7C,0x00,0x00,0x3E,0x7C,0x00,0x00,0x1F,0xF8,0x00,0x00,0x1F,0xF8,0x00,0x00,0x1F,0xF0,0x00,0x00,0x0F,0xF0,0x00,0x00,0x0F,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // Y ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xFF,0xFF,0xF8,0x0F,0xFF,0xFF,0xFC,0x0F,0xFF,0xFF,0xFC,0x0F,0xFF,0xFF,0xFC,0x0F,0xFF,0xFF,0xFC,0x0F,0xFF,0xFF,0xFC,0x00,0x00,0x01,0xFC,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF0,0x00,0x00,0x03,0xF0,0x00,0x00,0x03,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xC0,0x00,0x00,0x0F,0xC0,0x00,0x00,0x0F,0x80,0x00,0x00,0x1F,0x80,0x00,0x00,0x1F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3E,0x00,0x00,0x00,0x7E,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0xFC,0x00,0x00,0x00,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF0,0x00,0x00,0x03,0xF0,0x00,0x00,0x03,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xC0,0x00,0x00,0x0F,0xC0,0x00,0x00,0x0F,0x80,0x00,0x00,0x1F,0x80,0x00,0x00,0x1F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3E,0x00,0x00,0x00,0x7E,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0xF8,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x0F,0xFF,0xFF,0xFC,0x0F,0xFF,0xFF,0xFC,0x0F,0xFF,0xFF,0xFC,0x0F,0xFF,0xFF,0xFC,0x0F,0xFF,0xFF,0xFC,0x0F,0xFF,0xFF,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // Z ++0x00,0x01,0xFF,0xC0,0x00,0x01,0xFF,0xC0,0x00,0x01,0xFF,0xC0,0x00,0x01,0xFF,0xC0,0x00,0x01,0xFF,0x80,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xFF,0x80,0x00,0x01,0xFF,0xC0,0x00,0x01,0xFF,0xC0,0x00,0x01,0xFF,0xC0,0x00,0x01,0xFF,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // [ ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x1F,0x80,0x00,0x00,0x0F,0x80,0x00,0x00,0x0F,0xC0,0x00,0x00,0x0F,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0xFC,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x7E,0x00,0x00,0x00,0x3E,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x1F,0x80,0x00,0x00,0x0F,0x80,0x00,0x00,0x0F,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF8,0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0xFC,0x00,0x00,0x00,0xFC,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x7E,0x00,0x00,0x00,0x3E,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x1F,0x80,0x00,0x00,0x1F,0x80,0x00,0x00,0x0F,0x80,0x00,0x00,0x0F,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xF0,0x00,0x00,0x03,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ++0x00,0xFF,0xE0,0x00,0x00,0xFF,0xE0,0x00,0x00,0xFF,0xE0,0x00,0x00,0xFF,0xE0,0x00,0x00,0xFF,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0xFF,0xE0,0x00,0x00,0xFF,0xE0,0x00,0x00,0xFF,0xE0,0x00,0x00,0xFF,0xE0,0x00,0x00,0xFF,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ] ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x0F,0xF0,0x00,0x00,0x1F,0xF8,0x00,0x00,0x1F,0xF8,0x00,0x00,0x3F,0xFC,0x00,0x00,0x7F,0xFE,0x00,0x00,0x7E,0x7E,0x00,0x00,0xFE,0x7F,0x00,0x00,0xFC,0x3F,0x80,0x01,0xF8,0x1F,0x80,0x03,0xF8,0x1F,0xC0,0x03,0xF0,0x0F,0xC0,0x07,0xE0,0x07,0xE0,0x0F,0xE0,0x03,0xF0,0x0F,0xC0,0x03,0xF0,0x1F,0x80,0x01,0xF8,0x3F,0x00,0x00,0xFC,0x3F,0x00,0x00,0xFC,0x7E,0x00,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ^ ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // _ ++ ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x03,0xF0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x0F,0xE0,0x00,0x00,0x0F,0xC0,0x00,0x00,0x1F,0xC0,0x00,0x00,0x1F,0xC0,0x00,0x00,0x1F,0xC0,0x00,0x00,0x1F,0xC0,0x00,0x00,0x1F,0xC0,0x00,0x00,0x1F,0xC0,0x00,0x00,0x1F,0xC0,0x00,0x00,0x0F,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ` ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0xE0,0x00,0x00,0xFF,0xF8,0x00,0x03,0xFF,0xFE,0x00,0x07,0xFF,0xFF,0x00,0x07,0xFF,0xFF,0x00,0x07,0xFF,0xFF,0x80,0x07,0xC0,0x1F,0xC0,0x07,0x00,0x0F,0xC0,0x04,0x00,0x07,0xC0,0x00,0x00,0x07,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x1F,0xFF,0xE0,0x00,0xFF,0xFF,0xE0,0x01,0xFF,0xFF,0xE0,0x03,0xFF,0xFF,0xE0,0x07,0xFF,0xFF,0xE0,0x07,0xF0,0x03,0xE0,0x0F,0xC0,0x03,0xE0,0x0F,0x80,0x03,0xE0,0x1F,0x80,0x03,0xE0,0x1F,0x00,0x03,0xE0,0x1F,0x00,0x03,0xE0,0x1F,0x00,0x03,0xE0,0x1F,0x00,0x07,0xE0,0x1F,0x00,0x07,0xE0,0x1F,0x00,0x07,0xE0,0x1F,0x00,0x0F,0xE0,0x1F,0x80,0x0F,0xE0,0x1F,0x80,0x1F,0xE0,0x0F,0xC0,0x3F,0xE0,0x0F,0xF9,0xFF,0xE0,0x07,0xFF,0xFB,0xE0,0x07,0xFF,0xF3,0xE0,0x03,0xFF,0xF3,0xE0,0x01,0xFF,0xC3,0xE0,0x00,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // a ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x80,0x00,0x00,0x0F,0x80,0x00,0x00,0x0F,0x80,0x00,0x00,0x0F,0x80,0x00,0x00,0x0F,0x80,0x00,0x00,0x0F,0x80,0x00,0x00,0x0F,0x80,0x00,0x00,0x0F,0x80,0x00,0x00,0x0F,0x80,0x00,0x00,0x0F,0x80,0x00,0x00,0x0F,0x80,0x00,0x00,0x0F,0x80,0x00,0x00,0x0F,0x80,0x00,0x00,0x0F,0x80,0x00,0x00,0x0F,0x81,0xF0,0x00,0x0F,0x87,0xFC,0x00,0x0F,0x9F,0xFE,0x00,0x0F,0x9F,0xFF,0x00,0x0F,0xBF,0xFF,0x80,0x0F,0xFF,0xFF,0xC0,0x0F,0xF8,0x1F,0xC0,0x0F,0xF0,0x0F,0xE0,0x0F,0xF0,0x07,0xE0,0x0F,0xE0,0x03,0xE0,0x0F,0xE0,0x03,0xF0,0x0F,0xC0,0x03,0xF0,0x0F,0xC0,0x01,0xF0,0x0F,0xC0,0x01,0xF0,0x0F,0xC0,0x01,0xF0,0x0F,0xC0,0x01,0xF0,0x0F,0xC0,0x01,0xF8,0x0F,0x80,0x01,0xF8,0x0F,0x80,0x01,0xF8,0x0F,0x80,0x01,0xF8,0x0F,0x80,0x01,0xF8,0x0F,0x80,0x01,0xF8,0x0F,0x80,0x01,0xF8,0x0F,0x80,0x01,0xF8,0x0F,0xC0,0x01,0xF0,0x0F,0xC0,0x01,0xF0,0x0F,0xC0,0x01,0xF0,0x0F,0xC0,0x01,0xF0,0x0F,0xC0,0x03,0xF0,0x0F,0xE0,0x03,0xF0,0x0F,0xE0,0x03,0xE0,0x0F,0xE0,0x07,0xE0,0x0F,0xF0,0x07,0xE0,0x0F,0xF8,0x0F,0xC0,0x0F,0xFE,0x3F,0xC0,0x0F,0xFF,0xFF,0x80,0x0F,0x9F,0xFF,0x00,0x0F,0x9F,0xFF,0x00,0x0F,0x8F,0xFC,0x00,0x00,0x03,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // b ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xFC,0x00,0x00,0x07,0xFF,0x80,0x00,0x1F,0xFF,0xC0,0x00,0x3F,0xFF,0xE0,0x00,0x7F,0xFF,0xE0,0x00,0xFF,0xFF,0xE0,0x00,0xFE,0x01,0xE0,0x01,0xFC,0x00,0xE0,0x01,0xF8,0x00,0x20,0x03,0xF0,0x00,0x00,0x03,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x0F,0xC0,0x00,0x00,0x0F,0xC0,0x00,0x00,0x0F,0xC0,0x00,0x00,0x0F,0xC0,0x00,0x00,0x0F,0xC0,0x00,0x00,0x0F,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xF0,0x00,0x00,0x03,0xF0,0x00,0x20,0x01,0xF8,0x00,0x60,0x01,0xFE,0x01,0xE0,0x00,0xFF,0x8F,0xE0,0x00,0x7F,0xFF,0xE0,0x00,0x3F,0xFF,0xE0,0x00,0x1F,0xFF,0xE0,0x00,0x0F,0xFF,0x80,0x00,0x03,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // c ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x0F,0x83,0xE0,0x00,0x3F,0xE3,0xE0,0x00,0xFF,0xF3,0xE0,0x01,0xFF,0xFB,0xE0,0x01,0xFF,0xFB,0xE0,0x03,0xFF,0xFF,0xE0,0x07,0xF0,0x3F,0xE0,0x07,0xE0,0x1F,0xE0,0x07,0xC0,0x0F,0xE0,0x0F,0xC0,0x0F,0xE0,0x0F,0x80,0x07,0xE0,0x0F,0x80,0x07,0xE0,0x1F,0x80,0x07,0xE0,0x1F,0x80,0x03,0xE0,0x1F,0x00,0x03,0xE0,0x1F,0x00,0x03,0xE0,0x1F,0x00,0x03,0xE0,0x1F,0x00,0x03,0xE0,0x1F,0x00,0x03,0xE0,0x1F,0x00,0x03,0xE0,0x1F,0x00,0x03,0xE0,0x1F,0x00,0x03,0xE0,0x1F,0x00,0x03,0xE0,0x1F,0x00,0x03,0xE0,0x1F,0x00,0x03,0xE0,0x1F,0x00,0x03,0xE0,0x1F,0x80,0x03,0xE0,0x1F,0x80,0x07,0xE0,0x0F,0x80,0x07,0xE0,0x0F,0x80,0x07,0xE0,0x0F,0xC0,0x07,0xE0,0x0F,0xC0,0x0F,0xE0,0x07,0xE0,0x1F,0xE0,0x07,0xF0,0x3F,0xE0,0x03,0xFC,0xFF,0xE0,0x03,0xFF,0xFF,0xE0,0x01,0xFF,0xFB,0xE0,0x00,0xFF,0xF3,0xE0,0x00,0x7F,0xE3,0xE0,0x00,0x1F,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // d ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xF0,0x00,0x00,0x1F,0xFC,0x00,0x00,0x3F,0xFE,0x00,0x00,0xFF,0xFF,0x00,0x00,0xFF,0xFF,0x80,0x01,0xFF,0xFF,0xC0,0x03,0xF8,0x0F,0xC0,0x03,0xF0,0x07,0xE0,0x07,0xE0,0x03,0xE0,0x07,0xC0,0x01,0xF0,0x0F,0xC0,0x01,0xF0,0x0F,0x80,0x01,0xF0,0x0F,0x80,0x00,0xF8,0x1F,0x80,0x00,0xF8,0x1F,0x80,0x00,0xF8,0x1F,0xFF,0xFF,0xF8,0x1F,0xFF,0xFF,0xF8,0x1F,0xFF,0xFF,0xF8,0x1F,0xFF,0xFF,0xF8,0x1F,0xFF,0xFF,0xF8,0x1F,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x1F,0x80,0x00,0x00,0x1F,0x80,0x00,0x00,0x1F,0x80,0x00,0x00,0x0F,0x80,0x00,0x00,0x0F,0x80,0x00,0x00,0x0F,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xE0,0x00,0x30,0x07,0xF0,0x00,0x70,0x03,0xF8,0x01,0xF0,0x01,0xFF,0x1F,0xF0,0x01,0xFF,0xFF,0xF0,0x00,0xFF,0xFF,0xF0,0x00,0x7F,0xFF,0xE0,0x00,0x1F,0xFF,0x80,0x00,0x07,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // e ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xE0,0x00,0x00,0x7F,0xE0,0x00,0x01,0xFF,0xE0,0x00,0x01,0xFF,0xE0,0x00,0x03,0xFF,0xE0,0x00,0x07,0xFF,0xE0,0x00,0x07,0xE0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x0F,0x80,0x00,0x00,0x0F,0x80,0x00,0x00,0x0F,0x80,0x00,0x00,0x0F,0x80,0x00,0x00,0x0F,0x80,0x00,0x07,0xFF,0xFF,0xE0,0x07,0xFF,0xFF,0xE0,0x07,0xFF,0xFF,0xE0,0x07,0xFF,0xFF,0xE0,0x07,0xFF,0xFF,0xE0,0x00,0x0F,0x80,0x00,0x00,0x0F,0x80,0x00,0x00,0x0F,0x80,0x00,0x00,0x0F,0x80,0x00,0x00,0x0F,0x80,0x00,0x00,0x0F,0x80,0x00,0x00,0x0F,0x80,0x00,0x00,0x0F,0x80,0x00,0x00,0x0F,0x80,0x00,0x00,0x0F,0x80,0x00,0x00,0x0F,0x80,0x00,0x00,0x0F,0x80,0x00,0x00,0x0F,0x80,0x00,0x00,0x0F,0x80,0x00,0x00,0x0F,0x80,0x00,0x00,0x0F,0x80,0x00,0x00,0x0F,0x80,0x00,0x00,0x0F,0x80,0x00,0x00,0x0F,0x80,0x00,0x00,0x0F,0x80,0x00,0x00,0x0F,0x80,0x00,0x00,0x0F,0x80,0x00,0x00,0x0F,0x80,0x00,0x00,0x0F,0x80,0x00,0x00,0x0F,0x80,0x00,0x00,0x0F,0x80,0x00,0x00,0x0F,0x80,0x00,0x00,0x0F,0x80,0x00,0x00,0x0F,0x80,0x00,0x00,0x0F,0x80,0x00,0x00,0x0F,0x80,0x00,0x00,0x0F,0x80,0x00,0x00,0x0F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // f ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x80,0x00,0x00,0x7F,0xE3,0xE0,0x00,0xFF,0xF3,0xE0,0x01,0xFF,0xFB,0xE0,0x03,0xFF,0xFF,0xE0,0x03,0xF8,0x3F,0xE0,0x07,0xE0,0x1F,0xE0,0x07,0xC0,0x0F,0xE0,0x0F,0xC0,0x07,0xE0,0x0F,0x80,0x07,0xE0,0x0F,0x80,0x07,0xE0,0x1F,0x80,0x03,0xE0,0x1F,0x00,0x03,0xE0,0x1F,0x00,0x03,0xE0,0x1F,0x00,0x03,0xE0,0x1F,0x00,0x03,0xE0,0x1F,0x00,0x03,0xE0,0x1F,0x00,0x03,0xE0,0x1F,0x00,0x03,0xE0,0x1F,0x00,0x03,0xE0,0x1F,0x00,0x03,0xE0,0x1F,0x00,0x03,0xE0,0x1F,0x80,0x03,0xE0,0x1F,0x80,0x03,0xE0,0x0F,0x80,0x07,0xE0,0x0F,0x80,0x07,0xE0,0x0F,0xC0,0x07,0xE0,0x07,0xE0,0x0F,0xE0,0x07,0xF0,0x1F,0xE0,0x03,0xF8,0x7F,0xE0,0x03,0xFF,0xFB,0xE0,0x01,0xFF,0xFB,0xE0,0x00,0xFF,0xF3,0xE0,0x00,0x3F,0xE3,0xE0,0x00,0x07,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x03,0x00,0x0F,0xC0,0x03,0xC0,0x1F,0x80,0x03,0xFF,0xFF,0x00,0x03,0xFF,0xFF,0x00,0x03,0xFF,0xFE,0x00,0x01,0xFF,0xF8,0x00,0x00,0x1F,0xC0,0x00, // g ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x80,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC1,0xF8,0x00,0x07,0xC7,0xFE,0x00,0x07,0xCF,0xFF,0x00,0x07,0xDF,0xFF,0x80,0x07,0x9F,0xFF,0x80,0x07,0xFF,0xFF,0xC0,0x07,0xFC,0x1F,0xC0,0x07,0xF8,0x0F,0xC0,0x07,0xF0,0x07,0xE0,0x07,0xE0,0x07,0xE0,0x07,0xE0,0x03,0xE0,0x07,0xC0,0x03,0xE0,0x07,0xC0,0x03,0xE0,0x07,0xC0,0x03,0xE0,0x07,0xC0,0x03,0xE0,0x07,0xC0,0x03,0xE0,0x07,0xC0,0x03,0xE0,0x07,0xC0,0x03,0xE0,0x07,0xC0,0x03,0xE0,0x07,0xC0,0x03,0xE0,0x07,0xC0,0x03,0xE0,0x07,0xC0,0x03,0xE0,0x07,0xC0,0x03,0xE0,0x07,0xC0,0x03,0xE0,0x07,0xC0,0x03,0xE0,0x07,0xC0,0x03,0xE0,0x07,0xC0,0x03,0xE0,0x07,0xC0,0x03,0xE0,0x07,0xC0,0x03,0xE0,0x07,0xC0,0x03,0xE0,0x07,0xC0,0x03,0xE0,0x07,0xC0,0x03,0xE0,0x07,0xC0,0x03,0xE0,0x07,0xC0,0x03,0xE0,0x07,0xC0,0x03,0xE0,0x07,0xC0,0x03,0xE0,0x07,0xC0,0x03,0xE0,0x07,0xC0,0x03,0xE0,0x07,0xC0,0x03,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // h ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xF0,0x00,0x00,0xFF,0xF0,0x00,0x00,0xFF,0xF0,0x00,0x00,0xFF,0xF0,0x00,0x00,0xFF,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x03,0xFF,0xFF,0xFC,0x03,0xFF,0xFF,0xFC,0x03,0xFF,0xFF,0xFC,0x03,0xFF,0xFF,0xFC,0x03,0xFF,0xFF,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // i ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xFF,0xF0,0x00,0x01,0xFF,0xF0,0x00,0x01,0xFF,0xF0,0x00,0x01,0xFF,0xF0,0x00,0x01,0xFF,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x03,0xF0,0x00,0x00,0x03,0xE0,0x00,0x00,0x07,0xE0,0x00,0x07,0xFF,0xC0,0x00,0x0F,0xFF,0xC0,0x00,0x0F,0xFF,0x80,0x00,0x0F,0xFF,0x00,0x00,0x07,0xFC,0x00,0x00, // j ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xC0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x01,0xF8,0x03,0xE0,0x03,0xF0,0x03,0xE0,0x07,0xF0,0x03,0xE0,0x07,0xE0,0x03,0xE0,0x0F,0xC0,0x03,0xE0,0x1F,0x80,0x03,0xE0,0x3F,0x00,0x03,0xE0,0x7E,0x00,0x03,0xE0,0x7E,0x00,0x03,0xE0,0xFC,0x00,0x03,0xE1,0xF8,0x00,0x03,0xE3,0xF0,0x00,0x03,0xE7,0xE0,0x00,0x03,0xE7,0xE0,0x00,0x03,0xEF,0xC0,0x00,0x03,0xFF,0xC0,0x00,0x03,0xFF,0xE0,0x00,0x03,0xFF,0xE0,0x00,0x03,0xFF,0xF0,0x00,0x03,0xF9,0xF8,0x00,0x03,0xF9,0xF8,0x00,0x03,0xF0,0xFC,0x00,0x03,0xE0,0xFC,0x00,0x03,0xE0,0x7E,0x00,0x03,0xE0,0x3E,0x00,0x03,0xE0,0x3F,0x00,0x03,0xE0,0x1F,0x80,0x03,0xE0,0x1F,0x80,0x03,0xE0,0x0F,0xC0,0x03,0xE0,0x0F,0xC0,0x03,0xE0,0x07,0xE0,0x03,0xE0,0x07,0xE0,0x03,0xE0,0x03,0xF0,0x03,0xE0,0x01,0xF8,0x03,0xE0,0x01,0xF8,0x03,0xE0,0x00,0xFC,0x03,0xE0,0x00,0xFC,0x03,0xE0,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // k ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xFF,0xC0,0x00,0x03,0xFF,0xE0,0x00,0x03,0xFF,0xE0,0x00,0x03,0xFF,0xE0,0x00,0x03,0xFF,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xF0,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xFC,0x00,0x00,0x01,0xFF,0xF8,0x00,0x00,0xFF,0xF8,0x00,0x00,0x7F,0xF8,0x00,0x00,0x3F,0xF8,0x00,0x00,0x0F,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // l ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3C,0x07,0x80,0x1E,0x7E,0x1F,0xC0,0x3E,0xFF,0x3F,0xE0,0x3F,0xFF,0xBF,0xF0,0x3F,0xFF,0xFF,0xF0,0x3F,0xFF,0xFF,0xF0,0x3F,0x0F,0xF0,0xF8,0x3F,0x07,0xE0,0xF8,0x3E,0x07,0xE0,0xF8,0x3E,0x07,0xC0,0x78,0x3E,0x07,0xC0,0x78,0x3E,0x07,0xC0,0x78,0x3E,0x03,0xC0,0x78,0x3E,0x03,0xC0,0x78,0x3E,0x03,0xC0,0x78,0x3E,0x03,0xC0,0x78,0x3E,0x03,0xC0,0x78,0x3E,0x03,0xC0,0x78,0x3E,0x03,0xC0,0x78,0x3E,0x03,0xC0,0x78,0x3E,0x03,0xC0,0x78,0x3E,0x03,0xC0,0x78,0x3E,0x03,0xC0,0x78,0x3E,0x03,0xC0,0x78,0x3E,0x03,0xC0,0x78,0x3E,0x03,0xC0,0x78,0x3E,0x03,0xC0,0x78,0x3E,0x03,0xC0,0x78,0x3E,0x03,0xC0,0x78,0x3E,0x03,0xC0,0x78,0x3E,0x03,0xC0,0x78,0x3E,0x03,0xC0,0x78,0x3E,0x03,0xC0,0x78,0x3E,0x03,0xC0,0x78,0x3E,0x03,0xC0,0x78,0x3E,0x03,0xC0,0x78,0x3E,0x03,0xC0,0x78,0x3E,0x03,0xC0,0x78,0x3E,0x03,0xC0,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // m ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xF8,0x00,0x07,0x87,0xFE,0x00,0x07,0xCF,0xFF,0x00,0x07,0xDF,0xFF,0x80,0x07,0x9F,0xFF,0x80,0x07,0xFF,0xFF,0xC0,0x07,0xFC,0x1F,0xC0,0x07,0xF8,0x0F,0xC0,0x07,0xF0,0x07,0xE0,0x07,0xE0,0x07,0xE0,0x07,0xE0,0x03,0xE0,0x07,0xC0,0x03,0xE0,0x07,0xC0,0x03,0xE0,0x07,0xC0,0x03,0xE0,0x07,0xC0,0x03,0xE0,0x07,0xC0,0x03,0xE0,0x07,0xC0,0x03,0xE0,0x07,0xC0,0x03,0xE0,0x07,0xC0,0x03,0xE0,0x07,0xC0,0x03,0xE0,0x07,0xC0,0x03,0xE0,0x07,0xC0,0x03,0xE0,0x07,0xC0,0x03,0xE0,0x07,0xC0,0x03,0xE0,0x07,0xC0,0x03,0xE0,0x07,0xC0,0x03,0xE0,0x07,0xC0,0x03,0xE0,0x07,0xC0,0x03,0xE0,0x07,0xC0,0x03,0xE0,0x07,0xC0,0x03,0xE0,0x07,0xC0,0x03,0xE0,0x07,0xC0,0x03,0xE0,0x07,0xC0,0x03,0xE0,0x07,0xC0,0x03,0xE0,0x07,0xC0,0x03,0xE0,0x07,0xC0,0x03,0xE0,0x07,0xC0,0x03,0xE0,0x07,0xC0,0x03,0xE0,0x07,0xC0,0x03,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // n ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xE0,0x00,0x00,0x3F,0xF8,0x00,0x00,0x7F,0xFE,0x00,0x00,0xFF,0xFF,0x00,0x01,0xFF,0xFF,0x80,0x03,0xFF,0xFF,0x80,0x03,0xF8,0x1F,0xC0,0x07,0xF0,0x0F,0xC0,0x07,0xE0,0x07,0xE0,0x0F,0xC0,0x07,0xE0,0x0F,0xC0,0x03,0xE0,0x0F,0x80,0x03,0xF0,0x0F,0x80,0x03,0xF0,0x0F,0x80,0x01,0xF0,0x1F,0x80,0x01,0xF0,0x1F,0x80,0x01,0xF0,0x1F,0x80,0x01,0xF0,0x1F,0x00,0x01,0xF0,0x1F,0x00,0x01,0xF0,0x1F,0x00,0x01,0xF0,0x1F,0x00,0x01,0xF0,0x1F,0x00,0x01,0xF0,0x1F,0x00,0x01,0xF0,0x1F,0x80,0x01,0xF0,0x1F,0x80,0x01,0xF0,0x1F,0x80,0x01,0xF0,0x0F,0x80,0x01,0xF0,0x0F,0x80,0x03,0xF0,0x0F,0x80,0x03,0xF0,0x0F,0xC0,0x03,0xE0,0x0F,0xC0,0x07,0xE0,0x07,0xE0,0x07,0xE0,0x07,0xE0,0x0F,0xC0,0x03,0xF0,0x1F,0xC0,0x03,0xFE,0x7F,0x80,0x01,0xFF,0xFF,0x80,0x01,0xFF,0xFF,0x00,0x00,0xFF,0xFE,0x00,0x00,0x3F,0xFC,0x00,0x00,0x0F,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // o ++ ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xF0,0x00,0x07,0xC7,0xFC,0x00,0x07,0xDF,0xFF,0x00,0x07,0x9F,0xFF,0x80,0x07,0xFF,0xFF,0x80,0x07,0xFC,0x1F,0xC0,0x07,0xF8,0x0F,0xC0,0x07,0xF0,0x07,0xE0,0x07,0xE0,0x03,0xE0,0x07,0xE0,0x03,0xF0,0x07,0xC0,0x01,0xF0,0x07,0xC0,0x01,0xF0,0x07,0xC0,0x01,0xF0,0x07,0xC0,0x01,0xF0,0x07,0xC0,0x01,0xF8,0x07,0xC0,0x01,0xF8,0x07,0xC0,0x01,0xF8,0x07,0xC0,0x01,0xF8,0x07,0xC0,0x01,0xF8,0x07,0xC0,0x01,0xF8,0x07,0xC0,0x01,0xF8,0x07,0xC0,0x01,0xF0,0x07,0xC0,0x01,0xF0,0x07,0xC0,0x01,0xF0,0x07,0xC0,0x01,0xF0,0x07,0xE0,0x03,0xF0,0x07,0xE0,0x03,0xE0,0x07,0xF0,0x03,0xE0,0x07,0xF0,0x07,0xE0,0x07,0xF8,0x0F,0xC0,0x07,0xFF,0xFF,0xC0,0x07,0xBF,0xFF,0x80,0x07,0xDF,0xFF,0x00,0x07,0xCF,0xFE,0x00,0x07,0xC3,0xF8,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0x80,0x00,0x00, // p ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x80,0x00,0x00,0x7F,0xE3,0xE0,0x00,0xFF,0xF3,0xE0,0x01,0xFF,0xFB,0xE0,0x03,0xFF,0xFF,0xE0,0x03,0xF8,0x3F,0xE0,0x07,0xE0,0x1F,0xE0,0x07,0xC0,0x0F,0xE0,0x0F,0xC0,0x07,0xE0,0x0F,0x80,0x07,0xE0,0x0F,0x80,0x07,0xE0,0x0F,0x80,0x03,0xE0,0x1F,0x80,0x03,0xE0,0x1F,0x80,0x03,0xE0,0x1F,0x80,0x03,0xE0,0x1F,0x00,0x03,0xE0,0x1F,0x00,0x03,0xE0,0x1F,0x00,0x03,0xE0,0x1F,0x00,0x03,0xE0,0x1F,0x00,0x03,0xE0,0x1F,0x00,0x03,0xE0,0x1F,0x80,0x03,0xE0,0x1F,0x80,0x03,0xE0,0x0F,0x80,0x03,0xE0,0x0F,0x80,0x07,0xE0,0x0F,0x80,0x07,0xE0,0x0F,0xC0,0x07,0xE0,0x07,0xC0,0x0F,0xE0,0x07,0xE0,0x1F,0xE0,0x03,0xF0,0x3F,0xE0,0x03,0xFF,0xFF,0xE0,0x01,0xFF,0xFB,0xE0,0x00,0xFF,0xFB,0xE0,0x00,0x7F,0xF3,0xE0,0x00,0x1F,0xC3,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0, // q ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xC0,0x00,0x7C,0x1F,0xF8,0x00,0x7C,0x7F,0xFC,0x00,0x7C,0xFF,0xFC,0x00,0x7C,0xFF,0xFC,0x00,0x7D,0xFF,0xFC,0x00,0x7D,0xF8,0x3C,0x00,0x7F,0xE0,0x0C,0x00,0x7F,0x80,0x04,0x00,0x7F,0x80,0x00,0x00,0x7F,0x00,0x00,0x00,0x7F,0x00,0x00,0x00,0x7E,0x00,0x00,0x00,0x7E,0x00,0x00,0x00,0x7E,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // r ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xF0,0x00,0x00,0x3F,0xFE,0x00,0x00,0x7F,0xFF,0x80,0x00,0xFF,0xFF,0x80,0x01,0xFF,0xFF,0x80,0x01,0xFF,0xFF,0x80,0x03,0xF8,0x07,0x80,0x03,0xE0,0x01,0xC0,0x03,0xE0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xF8,0x00,0x00,0x03,0xFF,0x00,0x00,0x01,0xFF,0xE0,0x00,0x01,0xFF,0xFC,0x00,0x00,0xFF,0xFF,0x00,0x00,0x3F,0xFF,0x80,0x00,0x0F,0xFF,0x80,0x00,0x01,0xFF,0xC0,0x00,0x00,0x3F,0xC0,0x00,0x00,0x0F,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x07,0xE0,0x07,0x00,0x07,0xC0,0x07,0xC0,0x0F,0xC0,0x07,0xFC,0x7F,0x80,0x07,0xFF,0xFF,0x80,0x07,0xFF,0xFF,0x00,0x07,0xFF,0xFE,0x00,0x01,0xFF,0xFC,0x00,0x00,0x3F,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // s ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x1F,0x00,0x00,0x1F,0xFF,0xFF,0xC0,0x1F,0xFF,0xFF,0xE0,0x1F,0xFF,0xFF,0xE0,0x1F,0xFF,0xFF,0xE0,0x1F,0xFF,0xFF,0xE0,0x00,0x1F,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x1F,0x80,0x00,0x00,0x1F,0x80,0x00,0x00,0x0F,0xE0,0x00,0x00,0x0F,0xFF,0xE0,0x00,0x07,0xFF,0xE0,0x00,0x07,0xFF,0xE0,0x00,0x03,0xFF,0xE0,0x00,0x00,0xFF,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // t ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xC0,0x01,0xE0,0x07,0xC0,0x03,0xE0,0x07,0xC0,0x03,0xE0,0x07,0xC0,0x03,0xE0,0x07,0xC0,0x03,0xE0,0x07,0xC0,0x03,0xE0,0x07,0xC0,0x03,0xE0,0x07,0xC0,0x03,0xE0,0x07,0xC0,0x03,0xE0,0x07,0xC0,0x03,0xE0,0x07,0xC0,0x03,0xE0,0x07,0xC0,0x03,0xE0,0x07,0xC0,0x03,0xE0,0x07,0xC0,0x03,0xE0,0x07,0xC0,0x03,0xE0,0x07,0xC0,0x03,0xE0,0x07,0xC0,0x03,0xE0,0x07,0xC0,0x03,0xE0,0x07,0xC0,0x03,0xE0,0x07,0xC0,0x03,0xE0,0x07,0xC0,0x03,0xE0,0x07,0xC0,0x03,0xE0,0x07,0xC0,0x03,0xE0,0x07,0xC0,0x03,0xE0,0x07,0xC0,0x03,0xE0,0x07,0xC0,0x03,0xE0,0x07,0xC0,0x03,0xE0,0x07,0xC0,0x03,0xE0,0x07,0xC0,0x07,0xE0,0x07,0xE0,0x07,0xE0,0x07,0xE0,0x07,0xE0,0x03,0xF0,0x0F,0xE0,0x03,0xF8,0x1F,0xE0,0x03,0xFF,0xFF,0xE0,0x01,0xFF,0xF9,0xE0,0x01,0xFF,0xFB,0xE0,0x00,0xFF,0xF3,0xE0,0x00,0x7F,0xE3,0xE0,0x00,0x1F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // u ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x00,0xF8,0x1F,0x00,0x00,0xF8,0x1F,0x00,0x00,0xF8,0x1F,0x00,0x01,0xF0,0x0F,0x80,0x01,0xF0,0x0F,0x80,0x01,0xF0,0x0F,0x80,0x03,0xF0,0x0F,0xC0,0x03,0xE0,0x07,0xC0,0x03,0xE0,0x07,0xC0,0x03,0xE0,0x07,0xC0,0x07,0xE0,0x07,0xE0,0x07,0xC0,0x03,0xE0,0x07,0xC0,0x03,0xE0,0x07,0xC0,0x03,0xE0,0x0F,0x80,0x01,0xF0,0x0F,0x80,0x01,0xF0,0x0F,0x80,0x01,0xF0,0x0F,0x80,0x01,0xF0,0x1F,0x00,0x00,0xF8,0x1F,0x00,0x00,0xF8,0x1F,0x00,0x00,0xF8,0x1F,0x00,0x00,0xF8,0x3E,0x00,0x00,0x7C,0x3E,0x00,0x00,0x7C,0x3E,0x00,0x00,0x7C,0x7C,0x00,0x00,0x3E,0x7C,0x00,0x00,0x3E,0x7C,0x00,0x00,0x3E,0x7C,0x00,0x00,0x3E,0x78,0x00,0x00,0x1F,0xF8,0x00,0x00,0x1F,0xF8,0x00,0x00,0x1F,0xF8,0x00,0x00,0x1F,0xF0,0x00,0x00,0x0F,0xF0,0x00,0x00,0x0F,0xF0,0x00,0x00,0x0F,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // v ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x00,0x00,0x1F,0xF8,0x00,0x00,0x1F,0xF8,0x00,0x00,0x1F,0xF8,0x00,0x00,0x1F,0x7C,0x00,0x00,0x3E,0x7C,0x00,0x00,0x3E,0x7C,0x00,0x00,0x3E,0x7C,0x00,0x00,0x3E,0x7C,0x00,0x00,0x3E,0x3C,0x00,0x00,0x3C,0x3E,0x00,0x00,0x7C,0x3E,0x03,0xC0,0x7C,0x3E,0x03,0xC0,0x7C,0x3E,0x07,0xE0,0x7C,0x3E,0x07,0xE0,0x7C,0x1E,0x07,0xE0,0x78,0x1F,0x07,0xE0,0xF8,0x1F,0x07,0xF0,0xF8,0x1F,0x0F,0xF0,0xF8,0x1F,0x0E,0x70,0xF8,0x0F,0x0E,0x70,0xF0,0x0F,0x0E,0x70,0xF0,0x0F,0x9E,0x79,0xF0,0x0F,0x9E,0x79,0xF0,0x0F,0x9C,0x39,0xF0,0x0F,0x9C,0x39,0xF0,0x07,0x9C,0x39,0xE0,0x07,0xBC,0x3D,0xE0,0x07,0xBC,0x3D,0xE0,0x07,0xF8,0x1F,0xE0,0x07,0xF8,0x1F,0xE0,0x07,0xF8,0x1F,0xE0,0x03,0xF8,0x1F,0xC0,0x03,0xF8,0x1F,0xC0,0x03,0xF0,0x0F,0xC0,0x03,0xF0,0x0F,0xC0,0x03,0xF0,0x0F,0xC0,0x01,0xF0,0x0F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // w ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x01,0xF8,0x1F,0x80,0x01,0xF8,0x0F,0xC0,0x03,0xF0,0x07,0xC0,0x03,0xE0,0x07,0xE0,0x07,0xE0,0x03,0xE0,0x07,0xC0,0x01,0xF0,0x0F,0x80,0x01,0xF0,0x1F,0x80,0x00,0xF8,0x1F,0x00,0x00,0xFC,0x3F,0x00,0x00,0x7C,0x3E,0x00,0x00,0x7E,0x7E,0x00,0x00,0x3E,0x7C,0x00,0x00,0x1F,0xF8,0x00,0x00,0x1F,0xF8,0x00,0x00,0x0F,0xF0,0x00,0x00,0x0F,0xF0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x0F,0xF0,0x00,0x00,0x1F,0xF8,0x00,0x00,0x1F,0xF8,0x00,0x00,0x3F,0xFC,0x00,0x00,0x3E,0x7C,0x00,0x00,0x7E,0x7E,0x00,0x00,0x7C,0x3E,0x00,0x00,0xF8,0x1F,0x00,0x01,0xF8,0x1F,0x80,0x01,0xF0,0x0F,0x80,0x03,0xF0,0x0F,0xC0,0x03,0xE0,0x07,0xC0,0x07,0xE0,0x07,0xE0,0x07,0xC0,0x03,0xE0,0x0F,0xC0,0x03,0xF0,0x1F,0x80,0x01,0xF8,0x1F,0x00,0x00,0xF8,0x3F,0x00,0x00,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // x ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x00,0x7C,0x1F,0x00,0x00,0xFC,0x1F,0x80,0x00,0xF8,0x0F,0x80,0x00,0xF8,0x0F,0x80,0x01,0xF8,0x0F,0xC0,0x01,0xF0,0x07,0xC0,0x01,0xF0,0x07,0xC0,0x03,0xF0,0x03,0xE0,0x03,0xE0,0x03,0xE0,0x03,0xE0,0x03,0xE0,0x07,0xE0,0x01,0xF0,0x07,0xC0,0x01,0xF0,0x07,0xC0,0x01,0xF0,0x0F,0xC0,0x00,0xF8,0x0F,0x80,0x00,0xF8,0x0F,0x80,0x00,0xF8,0x1F,0x80,0x00,0x7C,0x1F,0x00,0x00,0x7C,0x1F,0x00,0x00,0x7C,0x3E,0x00,0x00,0x3E,0x3E,0x00,0x00,0x3E,0x3E,0x00,0x00,0x3E,0x7C,0x00,0x00,0x1F,0x7C,0x00,0x00,0x1F,0x7C,0x00,0x00,0x1F,0xF8,0x00,0x00,0x0F,0xF8,0x00,0x00,0x0F,0xF8,0x00,0x00,0x0F,0xF0,0x00,0x00,0x07,0xF0,0x00,0x00,0x07,0xF0,0x00,0x00,0x07,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x0F,0xC0,0x00,0x00,0x0F,0x80,0x00,0x00,0x0F,0x80,0x00,0x00,0x1F,0x80,0x00,0x00,0x3F,0x00,0x00,0x07,0xFF,0x00,0x00,0x07,0xFE,0x00,0x00,0x07,0xFC,0x00,0x00,0x07,0xF8,0x00,0x00,0x07,0xE0,0x00,0x00, // y ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xFF,0xFF,0xE0,0x03,0xFF,0xFF,0xE0,0x03,0xFF,0xFF,0xE0,0x03,0xFF,0xFF,0xE0,0x03,0xFF,0xFF,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x0F,0xC0,0x00,0x00,0x0F,0x80,0x00,0x00,0x1F,0x80,0x00,0x00,0x1F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x7E,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0xFC,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x03,0xF0,0x00,0x00,0x03,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x0F,0xC0,0x00,0x00,0x0F,0x80,0x00,0x00,0x1F,0x80,0x00,0x00,0x1F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x7E,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0xFC,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x03,0xF0,0x00,0x00,0x03,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xFF,0xFF,0xE0,0x07,0xFF,0xFF,0xE0,0x07,0xFF,0xFF,0xE0,0x07,0xFF,0xFF,0xE0,0x07,0xFF,0xFF,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // z ++0x00,0x00,0x0F,0xE0,0x00,0x00,0x3F,0xE0,0x00,0x00,0xFF,0xE0,0x00,0x00,0xFF,0xE0,0x00,0x01,0xFF,0xC0,0x00,0x01,0xF8,0x00,0x00,0x01,0xF0,0x00,0x00,0x03,0xF0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x0F,0xC0,0x00,0x00,0x7F,0x80,0x00,0x0F,0xFF,0x00,0x00,0x0F,0xF8,0x00,0x00,0x0F,0xF8,0x00,0x00,0x0F,0xFF,0x00,0x00,0x00,0x3F,0x80,0x00,0x00,0x0F,0xC0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xF0,0x00,0x00,0x03,0xF0,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xFE,0x00,0x00,0x00,0xFF,0xE0,0x00,0x00,0xFF,0xE0,0x00,0x00,0x7F,0xE0,0x00,0x00,0x1F,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // { ++0x00,0x01,0xE0,0x00,0x00,0x01,0xE0,0x00,0x00,0x01,0xE0,0x00,0x00,0x01,0xE0,0x00,0x00,0x01,0xE0,0x00,0x00,0x01,0xE0,0x00,0x00,0x01,0xE0,0x00,0x00,0x01,0xE0,0x00,0x00,0x01,0xE0,0x00,0x00,0x01,0xE0,0x00,0x00,0x01,0xE0,0x00,0x00,0x01,0xE0,0x00,0x00,0x01,0xE0,0x00,0x00,0x01,0xE0,0x00,0x00,0x01,0xE0,0x00,0x00,0x01,0xE0,0x00,0x00,0x01,0xE0,0x00,0x00,0x01,0xE0,0x00,0x00,0x01,0xE0,0x00,0x00,0x01,0xE0,0x00,0x00,0x01,0xE0,0x00,0x00,0x01,0xE0,0x00,0x00,0x01,0xE0,0x00,0x00,0x01,0xE0,0x00,0x00,0x01,0xE0,0x00,0x00,0x01,0xE0,0x00,0x00,0x01,0xE0,0x00,0x00,0x01,0xE0,0x00,0x00,0x01,0xE0,0x00,0x00,0x01,0xE0,0x00,0x00,0x01,0xE0,0x00,0x00,0x01,0xE0,0x00,0x00,0x01,0xE0,0x00,0x00,0x01,0xE0,0x00,0x00,0x01,0xE0,0x00,0x00,0x01,0xE0,0x00,0x00,0x01,0xE0,0x00,0x00,0x01,0xE0,0x00,0x00,0x01,0xE0,0x00,0x00,0x01,0xE0,0x00,0x00,0x01,0xE0,0x00,0x00,0x01,0xE0,0x00,0x00,0x01,0xE0,0x00,0x00,0x01,0xE0,0x00,0x00,0x01,0xE0,0x00,0x00,0x01,0xE0,0x00,0x00,0x01,0xE0,0x00,0x00,0x01,0xE0,0x00,0x00,0x01,0xE0,0x00,0x00,0x01,0xE0,0x00,0x00,0x01,0xE0,0x00,0x00,0x01,0xE0,0x00,0x00,0x01,0xE0,0x00,0x00,0x01,0xE0,0x00,0x00,0x01,0xE0,0x00,0x00,0x01,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // | ++0x03,0xF0,0x00,0x00,0x03,0xFE,0x00,0x00,0x03,0xFF,0x00,0x00,0x03,0xFF,0x80,0x00,0x03,0xFF,0x80,0x00,0x00,0x0F,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xF0,0x00,0x00,0x03,0xF8,0x00,0x00,0x01,0xFE,0x00,0x00,0x00,0x7F,0xF0,0x00,0x00,0x0F,0xF0,0x00,0x00,0x1F,0xF0,0x00,0x00,0xFF,0xF0,0x00,0x01,0xFE,0x00,0x00,0x03,0xF8,0x00,0x00,0x03,0xF0,0x00,0x00,0x03,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x0F,0xC0,0x00,0x00,0x7F,0xC0,0x00,0x03,0xFF,0x80,0x00,0x03,0xFF,0x00,0x00,0x03,0xFE,0x00,0x00,0x03,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // } ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xF0,0x00,0x00,0x07,0xFC,0x00,0x00,0x0F,0xFC,0x00,0x00,0x0F,0xFE,0x00,0x00,0x1F,0xFF,0x00,0x00,0x3F,0xFF,0x00,0x08,0x3E,0x1F,0x80,0x0E,0x3C,0x0F,0xC0,0x1E,0x7C,0x07,0xC0,0x1F,0x7C,0x07,0xE0,0x3E,0x78,0x03,0xE0,0x3E,0xF8,0x03,0xF0,0x7C,0x70,0x01,0xF8,0xFC,0x30,0x00,0xFF,0xF8,0x00,0x00,0xFF,0xF8,0x00,0x00,0x7F,0xF0,0x00,0x00,0x3F,0xF0,0x00,0x00,0x1F,0xE0,0x00,0x00,0x0F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ~ ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xC0,0x00,0x00,0x3F,0xF0,0x00,0x00,0xFF,0xFC,0x00,0x01,0xF8,0x7E,0x00,0x01,0xE0,0x1E,0x00,0x03,0xC0,0x0F,0x00,0x03,0x80,0x07,0x00,0x07,0x80,0x07,0x80,0x07,0x00,0x03,0x80,0x07,0x00,0x03,0x80,0x07,0x00,0x03,0x80,0x07,0x00,0x03,0x80,0x07,0x80,0x07,0x80,0x03,0x80,0x07,0x00,0x03,0xC0,0x0F,0x00,0x01,0xE0,0x1E,0x00,0x00,0xF8,0x7E,0x00,0x00,0x7F,0xFC,0x00,0x00,0x3F,0xF0,0x00,0x00,0x0F,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ° ++}; +diff -ruN main/drivers/auxdisplay/openvfd/controllers/fonts/icons16x16_h.h mod/drivers/auxdisplay/openvfd/controllers/fonts/icons16x16_h.h +--- main/drivers/auxdisplay/openvfd/controllers/fonts/icons16x16_h.h 1970-01-01 01:00:00.000000000 +0100 ++++ mod/drivers/auxdisplay/openvfd/controllers/fonts/icons16x16_h.h 2023-03-07 09:42:05.861566923 +0100 +@@ -0,0 +1,23 @@ ++// icons16x16_h.h ++// Font type : Full (15 characters) ++// Font size : 16x16 pixels ++// Memory usage : 484 bytes ++ ++const unsigned char icons16x16_H[484] = { ++0x10,0x10,0x01,0x0F, ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // Empty ++0x00,0x00,0x20,0x08,0x18,0x30,0x04,0x40,0x03,0x80,0x7F,0xFC,0x80,0x02,0x80,0x02,0xBF,0xFA,0x80,0x02,0xBF,0xFA,0x80,0x02,0xBF,0xFA,0x80,0x02,0x80,0x02,0x7F,0xFC, // TV Channel ++0x38,0x00,0x00,0x00,0x38,0x00,0x01,0x80,0x39,0x9C,0x01,0x80,0x01,0x9C,0x01,0x80,0x01,0x9C,0x01,0x80,0x03,0xC0,0x07,0xE0,0x07,0xE0,0x07,0xE0,0x07,0xE0,0x03,0xC0, // Temperaature ++0x0C,0x60,0x14,0x50,0x3F,0xF8,0x40,0x04,0x80,0x02,0x86,0xDA,0x86,0xDA,0x80,0x02,0xB6,0xDA,0xB6,0xDA,0x80,0x02,0xB6,0xC2,0xB6,0xC2,0x80,0x02,0x40,0x04,0x3F,0xF8, // Calendar ++0xFF,0xFE,0xAA,0xAA,0xFF,0xFE,0xA0,0x0A,0xA2,0x0A,0xA3,0x0A,0xA3,0x8A,0xA3,0xCA,0xA3,0x8A,0xA3,0x0A,0xA2,0x0A,0xA0,0x0A,0xFF,0xFE,0xAA,0xAA,0xFF,0xFE,0x00,0x00, // Media ++0x00,0x00,0x18,0x00,0x0C,0x00,0x06,0x60,0x03,0xC0,0x7F,0xFC,0xFF,0xFE,0xF8,0x06,0x98,0x02,0x90,0x02,0xF0,0x02,0x90,0x02,0x90,0x02,0xF8,0x06,0xFF,0xFE,0x7F,0xFC, // TV ++0x07,0xC0,0x04,0x40,0x04,0x40,0x04,0x40,0x07,0xC0,0x01,0x00,0x01,0x00,0x3F,0xF8,0x20,0x08,0x20,0x08,0xF8,0x3E,0x88,0x22,0x88,0x22,0x88,0x22,0xF8,0x3E,0x00,0x00, // Eth ++0x00,0x00,0x00,0x00,0x03,0xC0,0x1F,0xF8,0x3C,0x3C,0x71,0x8E,0x67,0xE6,0x0F,0xF0,0x1E,0x78,0x18,0x18,0x01,0x80,0x03,0xC0,0x03,0xC0,0x01,0x80,0x00,0x00,0x00,0x00, // Wifi ++0x08,0x00,0x0C,0x00,0x0E,0x00,0x0F,0x00,0x0F,0x80,0x0F,0xC0,0x0F,0xE0,0x0F,0xF0,0x0F,0xE0,0x0F,0xC0,0x0F,0x80,0x0F,0x00,0x0E,0x00,0x0C,0x00,0x08,0x00,0x00,0x00, // Play ++0x1C,0x38,0x3E,0x7C,0x3E,0x7C,0x3E,0x7C,0x3E,0x7C,0x3E,0x7C,0x3E,0x7C,0x3E,0x7C,0x3E,0x7C,0x3E,0x7C,0x3E,0x7C,0x3E,0x7C,0x3E,0x7C,0x3E,0x7C,0x1C,0x38,0x00,0x00, // Pause ++0x00,0x00,0x01,0x80,0x01,0x80,0x01,0x80,0x0D,0x80,0x0D,0xA0,0x0D,0xB0,0x05,0xA0,0x07,0xA0,0x03,0xE0,0x01,0xC0,0x01,0x80,0x01,0x80,0x03,0xC0,0x03,0xC0,0x01,0x80, // USB ++0x03,0xFC,0x04,0x04,0x09,0x54,0x11,0x54,0x21,0x54,0x21,0x54,0x20,0x04,0x20,0x04,0x2E,0xE4,0x28,0x94,0x2E,0x94,0x22,0x94,0x2E,0xE4,0x20,0x04,0x3F,0xFC,0x00,0x00, // SD ++0x00,0x00,0x01,0x00,0x01,0x80,0x01,0x40,0x09,0x20,0x05,0x20,0x03,0x40,0x01,0x80,0x01,0x80,0x03,0x40,0x05,0x20,0x09,0x20,0x01,0x40,0x01,0x80,0x01,0x00,0x00,0x00, // BT ++0x3F,0xF8,0x40,0x04,0x80,0x02,0x9E,0xF2,0x9E,0xF2,0x9E,0xF2,0x9E,0xF2,0x80,0x02,0x9E,0xF2,0x9E,0xF2,0x9E,0xF2,0x9E,0xF2,0x80,0x02,0x40,0x04,0x3F,0xF8,0x00,0x00, // Apps ++0x03,0xC0,0x23,0xC4,0x7F,0xFE,0x3F,0xFC,0x3F,0xFC,0x3E,0x7C,0xFC,0x3F,0xF8,0x1F,0xF8,0x1F,0xFC,0x3F,0x3E,0x7C,0x3F,0xFC,0x3F,0xFC,0x7F,0xFE,0x23,0xC4,0x03,0xC0, // Setup ++}; +diff -ruN main/drivers/auxdisplay/openvfd/controllers/fonts/icons16x16_v.h mod/drivers/auxdisplay/openvfd/controllers/fonts/icons16x16_v.h +--- main/drivers/auxdisplay/openvfd/controllers/fonts/icons16x16_v.h 1970-01-01 01:00:00.000000000 +0100 ++++ mod/drivers/auxdisplay/openvfd/controllers/fonts/icons16x16_v.h 2023-03-07 09:42:05.869566986 +0100 +@@ -0,0 +1,23 @@ ++// icons16x16_v.h ++// Font type : Full (15 characters) ++// Font size : 16x16 pixels ++// Memory usage : 484 bytes ++ ++const unsigned char icons16x16_V[484] = { ++0x10,0x10,0x01,0x0F, ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // Empty ++0xC0,0x20,0x22,0x24,0x24,0x28,0x30,0x30,0x30,0x28,0x24,0x24,0x22,0x20,0xC0,0x00,0x7F,0x80,0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x95,0x80,0x7F,0x00, // TV Channel ++0x00,0x00,0x15,0x15,0x15,0x00,0x00,0xF8,0xF8,0x00,0x00,0x50,0x50,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x78,0xFC,0xFF,0xFF,0xFC,0x78,0x01,0x01,0x01,0x00,0x00, // Temperaature ++0xF0,0x08,0x04,0x06,0x05,0x67,0x64,0x04,0x64,0x67,0x05,0x66,0x64,0x08,0xF0,0x00,0x3F,0x40,0x9B,0x9B,0x80,0x9B,0x9B,0x80,0x9B,0x9B,0x80,0x83,0x83,0x40,0x3F,0x00, // Calendar ++0xFF,0x05,0xFF,0x05,0x07,0x05,0xF7,0xE5,0xC7,0x85,0x07,0x05,0xFF,0x05,0xFF,0x00,0x7F,0x50,0x7F,0x50,0x70,0x50,0x77,0x53,0x71,0x50,0x70,0x50,0x7F,0x50,0x7F,0x00, // Media ++0xC0,0xE0,0xE0,0xE2,0xE6,0x6C,0x78,0x70,0x70,0x78,0x68,0x60,0x60,0xE0,0xC0,0x00,0x7F,0xE4,0xE4,0xFF,0xE1,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xE0,0x7F,0x00, // TV ++0x00,0x00,0x80,0x80,0x80,0x9F,0x91,0xF1,0x91,0x9F,0x80,0x80,0x80,0x00,0x00,0x00,0x7C,0x44,0x47,0x44,0x7C,0x00,0x00,0x00,0x00,0x00,0x7C,0x44,0x47,0x44,0x7C,0x00, // Eth ++0x00,0x60,0x70,0x38,0x98,0xD8,0xCC,0xEC,0xEC,0xCC,0xD8,0x98,0x38,0x70,0x60,0x00,0x00,0x00,0x00,0x03,0x03,0x01,0x19,0x3C,0x3C,0x19,0x01,0x03,0x03,0x00,0x00,0x00, // Wifi ++0x00,0x00,0x00,0x00,0xFF,0xFE,0xFC,0xF8,0xF0,0xE0,0xC0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x3F,0x1F,0x0F,0x07,0x03,0x01,0x00,0x00,0x00,0x00,0x00, // Play ++0x00,0x00,0xFE,0xFF,0xFF,0xFF,0xFE,0x00,0x00,0xFE,0xFF,0xFF,0xFF,0xFE,0x00,0x00,0x00,0x00,0x3F,0x7F,0x7F,0x7F,0x3F,0x00,0x00,0x3F,0x7F,0x7F,0x7F,0x3F,0x00,0x00, // Pause ++0x00,0x00,0x00,0x00,0x70,0xF0,0x00,0xFE,0xFE,0x00,0xE0,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x63,0xFF,0xFF,0x66,0x03,0x00,0x00,0x00,0x00,0x00, // USB ++0x00,0x00,0xF0,0x08,0x04,0x02,0x01,0x3D,0x01,0x3D,0x01,0x3D,0x01,0xFF,0x00,0x00,0x00,0x00,0x7F,0x40,0x57,0x55,0x5D,0x40,0x5F,0x51,0x51,0x4E,0x40,0x7F,0x00,0x00, // SD ++0x00,0x00,0x00,0x00,0x10,0x20,0x40,0xFE,0x84,0x48,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x02,0x7F,0x21,0x12,0x0C,0x00,0x00,0x00,0x00,0x00, // BT ++0xFC,0x02,0x01,0x79,0x79,0x79,0x79,0x01,0x79,0x79,0x79,0x79,0x01,0x02,0xFC,0x00,0x1F,0x20,0x40,0x4F,0x4F,0x4F,0x4F,0x40,0x4F,0x4F,0x4F,0x4F,0x40,0x20,0x1F,0x00, // Apps ++0xC0,0xC4,0xFE,0xFC,0xFC,0x7C,0x3F,0x1F,0x1F,0x3F,0x7C,0xFC,0xFC,0xFE,0xC4,0xC0,0x03,0x23,0x7F,0x3F,0x3F,0x3E,0xFC,0xF8,0xF8,0xFC,0x3E,0x3F,0x3F,0x7F,0x23,0x03, // Setup ++}; +diff -ruN main/drivers/auxdisplay/openvfd/controllers/fonts/icons32x32_h.h mod/drivers/auxdisplay/openvfd/controllers/fonts/icons32x32_h.h +--- main/drivers/auxdisplay/openvfd/controllers/fonts/icons32x32_h.h 1970-01-01 01:00:00.000000000 +0100 ++++ mod/drivers/auxdisplay/openvfd/controllers/fonts/icons32x32_h.h 2023-03-07 09:42:05.921567390 +0100 +@@ -0,0 +1,23 @@ ++// icons32x32_h.h ++// Font type : Full (15 characters) ++// Font size : 32x32 pixels ++// Memory usage : 1924 bytes ++ ++const unsigned char icons32x32_H[1924] = { ++0x20,0x20,0x01,0x0F, ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // Empty ++0x01,0x80,0x00,0xC0,0x00,0xC0,0x01,0x80,0x00,0x60,0x03,0x00,0x00,0x30,0x06,0x00,0x00,0x18,0x0C,0x00,0x00,0x0C,0x18,0x00,0x00,0x06,0x30,0x00,0x00,0x03,0x60,0x00,0x00,0x01,0xC0,0x00,0x03,0xFF,0xFF,0xE0,0x07,0xFF,0xFF,0xF0,0x0E,0x00,0x00,0x38,0x0C,0x00,0x00,0x18,0x0C,0x00,0x00,0x18,0x0C,0x00,0x00,0x18,0x0C,0xFF,0xFF,0x98,0x0C,0xFF,0xFF,0x98,0x0C,0x00,0x00,0x18,0x0C,0x00,0x00,0x18,0x0C,0xFF,0xFF,0x98,0x0C,0xFF,0xFF,0x98,0x0C,0x00,0x00,0x18,0x0C,0x00,0x00,0x18,0x0C,0xFF,0xFF,0x98,0x0C,0xFF,0xFF,0x98,0x0C,0x00,0x00,0x18,0x0E,0x00,0x00,0x18,0x07,0x00,0x00,0x70,0x03,0xFF,0xFF,0xE0,0x01,0xFF,0xFF,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // TV Channel ++0x00,0x01,0xC0,0x00,0x00,0x03,0x60,0x00,0x00,0x06,0x30,0x00,0x00,0x04,0x10,0x00,0x00,0x04,0x10,0x00,0x00,0x04,0x10,0x00,0x00,0x04,0x10,0x00,0x00,0x04,0x10,0x00,0x00,0x04,0x10,0x00,0x00,0x04,0x10,0x00,0x00,0x04,0x10,0x00,0x00,0x04,0x90,0x00,0x00,0x05,0xD0,0x00,0x00,0x05,0xD0,0x00,0x00,0x05,0xD0,0x00,0x00,0x05,0xD0,0x00,0x00,0x05,0xD0,0x00,0x00,0x05,0xD0,0x00,0x00,0x05,0xD0,0x00,0x00,0x0D,0xD8,0x00,0x00,0x19,0xCC,0x00,0x00,0x13,0xE4,0x00,0x00,0x37,0xF6,0x00,0x00,0x27,0xF2,0x00,0x00,0x27,0xF2,0x00,0x00,0x27,0xF2,0x00,0x00,0x37,0xF6,0x00,0x00,0x13,0xE4,0x00,0x00,0x18,0x0C,0x00,0x00,0x0E,0x38,0x00,0x00,0x03,0xE0,0x00,0x00,0x00,0x00,0x00, // Temperaature ++0x07,0xC0,0x0F,0x80,0x0F,0xC0,0x0F,0xC0,0x0E,0xC0,0x0D,0xC0,0x0C,0xC0,0x0C,0xC0,0x3C,0xFF,0xFC,0xF0,0x7C,0xFF,0xFC,0xF8,0xFF,0xFF,0xFF,0xFC,0xFF,0xFF,0xFF,0xFC,0xE0,0x00,0x00,0x1C,0xC0,0x00,0x00,0x0C,0xC0,0x00,0x00,0x0C,0xC0,0x00,0x00,0x0C,0xC0,0x3C,0xF3,0xCC,0xC0,0x3C,0xF3,0xCC,0xC0,0x3C,0xF3,0xCC,0xC0,0x3C,0xF3,0xCC,0xC0,0x00,0x00,0x0C,0xC0,0x00,0x00,0x0C,0xCF,0x3C,0xF3,0xCC,0xCF,0x3C,0xF3,0xCC,0xCF,0x3C,0xF3,0xCC,0xCF,0x3C,0xF3,0xCC,0xC0,0x00,0x00,0x0C,0xC0,0x00,0x00,0x0C,0xCF,0x3C,0xF0,0x0C,0xCF,0x3C,0xF0,0x0C,0xCF,0x3C,0xF0,0x0C,0xCF,0x3C,0xF0,0x0C,0xC0,0x00,0x00,0x0C,0xE0,0x00,0x00,0x1C,0x7F,0xFF,0xFF,0xF8,0x3F,0xFF,0xFF,0xF0, // Calendar ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC6,0x31,0x8C,0x63,0xC6,0x31,0x8C,0x63,0xC6,0x31,0x8C,0x63,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC3,0x00,0x00,0xC3,0xC3,0x18,0x00,0xC3,0xC3,0x1E,0x00,0xC3,0xC3,0x1F,0x80,0xC3,0xC3,0x1F,0xE0,0xC3,0xC3,0x1F,0xF0,0xC3,0xC3,0x1F,0xF8,0xC3,0xC3,0x1F,0xF0,0xC3,0xC3,0x1F,0xE0,0xC3,0xC3,0x1F,0x80,0xC3,0xC3,0x1E,0x00,0xC3,0xC3,0x18,0x00,0xC3,0xC3,0x00,0x00,0xC3,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC6,0x31,0x8C,0x63,0xC6,0x31,0x8C,0x63,0xC6,0x31,0x8C,0x63,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // Media ++0x00,0x00,0x00,0x00,0x01,0x80,0x00,0x00,0x01,0xC0,0x00,0x00,0x01,0xE0,0x00,0x00,0x00,0xF0,0x08,0x00,0x00,0x78,0x1C,0x00,0x00,0x3C,0x3C,0x00,0x00,0x1E,0x78,0x00,0x00,0x0F,0xF0,0x00,0x00,0x07,0xE0,0x00,0x1F,0xFF,0xFF,0xF8,0x3F,0xFF,0xFF,0xFC,0x7F,0xFF,0xFF,0xFE,0x7F,0xF0,0x00,0x3E,0x7F,0xC0,0x00,0x1E,0x7F,0xC0,0x00,0x0E,0x73,0xC0,0x00,0x0E,0x71,0x80,0x00,0x0E,0x73,0x80,0x00,0x0E,0x7F,0x80,0x00,0x0E,0x7F,0x80,0x00,0x0E,0x73,0x80,0x00,0x0E,0x71,0x80,0x00,0x0E,0x73,0x80,0x00,0x0E,0x7F,0x80,0x00,0x0E,0x7F,0xC0,0x00,0x0E,0x7F,0xC0,0x00,0x1E,0x7F,0xE0,0x00,0x1E,0x7F,0xFF,0xFF,0xFE,0x7F,0xFF,0xFF,0xFC,0x3F,0xFF,0xFF,0xF8,0x00,0x00,0x00,0x00, // TV ++0x00,0x3F,0xF0,0x00,0x00,0x3F,0xF0,0x00,0x00,0x30,0x30,0x00,0x00,0x30,0x30,0x00,0x00,0x30,0x30,0x00,0x00,0x30,0x30,0x00,0x00,0x30,0x30,0x00,0x00,0x30,0x30,0x00,0x00,0x3F,0xF0,0x00,0x00,0x3F,0xF0,0x00,0x00,0x03,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x03,0x00,0x00,0x0F,0xFF,0xFF,0xC0,0x0F,0xFF,0xFF,0xC0,0x0C,0x00,0x00,0xC0,0x0C,0x00,0x00,0xC0,0x0C,0x00,0x00,0xC0,0x0C,0x00,0x00,0xC0,0xFF,0xC0,0x0F,0xFC,0xFF,0xC0,0x0F,0xFC,0xC0,0xC0,0x0C,0x0C,0xC0,0xC0,0x0C,0x0C,0xC0,0xC0,0x0C,0x0C,0xC0,0xC0,0x0C,0x0C,0xC0,0xC0,0x0C,0x0C,0xC0,0xC0,0x0C,0x0C,0xFF,0xC0,0x0F,0xFC,0xFF,0xC0,0x0F,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // Eth ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xE0,0x00,0x00,0x1F,0xF8,0x00,0x00,0x7F,0xFE,0x00,0x01,0xFF,0xFF,0x80,0x03,0xFF,0xFF,0xC0,0x07,0xFF,0xFF,0xE0,0x0F,0xF8,0x1F,0xF0,0x1F,0xE0,0x07,0xF8,0x3F,0x80,0x01,0xFC,0x3F,0x07,0xE0,0xFC,0x3E,0x1F,0xF8,0x7C,0x1C,0x3F,0xFC,0x38,0x00,0x7F,0xFE,0x00,0x00,0xFF,0xFF,0x00,0x01,0xFC,0x3F,0x80,0x03,0xF8,0x1F,0xC0,0x03,0xE0,0x07,0xC0,0x01,0xC3,0xC3,0x80,0x00,0x07,0xE0,0x00,0x00,0x0F,0xF0,0x00,0x00,0x0F,0xF0,0x00,0x00,0x0F,0xF0,0x00,0x00,0x0F,0xF0,0x00,0x00,0x07,0xE0,0x00,0x00,0x03,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // Wifi ++0x00,0xC0,0x00,0x00,0x00,0xE0,0x00,0x00,0x00,0xF0,0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0xFC,0x00,0x00,0x00,0xFE,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0xFF,0x80,0x00,0x00,0xFF,0xC0,0x00,0x00,0xFF,0xE0,0x00,0x00,0xFF,0xF0,0x00,0x00,0xFF,0xF8,0x00,0x00,0xFF,0xFC,0x00,0x00,0xFF,0xFE,0x00,0x00,0xFF,0xFF,0x00,0x00,0xFF,0xFF,0x00,0x00,0xFF,0xFE,0x00,0x00,0xFF,0xFC,0x00,0x00,0xFF,0xF8,0x00,0x00,0xFF,0xF0,0x00,0x00,0xFF,0xE0,0x00,0x00,0xFF,0xC0,0x00,0x00,0xFF,0x80,0x00,0x00,0xFF,0x00,0x00,0x00,0xFE,0x00,0x00,0x00,0xFC,0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0xF0,0x00,0x00,0x00,0xE0,0x00,0x00,0x00,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // Play ++0x03,0xF0,0x0F,0xC0,0x07,0xF8,0x1F,0xE0,0x0F,0xFC,0x3F,0xF0,0x0F,0xFC,0x3F,0xF0,0x0F,0xFC,0x3F,0xF0,0x0F,0xFC,0x3F,0xF0,0x0F,0xFC,0x3F,0xF0,0x0F,0xFC,0x3F,0xF0,0x0F,0xFC,0x3F,0xF0,0x0F,0xFC,0x3F,0xF0,0x0F,0xFC,0x3F,0xF0,0x0F,0xFC,0x3F,0xF0,0x0F,0xFC,0x3F,0xF0,0x0F,0xFC,0x3F,0xF0,0x0F,0xFC,0x3F,0xF0,0x0F,0xFC,0x3F,0xF0,0x0F,0xFC,0x3F,0xF0,0x0F,0xFC,0x3F,0xF0,0x0F,0xFC,0x3F,0xF0,0x0F,0xFC,0x3F,0xF0,0x0F,0xFC,0x3F,0xF0,0x0F,0xFC,0x3F,0xF0,0x0F,0xFC,0x3F,0xF0,0x0F,0xFC,0x3F,0xF0,0x0F,0xFC,0x3F,0xF0,0x0F,0xFC,0x3F,0xF0,0x0F,0xFC,0x3F,0xF0,0x0F,0xFC,0x3F,0xF0,0x07,0xF8,0x1F,0xE0,0x03,0xF0,0x0F,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // Pause ++0x00,0x7F,0xFE,0x00,0x00,0x7F,0xFE,0x00,0x00,0x60,0x06,0x00,0x00,0x66,0x66,0x00,0x00,0x66,0x66,0x00,0x00,0x66,0x66,0x00,0x00,0x66,0x66,0x00,0x00,0x60,0x06,0x00,0x00,0x60,0x06,0x00,0x01,0xFF,0xFF,0x80,0x03,0xFF,0xFF,0xC0,0x06,0x00,0x00,0x60,0x06,0x07,0x70,0x60,0x06,0x08,0x88,0x60,0x06,0x08,0x88,0x60,0x06,0x08,0x88,0x60,0x06,0x0F,0xF8,0x60,0x06,0x00,0x00,0x60,0x06,0x08,0x70,0x60,0x06,0x08,0x88,0x60,0x06,0x08,0x88,0x60,0x06,0x08,0x88,0x60,0x06,0x07,0x08,0x60,0x06,0x00,0x00,0x60,0x06,0x0F,0xF0,0x60,0x06,0x00,0x08,0x60,0x06,0x00,0x08,0x60,0x06,0x00,0x08,0x60,0x06,0x0F,0xF0,0x60,0x06,0x00,0x00,0x60,0x07,0xFF,0xFF,0xE0,0x03,0xFF,0xFF,0xC0, // USB ++0x00,0x0F,0xFF,0xF0,0x00,0x1F,0xFF,0xF0,0x00,0x38,0x00,0x30,0x00,0x70,0x00,0x30,0x00,0xE3,0x33,0x30,0x01,0xC3,0x33,0x30,0x03,0x83,0x33,0x30,0x07,0x03,0x33,0x30,0x0E,0x03,0x33,0x30,0x0C,0x03,0x33,0x30,0x0C,0x03,0x33,0x30,0x0C,0x03,0x33,0x30,0x0C,0x00,0x00,0x30,0x0C,0x00,0x00,0x30,0x0C,0x00,0x00,0x30,0x0C,0x00,0x00,0x30,0x0C,0xFC,0xFC,0x30,0x0C,0xFC,0xFE,0x30,0x0C,0xC0,0xC7,0x30,0x0C,0xC0,0xC3,0x30,0x0C,0xFC,0xC3,0x30,0x0C,0xFC,0xC3,0x30,0x0C,0x0C,0xC3,0x30,0x0C,0x0C,0xC7,0x30,0x0C,0xFC,0xFE,0x30,0x0C,0xFC,0xFC,0x30,0x0C,0x00,0x00,0x30,0x0C,0x00,0x00,0x30,0x0F,0xFF,0xFF,0xF0,0x0F,0xFF,0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // SD ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x03,0x80,0x00,0x00,0x03,0xC0,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0x70,0x00,0x00,0x03,0x38,0x00,0x00,0xC3,0x1C,0x00,0x00,0xE3,0x0E,0x00,0x00,0x73,0x0E,0x00,0x00,0x3B,0x1C,0x00,0x00,0x1F,0x38,0x00,0x00,0x0F,0x70,0x00,0x00,0x07,0xE0,0x00,0x00,0x03,0xC0,0x00,0x00,0x03,0xC0,0x00,0x00,0x07,0xE0,0x00,0x00,0x0F,0x70,0x00,0x00,0x1F,0x38,0x00,0x00,0x3B,0x1C,0x00,0x00,0x73,0x0E,0x00,0x00,0xE3,0x0E,0x00,0x00,0xC3,0x1C,0x00,0x00,0x03,0x38,0x00,0x00,0x03,0x70,0x00,0x00,0x03,0xE0,0x00,0x00,0x03,0xC0,0x00,0x00,0x03,0x80,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // BT ++0x0F,0xFF,0xFF,0xC0,0x1F,0xFF,0xFF,0xE0,0x38,0x00,0x00,0x70,0x70,0x00,0x00,0x38,0xE0,0x00,0x00,0x1C,0xC0,0x00,0x00,0x0C,0xC1,0xFC,0xFE,0x0C,0xC3,0xFC,0xFF,0x0C,0xC3,0xFC,0xFF,0x0C,0xC3,0xFC,0xFF,0x0C,0xC3,0xFC,0xFF,0x0C,0xC3,0xFC,0xFF,0x0C,0xC3,0xFC,0xFF,0x0C,0xC3,0xFC,0xFF,0x0C,0xC0,0x00,0x00,0x0C,0xC0,0x00,0x00,0x0C,0xC3,0xFC,0xFF,0x0C,0xC3,0xFC,0xFF,0x0C,0xC3,0xFC,0xFF,0x0C,0xC3,0xFC,0xFF,0x0C,0xC3,0xFC,0xFF,0x0C,0xC3,0xFC,0xFF,0x0C,0xC3,0xFC,0xFF,0x0C,0xC1,0xFC,0xFE,0x0C,0xC0,0x00,0x00,0x0C,0xE0,0x00,0x00,0x1C,0x70,0x00,0x00,0x38,0x38,0x00,0x00,0x70,0x1F,0xFF,0xFF,0xE0,0x0F,0xFF,0xFF,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // Apps ++0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x03,0x07,0xF0,0xC0,0x07,0xCF,0xF1,0xE0,0x0F,0xFF,0xFF,0xF0,0x1F,0xFF,0xFF,0xF8,0x1F,0xFF,0xFF,0xF8,0x0F,0xFF,0xFF,0xF0,0x07,0xFF,0xFF,0xE0,0x07,0xFF,0xFF,0xE0,0x07,0xF8,0x1F,0xE0,0x0F,0xF0,0x0F,0xF8,0xFF,0xE0,0x07,0xFF,0xFF,0xE0,0x07,0xFF,0xFF,0xE0,0x07,0xFF,0xFF,0xE0,0x07,0xFF,0xFF,0xE0,0x07,0xFF,0xFF,0xE0,0x07,0xFF,0x1F,0xF0,0x0F,0xF0,0x07,0xF8,0x1F,0xE0,0x07,0xFF,0xFF,0xE0,0x07,0xFF,0xFF,0xE0,0x0F,0xFF,0xFF,0xF0,0x1F,0xFF,0xFF,0xF8,0x1F,0xFF,0xFF,0xF8,0x0F,0xFF,0xFF,0xF0,0x07,0x8F,0xF1,0xE0,0x03,0x0F,0xE0,0xC0,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00, // Setup ++}; +diff -ruN main/drivers/auxdisplay/openvfd/controllers/fonts/icons32x32_v.h mod/drivers/auxdisplay/openvfd/controllers/fonts/icons32x32_v.h +--- main/drivers/auxdisplay/openvfd/controllers/fonts/icons32x32_v.h 1970-01-01 01:00:00.000000000 +0100 ++++ mod/drivers/auxdisplay/openvfd/controllers/fonts/icons32x32_v.h 2023-03-07 09:42:05.921567390 +0100 +@@ -0,0 +1,23 @@ ++// icons32x32_v.h ++// Font type : Full (15 characters) ++// Font size : 32x32 pixels ++// Memory usage : 1924 bytes ++ ++const unsigned char icons32x32_V[1924] = { ++0x20,0x20,0x01,0x0F, ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // Empty ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x06,0x0C,0x18,0x30,0x60,0xC0,0x80,0x00,0x80,0xC0,0x60,0x30,0x18,0x0C,0x06,0x03,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0xFC,0x0E,0x06,0x86,0x86,0x86,0x86,0x86,0x86,0x86,0x87,0x87,0x87,0x86,0x86,0x86,0x86,0x86,0x86,0x86,0x06,0x0E,0xFC,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x00,0x00,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x00,0x00,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x0F,0x1C,0x38,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x38,0x18,0x0F,0x07,0x00,0x00,0x00, // TV Channel ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFC,0x06,0x03,0x01,0x03,0x06,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0xF0,0xF8,0xF0,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x70,0x18,0xCF,0xE0,0xFF,0xFF,0xFF,0xE0,0xCF,0x18,0x70,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x1C,0x30,0x27,0x6F,0x4F,0x4F,0x4F,0x6F,0x27,0x30,0x1C,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // Temperaature ++0xC0,0xE0,0xF0,0xF0,0xFE,0xFF,0xC7,0xC3,0xFF,0xFF,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xFF,0xFF,0xC3,0xC7,0xFF,0xFE,0xF0,0xF0,0xE0,0xC0,0x00,0x00,0xFF,0xFF,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0xF0,0xF0,0xF0,0x00,0x00,0xF0,0xF0,0xF0,0xF0,0x00,0x00,0xF0,0xF0,0xF0,0xF0,0x00,0x01,0xFF,0xFF,0x00,0x00,0xFF,0xFF,0x00,0x00,0x3C,0x3C,0x3C,0x3C,0x00,0x00,0x3C,0x3C,0x3C,0x3C,0x00,0x00,0x3C,0x3C,0x3C,0x3C,0x00,0x00,0x3C,0x3C,0x3C,0x3C,0x00,0x00,0xFF,0xFF,0x00,0x00,0x3F,0x7F,0xE0,0xC0,0xCF,0xCF,0xCF,0xCF,0xC0,0xC0,0xCF,0xCF,0xCF,0xCF,0xC0,0xC0,0xCF,0xCF,0xCF,0xCF,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xE0,0x7F,0x3F,0x00,0x00, // Calendar ++0xFC,0xFC,0x8C,0x8C,0x8C,0xFC,0xFC,0x8C,0x8C,0x8C,0xFC,0xFC,0x8C,0x8C,0x8C,0xFC,0xFC,0x8C,0x8C,0x8C,0xFC,0xFC,0x8C,0x8C,0x8C,0xFC,0xFC,0x8C,0x8C,0x8C,0xFC,0xFC,0xFF,0xFF,0x01,0x01,0x01,0x01,0xFF,0xFF,0x01,0x01,0x01,0xFD,0xFD,0xF9,0xF9,0xF1,0xF1,0xE1,0xE1,0xC1,0x81,0x01,0x01,0x01,0xFF,0xFF,0x01,0x01,0x01,0x01,0xFF,0xFF,0xFF,0xFF,0xC0,0xC0,0xC0,0xC0,0xFF,0xFF,0xC0,0xC0,0xC0,0xDF,0xDF,0xCF,0xCF,0xC7,0xC7,0xC3,0xC3,0xC1,0xC0,0xC0,0xC0,0xC0,0xFF,0xFF,0xC0,0xC0,0xC0,0xC0,0xFF,0xFF,0x1F,0x1F,0x18,0x18,0x18,0x1F,0x1F,0x18,0x18,0x18,0x1F,0x1F,0x18,0x18,0x18,0x1F,0x1F,0x18,0x18,0x18,0x1F,0x1F,0x18,0x18,0x18,0x1F,0x1F,0x18,0x18,0x18,0x1F,0x1F, // Media ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0x1E,0x3C,0x78,0xF0,0xE0,0xC0,0x80,0x00,0x00,0x80,0xC0,0xE0,0xF0,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0xF8,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0x3C,0x3C,0x1D,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1D,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x3C,0x7C,0xFC,0xF8,0xF0,0x00,0x00,0xFF,0xFF,0xFF,0x18,0x18,0xBD,0xFF,0xFF,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0x00,0x00,0x3F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7E,0x78,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x7C,0x7F,0x3F,0x1F,0x00, // TV ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x03,0x03,0x03,0x03,0x03,0x03,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC3,0xC3,0xC3,0xC3,0xFF,0xFF,0xC3,0xC3,0xC3,0xC3,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0xF0,0x30,0x30,0x3F,0x3F,0x30,0x30,0xF0,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0xF0,0x30,0x30,0x3F,0x3F,0x30,0x30,0xF0,0xF0,0x00,0x00,0x3F,0x3F,0x30,0x30,0x30,0x30,0x30,0x30,0x3F,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x3F,0x30,0x30,0x30,0x30,0x30,0x30,0x3F,0x3F,0x00,0x00, // Eth ++0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xC0,0xC0,0xE0,0xE0,0xF0,0xF0,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF0,0xF0,0xE0,0xE0,0xC0,0xC0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x7C,0x7E,0x7F,0x3F,0x1F,0x0F,0x87,0xC7,0xE3,0xE3,0xF1,0xF1,0xF1,0xF1,0xF1,0xF1,0xE3,0xE3,0xC7,0x87,0x0F,0x1F,0x3F,0x7F,0x7E,0x7C,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x1E,0x1F,0x1F,0x0F,0x07,0xC7,0xE3,0xF1,0xF1,0xF1,0xF1,0xE3,0xC7,0x07,0x0F,0x1F,0x1F,0x1E,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x07,0x0F,0x0F,0x0F,0x0F,0x07,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // Wifi ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFE,0xFC,0xF8,0xF0,0xE0,0xC0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFC,0xF8,0xF0,0xE0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x3F,0x1F,0x0F,0x07,0x03,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x3F,0x1F,0x0F,0x07,0x03,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // Play ++0x00,0x00,0x00,0x00,0xFC,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFC,0x00,0x00,0x00,0x00,0xFC,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x1F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x1F,0x0F,0x00,0x00,0x00,0x00,0x0F,0x1F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x1F,0x0F,0x00,0x00,0x00,0x00, // Pause ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x03,0x03,0x7B,0x7B,0x03,0x03,0x7B,0x7B,0x03,0x03,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0xFC,0x06,0x06,0x07,0x07,0x06,0xE6,0x16,0x16,0x16,0xE6,0x16,0x16,0x16,0xE6,0x07,0x07,0x06,0x06,0xFC,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x3D,0x41,0x41,0x41,0x39,0x05,0x05,0x05,0x79,0x00,0x00,0x00,0x00,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0xFF,0xC0,0xC0,0xC0,0xC0,0xC0,0xD1,0xD1,0xD1,0xD1,0xD1,0xD1,0xD1,0xD1,0xCE,0xC0,0xC0,0xC0,0xC0,0xFF,0x7F,0x00,0x00,0x00,0x00,0x00, // USB ++0x00,0x00,0x00,0x00,0x00,0x80,0xC0,0xE0,0x70,0x38,0x1C,0x0E,0x07,0x03,0xF3,0xF3,0x03,0x03,0xF3,0xF3,0x03,0x03,0xF3,0xF3,0x03,0x03,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x0F,0x00,0x00,0x0F,0x0F,0x00,0x00,0x0F,0x0F,0x00,0x00,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x00,0x00,0x3F,0x3F,0x33,0x33,0xF3,0xF3,0x00,0x00,0xFF,0xFF,0x03,0x03,0x03,0x87,0xFE,0xFC,0x00,0x00,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x3F,0x30,0x30,0x33,0x33,0x33,0x33,0x33,0x33,0x30,0x30,0x33,0x33,0x33,0x33,0x33,0x33,0x31,0x30,0x30,0x30,0x3F,0x3F,0x00,0x00,0x00,0x00, // SD ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFC,0xFC,0x38,0x70,0xE0,0xC0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x07,0x0E,0x1C,0x38,0x70,0xFF,0xFF,0xC0,0xE0,0x70,0x39,0x1F,0x0F,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xE0,0x70,0x38,0x1C,0x0E,0xFF,0xFF,0x03,0x07,0x0E,0x9C,0xF8,0xF0,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x3F,0x1C,0x0E,0x07,0x03,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // BT ++0xF0,0xF8,0x1C,0x0E,0x07,0x03,0x83,0xC3,0xC3,0xC3,0xC3,0xC3,0xC3,0xC3,0x03,0x03,0xC3,0xC3,0xC3,0xC3,0xC3,0xC3,0xC3,0x83,0x03,0x07,0x0E,0x1C,0xF8,0xF0,0x00,0x00,0xFF,0xFF,0x00,0x00,0x00,0x00,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x00,0x00,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x00,0x00,0x00,0x00,0xFF,0xFF,0x00,0x00,0xFF,0xFF,0x00,0x00,0x00,0x00,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x00,0x00,0x00,0x00,0xFF,0xFF,0x00,0x00,0x03,0x07,0x0E,0x1C,0x38,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x38,0x1C,0x0E,0x07,0x03,0x00,0x00, // Apps ++0x00,0x00,0x00,0xC0,0xE0,0xF0,0xF8,0xF8,0xF0,0xF0,0xE0,0xE0,0xF0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF8,0xE0,0xE0,0xE0,0xF0,0xF8,0xF8,0xF0,0xE0,0xC0,0x00,0x00,0x00,0xE0,0xE0,0xE0,0xE0,0xF1,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x1F,0x0F,0x07,0x07,0x07,0x07,0x07,0x07,0x0F,0x1F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF1,0xF0,0xE0,0xE0,0xE0,0x07,0x07,0x07,0x0F,0x8F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF8,0xF0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xF0,0xF8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8F,0x07,0x07,0x07,0x07,0x00,0x00,0x00,0x03,0x07,0x0F,0x1F,0x1F,0x0F,0x07,0x07,0x07,0x1F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x0F,0x07,0x07,0x07,0x0F,0x1F,0x1F,0x0F,0x07,0x03,0x00,0x00,0x00, // Setup ++}; +diff -ruN main/drivers/auxdisplay/openvfd/controllers/fonts/Retro8x16_v.h mod/drivers/auxdisplay/openvfd/controllers/fonts/Retro8x16_v.h +--- main/drivers/auxdisplay/openvfd/controllers/fonts/Retro8x16_v.h 1970-01-01 01:00:00.000000000 +0100 ++++ mod/drivers/auxdisplay/openvfd/controllers/fonts/Retro8x16_v.h 2023-03-07 09:42:05.977567824 +0100 +@@ -0,0 +1,107 @@ ++// Retro8x16_v.h ++// Font type : Full (96 characters) ++// Font size : 8x16 pixels ++// Memory usage : 1540 bytes ++ ++// Origin: http://www.rinkydinkelectronics.com/r_fonts.php ++// Modified by Arthur Liberman for compatibility with the OpenVFD driver. ++ ++const unsigned char Retro8x16_V[1540] = { ++0x08,0x10,0x20,0x60, ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ++0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x33,0x00,0x00,0x00,0x00, // ! ++0x00,0x00,0x3F,0x00,0x00,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // " ++0x00,0x30,0xFF,0x30,0x30,0xFF,0x30,0x00,0x00,0x03,0x3F,0x03,0x03,0x3F,0x03,0x00, // # ++0x00,0x30,0xCC,0xFF,0xCC,0x0C,0x00,0x00,0x00,0x0C,0x0C,0x3F,0x0C,0x03,0x00,0x00, // $ ++0x00,0x3C,0x3C,0x00,0xC0,0x30,0x0C,0x00,0x00,0x30,0x0C,0x03,0x00,0x3C,0x3C,0x00, // % ++0x00,0x3C,0xC3,0xC3,0x3C,0x00,0x00,0x00,0x00,0x0F,0x30,0x30,0x33,0x0C,0x33,0x00, // & ++0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ' ++0x00,0xF0,0x0C,0x03,0x00,0x00,0x00,0x00,0x00,0x03,0x0C,0x30,0x00,0x00,0x00,0x00, // ( ++0x00,0x00,0x00,0x03,0x0C,0xF0,0x00,0x00,0x00,0x00,0x00,0x30,0x0C,0x03,0x00,0x00, // ) ++0x00,0x0C,0x30,0xFF,0x30,0x0C,0x00,0x00,0x00,0x0C,0x03,0x3F,0x03,0x0C,0x00,0x00, // * ++0x00,0xC0,0xC0,0xFC,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00,0x0F,0x00,0x00,0x00,0x00, // + ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x0F,0x00,0x00,0x00, // , ++0x00,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // - ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x00, // . ++0x00,0x00,0x00,0x00,0xC0,0x30,0x0C,0x00,0x00,0x30,0x0C,0x03,0x00,0x00,0x00,0x00, // / ++0x00,0xFC,0x03,0xC3,0xC3,0x33,0xFC,0x00,0x00,0x0F,0x33,0x30,0x30,0x30,0x0F,0x00, // 0 ++0x00,0x00,0x00,0x0C,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x3F,0x30,0x00,0x00, // 1 ++0x00,0x0C,0x03,0xC3,0xC3,0xC3,0x3C,0x00,0x00,0x3C,0x33,0x30,0x30,0x30,0x30,0x00, // 2 ++0x00,0x03,0x03,0xC3,0xC3,0xF3,0x0F,0x00,0x00,0x0C,0x30,0x30,0x30,0x30,0x0F,0x00, // 3 ++0x00,0x00,0xC0,0x30,0x0C,0xFF,0x00,0x00,0x00,0x03,0x03,0x03,0x03,0x3F,0x03,0x00, // 4 ++0x00,0x3F,0x33,0x33,0x33,0x33,0xC3,0x00,0x00,0x0C,0x30,0x30,0x30,0x30,0x0F,0x00, // 5 ++0x00,0xF0,0xCC,0xC3,0xC3,0xC3,0x03,0x00,0x00,0x0F,0x30,0x30,0x30,0x30,0x0F,0x00, // 6 ++0x00,0x03,0x03,0x03,0xC3,0x33,0x0F,0x00,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x00, // 7 ++0x00,0x3C,0xC3,0xC3,0xC3,0xC3,0x3C,0x00,0x00,0x0F,0x30,0x30,0x30,0x30,0x0F,0x00, // 8 ++0x00,0x3C,0xC3,0xC3,0xC3,0xC3,0xFC,0x00,0x00,0x30,0x30,0x30,0x30,0x0C,0x03,0x00, // 9 ++0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00, // : ++0x00,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x0F,0x00,0x00,0x00, // ; ++0x00,0x00,0xC0,0x30,0x0C,0x03,0x00,0x00,0x00,0x00,0x00,0x03,0x0C,0x30,0x00,0x00, // < ++0x00,0x30,0x30,0x30,0x30,0x30,0x30,0x00,0x00,0x03,0x03,0x03,0x03,0x03,0x03,0x00, // = ++0x00,0x00,0x03,0x0C,0x30,0xC0,0x00,0x00,0x00,0x00,0x30,0x0C,0x03,0x00,0x00,0x00, // > ++0x00,0x0C,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ? ++0x00,0xFC,0x03,0xC3,0x33,0xC3,0xFC,0x00,0x00,0x0F,0x30,0x30,0x33,0x33,0x30,0x00, // @ ++0x00,0xF0,0x0C,0x03,0x03,0x0C,0xF0,0x00,0x00,0x3F,0x03,0x03,0x03,0x03,0x3F,0x00, // A ++0x00,0xFF,0xC3,0xC3,0xC3,0xC3,0x3C,0x00,0x00,0x3F,0x30,0x30,0x30,0x30,0x0F,0x00, // B ++0x00,0xFC,0x03,0x03,0x03,0x03,0x0C,0x00,0x00,0x0F,0x30,0x30,0x30,0x30,0x0C,0x00, // C ++0x00,0xFF,0x03,0x03,0x03,0x03,0xFC,0x00,0x00,0x3F,0x30,0x30,0x30,0x30,0x0F,0x00, // D ++0x00,0xFF,0xC3,0xC3,0xC3,0xC3,0x03,0x00,0x00,0x3F,0x30,0x30,0x30,0x30,0x30,0x00, // E ++0x00,0xFF,0xC3,0xC3,0xC3,0xC3,0x03,0x00,0x00,0x3F,0x00,0x00,0x00,0x00,0x00,0x00, // F ++0x00,0xFC,0x03,0x03,0x83,0x83,0x83,0x00,0x00,0x0F,0x30,0x30,0x31,0x31,0x3F,0x00, // G ++0x00,0xFF,0xC0,0xC0,0xC0,0xC0,0xFF,0x00,0x00,0x3F,0x00,0x00,0x00,0x00,0x3F,0x00, // H ++0x00,0x00,0x03,0xFF,0x03,0x00,0x00,0x00,0x00,0x00,0x30,0x3F,0x30,0x00,0x00,0x00, // I ++0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x0C,0x30,0x30,0x30,0x30,0x0F,0x00, // J ++0x00,0xFF,0xC0,0xC0,0x30,0x0C,0x03,0x00,0x00,0x3F,0x00,0x00,0x03,0x0C,0x30,0x00, // K ++0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x30,0x30,0x30,0x30,0x30,0x00, // L ++0x00,0xFF,0x0C,0xF0,0xF0,0x0C,0xFF,0x00,0x00,0x3F,0x00,0x00,0x00,0x00,0x3F,0x00, // M ++0x00,0xFF,0x0C,0xF0,0xC0,0x00,0xFF,0x00,0x00,0x3F,0x00,0x00,0x03,0x0C,0x3F,0x00, // N ++0x00,0xFC,0x03,0x03,0x03,0x03,0xFC,0x00,0x00,0x0F,0x30,0x30,0x30,0x30,0x0F,0x00, // O ++0x00,0xFF,0xC3,0xC3,0xC3,0xC3,0x3C,0x00,0x00,0x3F,0x00,0x00,0x00,0x00,0x00,0x00, // P ++0x00,0xFC,0x03,0x03,0x03,0x03,0xFC,0x00,0x00,0x0F,0x30,0x30,0x33,0x0C,0x33,0x00, // Q ++0x00,0xFF,0xC3,0xC3,0xC3,0xC3,0x3C,0x00,0x00,0x3F,0x00,0x00,0x03,0x0C,0x30,0x00, // R ++0x00,0x3C,0xC3,0xC3,0xC3,0xC3,0x0C,0x00,0x00,0x0C,0x30,0x30,0x30,0x30,0x0F,0x00, // S ++0x00,0x03,0x03,0xFF,0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x00, // T ++0x00,0xFF,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x0F,0x30,0x30,0x30,0x30,0x0F,0x00, // U ++0x00,0xFF,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x03,0x0C,0x30,0x30,0x0C,0x03,0x00, // V ++0x00,0xFF,0x00,0xC0,0xC0,0x00,0xFF,0x00,0x00,0x3F,0x0C,0x03,0x03,0x0C,0x3F,0x00, // W ++0x00,0x0F,0x30,0xC0,0xC0,0x30,0x0F,0x00,0x00,0x3C,0x03,0x00,0x00,0x03,0x3C,0x00, // X ++0x00,0x0F,0x30,0xC0,0x30,0x0F,0x00,0x00,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x00, // Y ++0x00,0x03,0x03,0xC3,0xC3,0x33,0x0F,0x00,0x00,0x3C,0x33,0x30,0x30,0x30,0x30,0x00, // Z ++0x00,0xFF,0xFF,0x03,0x03,0x03,0x03,0x00,0x00,0x3F,0x3F,0x30,0x30,0x30,0x30,0x00, // [ ++0x00,0x0C,0x30,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x0C,0x30,0x00, // ++0x00,0x03,0x03,0x03,0x03,0xFF,0xFF,0x00,0x00,0x30,0x30,0x30,0x30,0x3F,0x3F,0x00, // ] ++0x00,0x00,0xC0,0x30,0xC0,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x03,0x00,0x00, // ^ ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x30,0x30,0x30,0x30,0x00, // _ ++0x00,0x00,0x03,0x0C,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ` ++0x00,0x00,0x30,0x30,0x30,0x30,0xC0,0x00,0x00,0x0C,0x33,0x33,0x33,0x33,0x3F,0x00, // a ++0x00,0xFF,0x30,0x30,0x30,0x30,0xC0,0x00,0x00,0x3F,0x30,0x30,0x30,0x30,0x0F,0x00, // b ++0x00,0xC0,0x30,0x30,0x30,0x30,0x30,0x00,0x00,0x0F,0x30,0x30,0x30,0x30,0x30,0x00, // c ++0x00,0xC0,0x30,0x30,0x30,0x30,0xFF,0x00,0x00,0x0F,0x30,0x30,0x30,0x30,0x3F,0x00, // d ++0x00,0xC0,0x30,0x30,0x30,0x30,0xC0,0x00,0x00,0x0F,0x33,0x33,0x33,0x33,0x33,0x00, // e ++0x00,0xC0,0xFC,0xC3,0xC3,0xC3,0x0C,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x00,0x00, // f ++0x00,0xC0,0x30,0x30,0x30,0x30,0xC0,0x00,0x00,0x03,0xCC,0xCC,0xCC,0xCC,0x3F,0x00, // g ++0x00,0xFF,0x30,0x30,0x30,0x30,0xC0,0x00,0x00,0x3F,0x00,0x00,0x00,0x00,0x3F,0x00, // h ++0x00,0x00,0x30,0xF3,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x3F,0x30,0x00,0x00,0x00, // i ++0x00,0x00,0x30,0x30,0x30,0xF3,0x00,0x00,0x00,0x30,0xC0,0xC0,0xC0,0x3F,0x00,0x00, // j ++0x00,0xFF,0x00,0x00,0x00,0xC0,0x30,0x00,0x00,0x3F,0x03,0x03,0x03,0x0C,0x30,0x00, // k ++0x00,0x00,0x03,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x3F,0x30,0x00,0x00,0x00, // l ++0x00,0xF0,0x30,0xC0,0xC0,0x30,0xF0,0x00,0x00,0x3F,0x00,0x0F,0x0F,0x00,0x3F,0x00, // m ++0x00,0xF0,0x30,0x30,0x30,0x30,0xC0,0x00,0x00,0x3F,0x00,0x00,0x00,0x00,0x3F,0x00, // n ++0x00,0xC0,0x30,0x30,0x30,0x30,0xC0,0x00,0x00,0x0F,0x30,0x30,0x30,0x30,0x0F,0x00, // o ++0x00,0xF0,0x30,0x30,0x30,0x30,0xC0,0x00,0x00,0xFF,0x0C,0x0C,0x0C,0x0C,0x03,0x00, // p ++0x00,0xC0,0x30,0x30,0x30,0x30,0xF0,0x00,0x00,0x03,0x0C,0x0C,0x0C,0x0C,0xFF,0x00, // q ++0x00,0xF0,0xC0,0x30,0x30,0x30,0x30,0x00,0x00,0x3F,0x00,0x00,0x00,0x00,0x00,0x00, // r ++0x00,0xC0,0x30,0x30,0x30,0x30,0x30,0x00,0x00,0x30,0x33,0x33,0x33,0x33,0x0C,0x00, // s ++0x00,0x30,0x30,0xFF,0x30,0x30,0x00,0x00,0x00,0x00,0x00,0x0F,0x30,0x30,0x0C,0x00, // t ++0x00,0xF0,0x00,0x00,0x00,0x00,0xF0,0x00,0x00,0x0F,0x30,0x30,0x30,0x0C,0x3F,0x00, // u ++0x00,0xF0,0x00,0x00,0x00,0x00,0xF0,0x00,0x00,0x03,0x0C,0x30,0x30,0x0C,0x03,0x00, // v ++0x00,0xF0,0x00,0x00,0x00,0x00,0xF0,0x00,0x00,0x3F,0x30,0x0F,0x0F,0x30,0x3F,0x00, // w ++0x00,0x30,0xC0,0x00,0x00,0xC0,0x30,0x00,0x00,0x30,0x0C,0x03,0x03,0x0C,0x30,0x00, // x ++0x00,0xF0,0x00,0x00,0x00,0x00,0xF0,0x00,0x00,0x03,0xCC,0xCC,0xCC,0xCC,0x3F,0x00, // y ++0x00,0x30,0x30,0x30,0x30,0xF0,0x30,0x00,0x00,0x30,0x3C,0x33,0x33,0x30,0x30,0x00, // z ++0x00,0xC0,0xC0,0xFC,0x3F,0x03,0x03,0x00,0x00,0x00,0x00,0x0F,0x3F,0x30,0x30,0x00, // { ++0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x00, // | ++0x00,0x03,0x03,0x3F,0xFC,0xC0,0xC0,0x00,0x00,0x30,0x30,0x3F,0x0F,0x00,0x00,0x00, // } ++0x00,0xC0,0x30,0xC0,0x00,0xF0,0x00,0x00,0x00,0x03,0x00,0x00,0x03,0x00,0x00,0x00, // ~ ++0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x30,0x00,0x30,0x00, // ... ++}; +diff -ruN main/drivers/auxdisplay/openvfd/controllers/gfx_mono_ctrl.c mod/drivers/auxdisplay/openvfd/controllers/gfx_mono_ctrl.c +--- main/drivers/auxdisplay/openvfd/controllers/gfx_mono_ctrl.c 1970-01-01 01:00:00.000000000 +0100 ++++ mod/drivers/auxdisplay/openvfd/controllers/gfx_mono_ctrl.c 2023-03-07 09:42:01.557533567 +0100 +@@ -0,0 +1,986 @@ ++#include "gfx_mono_ctrl.h" ++#include "fonts/Grotesk16x32_h.h" ++#include "fonts/Grotesk16x32_v.h" ++#include "fonts/Grotesk24x48_v.h" ++#include "fonts/Grotesk32x64_h.h" ++#include "fonts/Retro8x16_v.h" ++#include "fonts/icons16x16_v.h" ++#include "fonts/icons32x32_h.h" ++#include "fonts/icons32x32_v.h" ++ ++static unsigned char gfx_mono_ctrl_init(void); ++static unsigned short gfx_mono_ctrl_get_brightness_levels_count(void); ++static unsigned short gfx_mono_ctrl_get_brightness_level(void); ++static unsigned char gfx_mono_ctrl_set_brightness_level(unsigned short level); ++static unsigned char gfx_mono_ctrl_get_power(void); ++static void gfx_mono_ctrl_set_power(unsigned char state); ++static void gfx_mono_ctrl_power_suspend(void) { gfx_mono_ctrl_set_power(0); } ++static void gfx_mono_ctrl_power_resume(void) { gfx_mono_ctrl_init(); } ++static struct vfd_display *gfx_mono_ctrl_get_display_type(void); ++static unsigned char gfx_mono_ctrl_set_display_type(struct vfd_display *display); ++static void gfx_mono_ctrl_set_icon(const char *name, unsigned char state); ++static size_t gfx_mono_ctrl_read_data(unsigned char *data, size_t length); ++static size_t gfx_mono_ctrl_write_data(const unsigned char *data, size_t length); ++static size_t gfx_mono_ctrl_write_display_data(const struct vfd_display_data *data); ++ ++static struct controller_interface gfx_mono_ctrl_interface = { ++ .init = gfx_mono_ctrl_init, ++ .get_brightness_levels_count = gfx_mono_ctrl_get_brightness_levels_count, ++ .get_brightness_level = gfx_mono_ctrl_get_brightness_level, ++ .set_brightness_level = gfx_mono_ctrl_set_brightness_level, ++ .get_power = gfx_mono_ctrl_get_power, ++ .set_power = gfx_mono_ctrl_set_power, ++ .power_suspend = gfx_mono_ctrl_power_suspend, ++ .power_resume = gfx_mono_ctrl_power_resume, ++ .get_display_type = gfx_mono_ctrl_get_display_type, ++ .set_display_type = gfx_mono_ctrl_set_display_type, ++ .set_icon = gfx_mono_ctrl_set_icon, ++ .read_data = gfx_mono_ctrl_read_data, ++ .write_data = gfx_mono_ctrl_write_data, ++ .write_display_data = gfx_mono_ctrl_write_display_data, ++}; ++ ++#define MAX_INDICATORS 4 ++ ++enum display_modes { ++ DISPLAY_MODE_296x128, ++ DISPLAY_MODE_200x200, ++ DISPLAY_MODE_128x32, ++ DISPLAY_MODE_96x32, ++ DISPLAY_MODE_80x32, ++ DISPLAY_MODE_80x48, ++ DISPLAY_MODE_64x48, ++ DISPLAY_MODE_128x64, ++ DISPLAY_MODE_96x64, ++ DISPLAY_MODE_80x64, ++ DISPLAY_MODE_64x64, ++}; ++ ++enum indicator_icons { ++ INDICATOR_ICON_NONE = 1, ++ INDICATOR_ICON_CHANNEL, ++ INDICATOR_ICON_TEMP, ++ INDICATOR_ICON_CALENDAR, ++ INDICATOR_ICON_MEDIA, ++ INDICATOR_ICON_TV, ++ INDICATOR_ICON_ETH, ++ INDICATOR_ICON_WIFI, ++ INDICATOR_ICON_PLAY, ++ INDICATOR_ICON_PAUSE, ++ INDICATOR_ICON_USB, ++ INDICATOR_ICON_SD, ++ INDICATOR_ICON_BT, ++ INDICATOR_ICON_APPS, ++ INDICATOR_ICON_SETUP, ++}; ++ ++struct gfx_mono_ctrl_display { ++ unsigned char columns : 3; ++ unsigned char rows : 3; ++ unsigned char offset : 2; ++ ++ unsigned char reserved1; ++ ++ unsigned char flags_secs : 1; ++ unsigned char reserved2 : 1; ++ unsigned char flags_transpose : 1; ++ unsigned char reserved3 : 5; ++ ++ unsigned char controller; ++}; ++ ++struct indicators { ++ unsigned int usb : 1; ++ unsigned int sd : 1; ++ unsigned int play : 1; ++ unsigned int pause : 1; ++ unsigned int eth : 1; ++ unsigned int wifi : 1; ++ unsigned int bt : 1; ++ unsigned int apps : 1; ++ unsigned int setup : 1; ++ unsigned int reserved : 23; ++}; ++ ++static void setup_fonts(void); ++static void init_font(struct font *font_struct, const unsigned char *font_bitmaps); ++static void init_rect(struct rect *rect, const struct font *font, const char *str, unsigned char x, unsigned char y, unsigned char transposed); ++static unsigned char print_icon(unsigned char ch); ++static void print_indicator(unsigned char ch, unsigned char state, unsigned char index); ++static void print_clock(const struct vfd_display_data *data, unsigned char print_seconds); ++static void print_channel(const struct vfd_display_data *data); ++static void print_playback_time(const struct vfd_display_data *data); ++static void print_title(const struct vfd_display_data *data); ++static void print_date(const struct vfd_display_data *data); ++static void print_temperature(const struct vfd_display_data *data); ++static void print_char(char ch, const struct font *font_struct, unsigned char x, unsigned char y); ++ ++static struct vfd_dev *dev = NULL; ++static unsigned char columns = 128; ++static unsigned char rows = 32 / 8; ++static unsigned char col_offset = 0; ++static unsigned char show_colon = 1; ++static unsigned char show_icons = 1; ++static unsigned char swap_banks_orientation = 0; ++static enum display_modes display_mode = DISPLAY_MODE_128x32; ++static unsigned char icon_x_offset = 0; ++static unsigned char indicators_on_screen[MAX_INDICATORS] = { 0 }; ++static unsigned char ram_buffer[5000] = { 0 }; ++static struct vfd_display_data old_data; ++static struct font font_text = { 0 }; ++static struct font font_icons = { 0 }; ++static struct font font_indicators = { 0 }; ++static struct font font_small_text = { 0 }; ++static struct indicators indicators = { 0 }; ++static struct gfx_mono_ctrl_display gfx_mono_ctrl_display; ++ ++static struct specific_gfx_mono_ctrl specific_gfx_mono_ctrl; ++ ++struct controller_interface *init_gfx_mono_ctrl(struct vfd_dev *_dev, const struct specific_gfx_mono_ctrl *_specific_gfx_mono_ctrl) ++{ ++ dev = _dev; ++ specific_gfx_mono_ctrl = *_specific_gfx_mono_ctrl; ++ memcpy(&gfx_mono_ctrl_display, &dev->dtb_active.display, sizeof(gfx_mono_ctrl_display)); ++ if (specific_gfx_mono_ctrl.screen_view) { ++ columns = specific_gfx_mono_ctrl.screen_view->columns; ++ rows = specific_gfx_mono_ctrl.screen_view->rows; ++ col_offset = specific_gfx_mono_ctrl.screen_view->colomn_offset; ++ swap_banks_orientation = specific_gfx_mono_ctrl.screen_view->swap_banks_orientation; ++ } else { ++ columns = (gfx_mono_ctrl_display.columns + 1) * 16; ++ rows = gfx_mono_ctrl_display.rows + 1; ++ col_offset = gfx_mono_ctrl_display.offset << 1; ++ } ++ memset(&old_data, 0, sizeof(old_data)); ++ ++ setup_fonts(); ++ if (specific_gfx_mono_ctrl.init) ++ gfx_mono_ctrl_interface.init = specific_gfx_mono_ctrl.init; ++ if (specific_gfx_mono_ctrl.set_display_type) ++ gfx_mono_ctrl_interface.set_display_type = specific_gfx_mono_ctrl.set_display_type; ++ if (!specific_gfx_mono_ctrl.print_char) ++ specific_gfx_mono_ctrl.print_char = print_char; ++ return &gfx_mono_ctrl_interface; ++} ++ ++static void print_char(char ch, const struct font *font_struct, unsigned char x, unsigned char y) ++{ ++ unsigned short offset = 0, i; ++ if (x >= columns || y >= rows || ch < font_struct->font_offset || ch >= font_struct->font_offset + font_struct->font_char_count) ++ return; ++ ++ ch -= font_struct->font_offset; ++ offset = ch * font_struct->font_char_size; ++ offset += 4; ++ for (i = 0; i < font_struct->font_height; i++) { ++ specific_gfx_mono_ctrl.set_xy(x, y + i); ++ specific_gfx_mono_ctrl.write_ctrl_data_buf(&font_struct->font_bitmaps[offset], font_struct->font_width); ++ offset += font_struct->font_width; ++ } ++} ++ ++extern void transpose8rS64(unsigned char* A, unsigned char* B); ++ ++#define GFX_MONO_CTRL_PRINT_DEBUG 0 ++ ++#if GFX_MONO_CTRL_PRINT_DEBUG ++unsigned char print_buffer_cnt = 30; ++char txt_buf[204800] = { 0 }; ++static void print_buffer(unsigned char *buf, const struct rect *rect, unsigned char rotate) ++{ ++ char *t = txt_buf; ++ if (!print_buffer_cnt) ++ return; ++ print_buffer_cnt--; ++ if (rotate) ++ pr_dbg2("Transposed Buffer:\n"); ++ else ++ pr_dbg2("Non-Transposed Buffer:\n"); ++ if (swap_banks_orientation) { ++ unsigned char height = rotate ? rect->width : rect->height; ++ unsigned char width = rotate ? rect->height : rect->width; ++ for (int j = 0; j < height; j++) { ++ t = txt_buf; ++ for (int i = 0; i < width; i++) { ++ for (int k = 0; k < 8; k++) { ++ *t++ = (buf[j * width + i] & (0x80 >> k)) ? '#' : ' '; ++ } ++ *t++ = ' '; ++ } ++ *t++ = '\0'; ++ printk(KERN_DEBUG "%s\n", txt_buf); ++ } ++ } else { ++ unsigned char height = rotate ? rect->height : rect->width / 8; ++ unsigned char width = rotate ? rect->width : rect->height * 8; ++ for (int j = 0; j < height; j++) { ++ for (int k = 0; k < 8; k++) { ++ t = txt_buf; ++ for (int i = 0; i < width; i++) { ++ if (i % 8 == 0) ++ *t++ = ' '; ++ *t++ = (buf[j * width + i] & (1 << k)) ? '#' : ' '; ++ } ++ *t++ = '\n'; ++ *t++ = '\0'; ++ printk(KERN_DEBUG "%s", txt_buf); ++ } ++ printk(KERN_DEBUG "\n"); ++ } ++ } ++ ++ printk(KERN_DEBUG "\n\n"); ++} ++#else ++static void print_buffer(unsigned char *buf, const struct rect *rect, unsigned char rotate) { } ++#endif ++ ++unsigned char t_buf[sizeof(ram_buffer)] = { 0 }; ++void transpose_buffer(unsigned char *buffer, const struct rect *rect) ++{ ++ unsigned short i; ++ if (!rect->width || !rect->height) ++ return; ++ ++ print_buffer(buffer, rect, 0); ++ if (swap_banks_orientation) { ++ unsigned char tmp[8]; ++ unsigned short x, y; ++ for (y = 0; y < rect->height; y += 8) { ++ for (x = 0; x < rect->width; x++) { ++ int s = x + y * rect->width; ++ int d = 8 * (rect->width - 1 - x) * (rect->height / 8) + (y / 8); ++ for (i = 0; i < 8; i++) ++ tmp[i] = buffer[s + (i * rect->width)]; ++ transpose8rS64(tmp, tmp); ++ for (i = 0; i < 8; i++) ++ t_buf[d + (i * rect->height / 8)] = tmp[i]; ++ } ++ } ++ } else { ++ for (i = 0; i < (rect->height * rect->width) / 8; i++) { ++ int d = (rect->height - 1 - i % rect->height) * (rect->width / 8) + (i / rect->height); ++ transpose8rS64(&buffer[i * 8], &t_buf[d * 8]); ++ } ++ } ++ memcpy(buffer, t_buf, rect->height * rect->width); ++ print_buffer(buffer, rect, 1); ++} ++ ++static void print_string(const char *str, const struct font *font_struct, unsigned char x, unsigned char y) ++{ ++ unsigned char ch = 0; ++ unsigned short soffset = 0, doffset = 0, i, j, k; ++ struct rect rect; ++ unsigned char rect_width = 0, text_width = 0; ++ init_rect(&rect, font_struct, str, x, y, gfx_mono_ctrl_display.flags_transpose); ++ if (rect.length == 0) ++ return; ++ ++ if (gfx_mono_ctrl_display.flags_transpose) { ++ rect_width = rect.height * 8; ++ text_width = rect.text_height; ++ } else { ++ rect_width = rect.width; ++ text_width = rect.text_width; ++ } ++ for (k = 0; k < rect.length; k += text_width) { ++ for (i = 0; i < font_struct->font_height; i++) { ++ for (j = 0; j < text_width; j++) { ++ doffset = k + j; ++ ch = doffset < rect.length ? str[doffset] : ' '; ++ if (ch < font_struct->font_offset || ch >= font_struct->font_offset + font_struct->font_char_count) ++ ch = ' '; ++ ch -= font_struct->font_offset; ++ soffset = ch * font_struct->font_char_size + i * font_struct->font_width; ++ soffset += 4; ++ memcpy(&ram_buffer[i * rect_width + (k * font_struct->font_height + j) * font_struct->font_width], &font_struct->font_bitmaps[soffset], font_struct->font_width); ++ } ++ } ++ } ++ ++ rect.length = rect.text_height * rect.text_width; ++ if (gfx_mono_ctrl_display.flags_transpose) ++ transpose_buffer(ram_buffer, &rect); ++ else ++ print_buffer(ram_buffer, &rect, 0); ++ specific_gfx_mono_ctrl.print_string(ram_buffer, &rect); ++} ++ ++static unsigned char prepare_and_print_string(const char *str, const struct font *font_struct, unsigned char x, unsigned char y) ++{ ++ char buffer[512]; ++ struct rect rect; ++ init_rect(&rect, font_struct, str, 0, y, 0); ++ if (rect.length > 0) { ++ if (rect.length < strlen(str)) { ++ scnprintf(buffer, sizeof(buffer), "%s", str); ++ buffer[rect.length - 1] = 0x7F; // 0x7F = position of ellipsis. ++ buffer[rect.length] = '\0'; ++ print_string(buffer, font_struct, x, y); ++ } else { ++ print_string(str, font_struct, x, y); ++ } ++ } ++ return rect.length; ++} ++ ++static void setup_fonts(void) ++{ ++ init_font(&font_indicators, icons16x16_V); ++ init_font(&font_small_text, Retro8x16_V); ++ switch (rows) { ++ case 128: ++ init_font(&font_text, Grotesk32x64_H); ++ init_font(&font_small_text, Grotesk16x32_H); ++ init_font(&font_icons, icons32x32_H); ++ init_font(&font_indicators, icons32x32_H); ++ display_mode = DISPLAY_MODE_296x128; ++ break; ++ case 200: ++ init_font(&font_text, Grotesk32x64_H); ++ init_font(&font_small_text, Grotesk16x32_H); ++ init_font(&font_icons, icons32x32_H); ++ init_font(&font_indicators, icons32x32_H); ++ display_mode = DISPLAY_MODE_200x200; ++ break; ++ case 6: ++ init_font(&font_text, Grotesk16x32_V); ++ init_font(&font_icons, icons16x16_V); ++ if (columns >= 80) { ++ display_mode = DISPLAY_MODE_80x48; ++ } else { ++ show_colon = 0; ++ display_mode = DISPLAY_MODE_64x48; ++ } ++ break; ++ case 8: ++ if (columns >= 96) { ++ init_font(&font_text, Grotesk24x48_V); ++ init_font(&font_icons, icons16x16_V); ++ if (columns >= 120) { ++ display_mode = DISPLAY_MODE_128x64; ++ } else { ++ show_colon = 0; ++ display_mode = DISPLAY_MODE_96x64; ++ } ++ } else { ++ init_font(&font_text, Grotesk16x32_V); ++ init_font(&font_icons, icons32x32_V); ++ if (columns >= 80) { ++ display_mode = DISPLAY_MODE_80x64; ++ } else { ++ show_colon = 0; ++ display_mode = DISPLAY_MODE_64x64; ++ } ++ } ++ break; ++ case 4: ++ default: ++ init_font(&font_text, Grotesk16x32_V); ++ if (columns >= 120) { ++ display_mode = DISPLAY_MODE_128x32; ++ init_font(&font_icons, icons32x32_V); ++ } else if (columns >= 96) { ++ display_mode = DISPLAY_MODE_96x32; ++ init_font(&font_icons, icons16x16_V); ++ } else if (columns >= 80) { ++ display_mode = DISPLAY_MODE_80x32; ++ show_icons = 0; ++ } else { ++ show_colon = 0; ++ show_icons = 0; ++ } ++ break; ++ } ++} ++ ++static unsigned char gfx_mono_ctrl_init(void) ++{ ++ old_data.mode = DISPLAY_MODE_NONE; ++ if (gfx_mono_ctrl_interface.init != gfx_mono_ctrl_init) ++ return gfx_mono_ctrl_interface.init(); ++ return 0; ++} ++ ++static unsigned short gfx_mono_ctrl_get_brightness_levels_count(void) ++{ ++ return 8; ++} ++ ++static unsigned short gfx_mono_ctrl_get_brightness_level(void) ++{ ++ return dev->brightness; ++} ++ ++static unsigned char gfx_mono_ctrl_set_brightness_level(unsigned short level) ++{ ++ unsigned char tmp = dev->brightness = level & 0x7; ++ dev->power = 1; ++ specific_gfx_mono_ctrl.set_contrast(tmp * 36); // ruonds to 0 - 252. ++ return 1; ++} ++ ++static unsigned char gfx_mono_ctrl_get_power(void) ++{ ++ return dev->power; ++} ++ ++static void gfx_mono_ctrl_set_power(unsigned char state) ++{ ++ specific_gfx_mono_ctrl.set_power(state); ++ dev->power = state; ++} ++ ++static struct vfd_display *gfx_mono_ctrl_get_display_type(void) ++{ ++ return &dev->dtb_active.display; ++} ++ ++static unsigned char gfx_mono_ctrl_set_display_type(struct vfd_display *display) ++{ ++ pr_dbg2("gfx_mono_ctrl_set_display_type - not implemented\n"); ++ return 0; ++} ++ ++static void gfx_mono_ctrl_set_icon(const char *name, unsigned char state) ++{ ++ enum indicator_icons icon = INDICATOR_ICON_NONE; ++ if (strncmp(name,"usb",3) == 0 && indicators.usb != state) { ++ icon = INDICATOR_ICON_USB; ++ indicators.usb = state; ++ } else if (strncmp(name,"sd",2) == 0 && indicators.sd != state) { ++ icon = INDICATOR_ICON_SD; ++ indicators.sd = state; ++ } else if (strncmp(name,"play",4) == 0 && indicators.play != state) { ++ icon = INDICATOR_ICON_PLAY; ++ indicators.play = state; ++ } else if (strncmp(name,"pause",5) == 0 && indicators.pause != state) { ++ icon = INDICATOR_ICON_PAUSE; ++ indicators.pause = state; ++ } else if (strncmp(name,"eth",3) == 0 && indicators.eth != state) { ++ icon = INDICATOR_ICON_ETH; ++ indicators.eth = state; ++ } else if (strncmp(name,"wifi",4) == 0 && indicators.wifi != state) { ++ icon = INDICATOR_ICON_WIFI; ++ indicators.wifi = state; ++ } else if (strncmp(name,"b-t",3) == 0 && indicators.bt != state) { ++ icon = INDICATOR_ICON_BT; ++ indicators.bt = state; ++ } else if (strncmp(name,"apps",4) == 0 && indicators.apps != state) { ++ icon = INDICATOR_ICON_APPS; ++ indicators.apps = state; ++ } else if (strncmp(name,"setup",5) == 0 && indicators.setup != state) { ++ icon = INDICATOR_ICON_SETUP; ++ indicators.setup = state; ++ } else if (strncmp(name,"colon",5) == 0) { ++ dev->status_led_mask = state ? (dev->status_led_mask | ledDots[LED_DOT_SEC]) : (dev->status_led_mask & ~ledDots[LED_DOT_SEC]); ++ } ++ ++ switch (icon) { ++ case INDICATOR_ICON_USB: ++ if (!indicators.usb && indicators.sd) ++ print_indicator(INDICATOR_ICON_SD, 1, 2); ++ else ++ print_indicator(INDICATOR_ICON_USB, indicators.usb, 2); ++ break; ++ case INDICATOR_ICON_SD: ++ if (!indicators.usb) ++ print_indicator(INDICATOR_ICON_SD, indicators.sd, 2); ++ break; ++ case INDICATOR_ICON_PLAY: ++ if (!indicators.play && indicators.pause) ++ print_indicator(INDICATOR_ICON_PAUSE, 1, 1); ++ else ++ print_indicator(INDICATOR_ICON_PLAY, indicators.play, 1); ++ break; ++ case INDICATOR_ICON_PAUSE: ++ if (!indicators.pause && indicators.play) ++ print_indicator(INDICATOR_ICON_PLAY, 1, 1); ++ else ++ print_indicator(INDICATOR_ICON_PAUSE, indicators.pause, 1); ++ break; ++ case INDICATOR_ICON_ETH: ++ if (!indicators.eth && indicators.wifi) ++ print_indicator(INDICATOR_ICON_WIFI, 1, 0); ++ else ++ print_indicator(INDICATOR_ICON_ETH, indicators.eth, 0); ++ break; ++ case INDICATOR_ICON_WIFI: ++ if (!indicators.eth) ++ print_indicator(INDICATOR_ICON_WIFI, indicators.wifi, 0); ++ break; ++ case INDICATOR_ICON_BT: ++ case INDICATOR_ICON_APPS: ++ case INDICATOR_ICON_SETUP: ++ if (indicators.setup) ++ print_indicator(INDICATOR_ICON_SETUP, indicators.setup, 3); ++ else if (indicators.apps) ++ print_indicator(INDICATOR_ICON_APPS, indicators.apps, 3); ++ else ++ print_indicator(INDICATOR_ICON_BT, indicators.bt, 3); ++ break; ++ default: ++ break; ++ } ++} ++ ++static size_t gfx_mono_ctrl_read_data(unsigned char *data, size_t length) ++{ ++ return 0; ++} ++ ++static size_t gfx_mono_ctrl_write_data(const unsigned char *_data, size_t length) ++{ ++ return length; ++} ++ ++static size_t gfx_mono_ctrl_write_display_data(const struct vfd_display_data *data) ++{ ++ size_t status = sizeof(*data); ++ if (data->mode != old_data.mode) { ++ unsigned char i; ++ icon_x_offset = 0; ++ memset(&old_data, 0, sizeof(old_data)); ++ specific_gfx_mono_ctrl.clear(); ++ switch (data->mode) { ++ case DISPLAY_MODE_CLOCK: ++ old_data.mode = DISPLAY_MODE_CLOCK; ++ for (i = 0; i < MAX_INDICATORS; i++) ++ print_indicator(indicators_on_screen[i], 1, i); ++ old_data.mode = 0; ++ break; ++ case DISPLAY_MODE_DATE: ++ if (show_icons) ++ icon_x_offset = print_icon(INDICATOR_ICON_CALENDAR); ++ break; ++ case DISPLAY_MODE_CHANNEL: ++ if (show_icons) ++ icon_x_offset = print_icon(INDICATOR_ICON_CHANNEL); ++ break; ++ case DISPLAY_MODE_PLAYBACK_TIME: ++ if (show_icons) ++ icon_x_offset = print_icon(INDICATOR_ICON_MEDIA); ++ break; ++ case DISPLAY_MODE_TITLE: ++ break; ++ case DISPLAY_MODE_TEMPERATURE: ++ if (show_icons) ++ icon_x_offset = print_icon(INDICATOR_ICON_TEMP); ++ break; ++ default: ++ status = 0; ++ break; ++ } ++ } ++ ++ switch (data->mode) { ++ case DISPLAY_MODE_CLOCK: ++ print_clock(data, 1); ++ break; ++ case DISPLAY_MODE_DATE: ++ print_date(data); ++ break; ++ case DISPLAY_MODE_CHANNEL: ++ print_channel(data); ++ break; ++ case DISPLAY_MODE_PLAYBACK_TIME: ++ print_playback_time(data); ++ break; ++ case DISPLAY_MODE_TITLE: ++ print_title(data); ++ break; ++ case DISPLAY_MODE_TEMPERATURE: ++ print_temperature(data); ++ break; ++ default: ++ status = 0; ++ break; ++ } ++ ++ old_data = *data; ++ return status; ++} ++ ++static unsigned char print_icon(unsigned char ch) ++{ ++ char str[] = { ch, 0 }; ++ unsigned char offset_x = 0; ++ unsigned char x, y; ++ switch (display_mode) { ++ case DISPLAY_MODE_128x32: ++ y = (rows - font_icons.font_height) / 2; ++ print_string(str, &font_icons, 0, y); ++ offset_x = font_icons.font_width + font_text.font_width / 2; ++ break; ++ case DISPLAY_MODE_96x32 : ++ y = (rows - font_icons.font_height) / 2; ++ print_string(str, &font_icons, 0, y); ++ offset_x = font_icons.font_width; ++ break; ++ case DISPLAY_MODE_80x32 : ++ break; ++ case DISPLAY_MODE_64x48 : ++ case DISPLAY_MODE_64x64 : ++ case DISPLAY_MODE_96x64 : ++ print_string(str, &font_icons, 0, font_text.font_height); ++ break; ++ case DISPLAY_MODE_296x128: ++ case DISPLAY_MODE_200x200: ++ case DISPLAY_MODE_80x48 : ++ case DISPLAY_MODE_128x64: ++ case DISPLAY_MODE_80x64 : ++ x = (columns - font_icons.font_width) / 2; ++ print_string(str, &font_icons, x, font_text.font_height); ++ break; ++ } ++ ++ return offset_x; ++} ++ ++static void print_indicator(unsigned char ch, unsigned char state, unsigned char index) ++{ ++ char str[] = { state ? ch : INDICATOR_ICON_NONE, 0 }; ++ unsigned char x, y; ++ if (index >= MAX_INDICATORS) ++ return; ++ ++ indicators_on_screen[index] = str[0]; ++ if (old_data.mode == DISPLAY_MODE_CLOCK) { ++ switch (display_mode) { ++ case DISPLAY_MODE_296x128: ++ case DISPLAY_MODE_128x32: ++ { ++ char size = (columns - (font_text.font_width * 5)) / 2; ++ x = (size - font_indicators.font_width) / 2; ++ if (index >= 2) ++ x += size + (font_text.font_width * 5); ++ y = font_indicators.font_height * (index % 2); ++ print_string(str, &font_indicators, x, y); ++ break; ++ } ++ case DISPLAY_MODE_96x32 : ++ case DISPLAY_MODE_80x32 : ++ break; ++ case DISPLAY_MODE_64x48 : ++ case DISPLAY_MODE_64x64 : ++ case DISPLAY_MODE_96x64 : ++ case DISPLAY_MODE_80x48 : ++ case DISPLAY_MODE_128x64: ++ case DISPLAY_MODE_80x64 : ++ x = columns / MAX_INDICATORS; ++ x = (x - font_indicators.font_width) / 2 + index * x; ++ print_string(str, &font_indicators, x, font_text.font_height); ++ break; ++ case DISPLAY_MODE_200x200: ++ x = columns / MAX_INDICATORS; ++ x = (x - font_indicators.font_width) / 2 + index * x; ++ print_string(str, &font_indicators, x, font_text.font_height + ((font_small_text.font_height * 5) / 2)); ++ break; ++ } ++ } ++} ++ ++static void print_clock_date(const struct vfd_display_data *data, unsigned char force_print) ++{ ++ if ((rows == 128 || rows == 200) && !gfx_mono_ctrl_display.flags_transpose) ++ { ++ force_print |= data->time_date.day != old_data.time_date.day || data->time_date.month != old_data.time_date.month || data->time_date.year != old_data.time_date.year; ++ if (force_print) ++ { ++ char buffer[20]; ++ const char *days[7] = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" }; ++ const char *months[12] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", ++ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; ++ int len = scnprintf(buffer, sizeof(buffer), "%s %02d, %04d", months[data->time_date.month], data->time_date.day, data->time_date.year); ++ unsigned char offset = (columns - (len * font_small_text.font_width)) / 2; ++ print_string(buffer, &font_small_text, offset, font_text.font_height); ++ len = scnprintf(buffer, sizeof(buffer), "%s", days[data->time_date.day_of_week]); ++ offset = (columns - (len * font_small_text.font_width)) / 2; ++ print_string(buffer, &font_small_text, offset, font_text.font_height + font_small_text.font_height); ++ } ++ } ++} ++ ++static void print_clock(const struct vfd_display_data *data, unsigned char print_seconds) ++{ ++ char buffer[10]; ++ unsigned char force_print = old_data.mode == DISPLAY_MODE_NONE; ++ unsigned char offset = 0; ++ unsigned char colon_on = data->colon_on || dev->status_led_mask & ledDots[LED_DOT_SEC] ? 1 : 0; ++ print_seconds &= gfx_mono_ctrl_display.flags_secs & show_colon; ++ if (gfx_mono_ctrl_display.flags_transpose) { ++ if (force_print || data->time_date.minutes != old_data.time_date.minutes || ++ data->time_date.hours != old_data.time_date.hours) { ++ offset = (columns - (font_text.font_height * 8 * 2 + show_colon * font_text.font_width)) / 2; ++ scnprintf(buffer, sizeof(buffer), "%02d", data->time_date.hours); ++ print_string(buffer, &font_text, offset, 0); ++ scnprintf(buffer, sizeof(buffer), "%02d", data->time_date.minutes); ++ print_string(buffer, &font_text, offset + show_colon * font_text.font_width + (font_text.font_height * 8), 0); ++ } ++ if (colon_on != old_data.colon_on && show_colon) { ++ unsigned char offset = (columns - font_text.font_width) / 2; ++ specific_gfx_mono_ctrl.print_char(colon_on ? ':' : ' ', &font_text, offset, rows - font_text.font_height); ++ } ++ } else if (!force_print) { ++ const int len = print_seconds ? 8 : 5; ++ offset = (columns - (font_text.font_width * len)) / 2; ++ if (data->time_date.hours != old_data.time_date.hours) { ++ scnprintf(buffer, sizeof(buffer), "%02d", data->time_date.hours); ++ print_string(buffer, &font_text, offset, 0); ++ } ++ offset += 2 * font_text.font_width; ++ if (show_colon) { ++ if (colon_on != old_data.colon_on) ++ specific_gfx_mono_ctrl.print_char(colon_on ? ':' : ' ', &font_text, offset, 0); ++ offset += font_text.font_width; ++ } ++ if (data->time_date.minutes != old_data.time_date.minutes) { ++ scnprintf(buffer, sizeof(buffer), "%02d", data->time_date.minutes); ++ print_string(buffer, &font_text, offset, 0); ++ } ++ offset += 2 * font_text.font_width; ++ if (print_seconds) { ++ if (colon_on != old_data.colon_on) ++ specific_gfx_mono_ctrl.print_char(colon_on ? ':' : ' ', &font_text, offset, 0); ++ offset += font_text.font_width; ++ if (data->time_date.seconds != old_data.time_date.seconds) { ++ scnprintf(buffer, sizeof(buffer), "%02d", data->time_date.seconds); ++ print_string(buffer, &font_text, offset + (6 * font_text.font_width), 0); ++ } ++ } ++ } else if (print_seconds) { ++ int len = scnprintf(buffer, sizeof(buffer), "%02d%c%02d%c%02d", data->time_date.hours, colon_on ? ':' : ' ', data->time_date.minutes, ++ colon_on ? ':' : ' ', data->time_date.seconds); ++ offset = (columns - (font_text.font_width * len)) / 2; ++ print_string(buffer, &font_text, offset, 0); ++ } else { ++ int len; ++ if (show_colon) ++ len = scnprintf(buffer, sizeof(buffer), "%02d%c%02d", data->time_date.hours, colon_on ? ':' : ' ', data->time_date.minutes); ++ else ++ len = scnprintf(buffer, sizeof(buffer), "%02d%02d", data->time_date.hours, data->time_date.minutes); ++ offset = (columns - (font_text.font_width * len)) / 2; ++ print_string(buffer, &font_text, offset, 0); ++ } ++ print_clock_date(data, force_print); ++} ++ ++static void print_channel(const struct vfd_display_data *data) ++{ ++ char buffer[10]; ++ scnprintf(buffer, sizeof(buffer), "%*d", 4, data->channel_data.channel % 10000); ++ print_string(buffer, &font_text, font_icons.font_width + (font_text.font_width / 2), 0); ++} ++ ++static void print_playback_time(const struct vfd_display_data *data) ++{ ++ char buffer[20]; ++ unsigned char offset = icon_x_offset ? icon_x_offset : (columns - (show_colon * font_text.font_width + font_text.font_width * 4)) / 2; ++ unsigned char force_print = old_data.mode == DISPLAY_MODE_NONE || data->time_date.hours != old_data.time_date.hours; ++ if (gfx_mono_ctrl_display.flags_transpose) { ++ if (data->time_date.hours > 0) { ++ if (force_print || data->time_date.minutes != old_data.time_date.minutes || ++ data->time_date.hours != old_data.time_date.hours) { ++ scnprintf(buffer, sizeof(buffer), "%02d", data->time_date.hours); ++ print_string(buffer, &font_text, offset, 0); ++ scnprintf(buffer, sizeof(buffer), "%02d", data->time_date.minutes); ++ print_string(buffer, &font_text, offset + show_colon * font_text.font_width + (font_text.font_height * 8), 0); ++ } ++ } else { ++ if (force_print || data->time_date.seconds != old_data.time_date.seconds || ++ data->time_date.minutes != old_data.time_date.minutes) { ++ scnprintf(buffer, sizeof(buffer), "%02d", data->time_date.minutes); ++ print_string(buffer, &font_text, offset, 0); ++ scnprintf(buffer, sizeof(buffer), "%02d", data->time_date.seconds); ++ print_string(buffer, &font_text, offset + show_colon * font_text.font_width + (font_text.font_height * 8), 0); ++ } ++ } ++ if (show_colon) ++ specific_gfx_mono_ctrl.print_char(data->colon_on ? ':' : ' ', &font_text, offset + (font_text.font_height * 8), rows - font_text.font_height); ++ } else if (!force_print) { ++ if (data->colon_on != old_data.colon_on && show_colon) { ++ specific_gfx_mono_ctrl.print_char(data->colon_on ? ':' : ' ', &font_text, offset + (2 * font_text.font_width), 0); ++ } ++ if (data->time_date.hours > 0) { ++ if (data->time_date.hours != old_data.time_date.hours) { ++ scnprintf(buffer, sizeof(buffer), "%02d", data->time_date.hours); ++ print_string(buffer, &font_text, offset, 0); ++ } ++ if (data->time_date.minutes != old_data.time_date.minutes) { ++ scnprintf(buffer, sizeof(buffer), "%02d", data->time_date.minutes); ++ print_string(buffer, &font_text, offset + (show_colon * font_text.font_width + 2 * font_text.font_width), 0); ++ } ++ } else { ++ if (data->time_date.minutes != old_data.time_date.minutes) { ++ scnprintf(buffer, sizeof(buffer), "%02d", data->time_date.minutes); ++ print_string(buffer, &font_text, offset, 0); ++ } ++ if (data->time_date.seconds != old_data.time_date.seconds) { ++ scnprintf(buffer, sizeof(buffer), "%02d", data->time_date.seconds); ++ print_string(buffer, &font_text, offset + (show_colon * font_text.font_width + 2 * font_text.font_width), 0); ++ } ++ } ++ } else { ++ unsigned char pos0, pos1; ++ if (data->time_date.hours > 0) { ++ pos0 = data->time_date.hours; ++ pos1 = data->time_date.minutes; ++ } else { ++ pos0 = data->time_date.minutes; ++ pos1 = data->time_date.seconds; ++ } ++ if (show_colon) ++ scnprintf(buffer, sizeof(buffer), "%02d%c%02d", pos0, data->colon_on ? ':' : ' ', pos1); ++ else ++ scnprintf(buffer, sizeof(buffer), "%02d%02d", pos0, pos1); ++ print_string(buffer, &font_text, offset, 0); ++ } ++ if (rows >= 6 && !gfx_mono_ctrl_display.flags_transpose && strcmp(data->string_main, old_data.string_main)) { ++ struct rect rect; ++ offset = show_icons * font_icons.font_width; ++ init_rect(&rect, &font_small_text, data->string_main, offset, font_text.font_height, 0); ++ if (rect.length > 0) { ++ if (show_icons) { ++ print_icon(INDICATOR_ICON_NONE); ++ buffer[0] = INDICATOR_ICON_MEDIA; ++ buffer[1] = '\0'; ++ print_string(buffer, &font_icons, 0, font_text.font_height); ++ } ++ if (rect.length < strlen(data->string_main)) { ++ scnprintf(buffer, sizeof(buffer), "%s", data->string_main); ++ buffer[rect.length - 1] = 0x7F; // 0x7F = position of ellipsis. ++ buffer[rect.length] = '\0'; ++ print_string(buffer, &font_small_text, offset, font_text.font_height); ++ } else { ++ print_string(data->string_main, &font_small_text, offset, font_text.font_height); ++ } ++ } ++ } ++} ++ ++static void print_title(const struct vfd_display_data *data) ++{ ++ unsigned char offset = (unsigned char)max((size_t)0, (columns - (font_text.font_width * strlen(data->string_main))) / 2); ++ if (strlen(data->string_secondary) > 0 && prepare_and_print_string(data->string_main, &font_text, offset, font_small_text.font_height)) ++ prepare_and_print_string(data->string_secondary, &font_small_text, 0, 0); ++ else ++ prepare_and_print_string(data->string_main, &font_text, offset, 0); ++} ++ ++static void print_date(const struct vfd_display_data *data) ++{ ++ char buffer[10]; ++ unsigned char force_print = old_data.mode == DISPLAY_MODE_NONE || data->time_date.day != old_data.time_date.day || data->time_date.month != old_data.time_date.month; ++ unsigned char offset = icon_x_offset ? icon_x_offset : (columns - (show_colon * font_text.font_width + font_text.font_width * 4)) / 2; ++ if (force_print) { ++ if (gfx_mono_ctrl_display.flags_transpose) { ++ scnprintf(buffer, sizeof(buffer), "%02d", data->time_secondary._reserved ? data->time_date.month + 1 : data->time_date.day); ++ print_string(buffer, &font_text, offset, 0); ++ scnprintf(buffer, sizeof(buffer), "%02d", data->time_secondary._reserved ? data->time_date.day : data->time_date.month + 1); ++ print_string(buffer, &font_text, offset + show_colon * font_text.font_width + (font_text.font_height * 8), 0); ++ if (show_colon) ++ specific_gfx_mono_ctrl.print_char('|', &font_text, offset + font_text.font_height * 8, rows - font_text.font_height); ++ } else { ++ unsigned char day, month; ++ if (data->time_secondary._reserved) { ++ day = data->time_date.month + 1; ++ month = data->time_date.day; ++ } else { ++ day = data->time_date.day; ++ month = data->time_date.month + 1; ++ } ++ if (show_colon) ++ scnprintf(buffer, sizeof(buffer), "%02d/%02d", day, month); ++ else ++ scnprintf(buffer, sizeof(buffer), "%02d%02d", day, month); ++ print_string(buffer, &font_text, offset, 0); ++ } ++ } ++} ++ ++static void print_temperature(const struct vfd_display_data *data) ++{ ++ char buffer[10]; ++ if (data->temperature != old_data.temperature) { ++ if (gfx_mono_ctrl_display.flags_transpose) { ++ unsigned char offset = icon_x_offset ? icon_x_offset : (columns - (2 * 8 * font_text.font_height)) / 2; ++ scnprintf(buffer, sizeof(buffer), "%02d", data->temperature % 100); ++ print_string(buffer, &font_text, offset, 0); ++ scnprintf(buffer, sizeof(buffer), "%cC", 0x7F); // 0x7F = position of degree. ++ print_string(buffer, &font_text, offset + 8 * font_text.font_height, 0); ++ } else { ++ size_t len = scnprintf(buffer, sizeof(buffer), "%d%cC", data->temperature % 1000, 0x7F); // 0x7F = position of degree. ++ unsigned char offset = icon_x_offset ? icon_x_offset : (columns - (len * font_text.font_width)) / 2; ++ print_string(buffer, &font_text, offset, 0); ++ } ++ } ++} ++ ++static void init_font(struct font *font_struct, const unsigned char *font_bitmaps) ++{ ++ if (swap_banks_orientation) { ++ font_struct->font_width = font_bitmaps[0] / 8; ++ font_struct->font_height = font_bitmaps[1]; ++ } else { ++ font_struct->font_width = font_bitmaps[0]; ++ font_struct->font_height = font_bitmaps[1] / 8; ++ } ++ font_struct->font_offset = font_bitmaps[2]; ++ font_struct->font_char_size = font_struct->font_height * font_struct->font_width; ++ font_struct->font_char_count = font_bitmaps[3]; ++ font_struct->font_bitmaps = font_bitmaps; ++#if GFX_MONO_CTRL_PRINT_DEBUG ++ pr_dbg2("font_width = %d, font_height = %d, font_offset = %d, font_char_size = %d, font_char_count = %d\n", ++ font_struct->font_width, font_struct->font_height, font_struct->font_offset, font_struct->font_char_size, font_struct->font_char_count); ++#endif ++} ++ ++static void init_rect(struct rect *rect, const struct font *font, const char *str, unsigned char x, unsigned char y, unsigned char transposed) ++{ ++ unsigned char c_width = 0, c_height = 0; ++ memset(rect, 0, sizeof(*rect)); ++ if (x < columns && y < rows) { ++ rect->font = font; ++ if (!transposed) { ++ rect->x1 = x; ++ rect->y1 = y; ++ rect->width = columns - x; ++ rect->height = rows - y; ++ c_width = rect->width / font->font_width; ++ c_height = rect->height / font->font_height; ++ rect->length = (unsigned char)min(strlen(str), (size_t)(c_width * c_height)); ++ rect->text_width = min(c_width, rect->length); ++ for (rect->text_height = 0; rect->text_height < c_height; rect->text_height++) ++ if (rect->text_width * rect->text_height >= rect->length) ++ break; ++ rect->width = rect->text_width * font->font_width; ++ rect->height = rect->text_height * font->font_height; ++ rect->x2 = x + rect->width - 1; ++ rect->y2 = y + rect->height - 1; ++ } else { ++ const unsigned short font_height = font->font_height * 8; ++ const unsigned short font_width = font->font_width / 8; ++ rect->width = columns - x; ++ rect->height = rows - y; ++ c_width = rect->width / font_height; ++ c_height = rect->height / font_width; ++ rect->length = (unsigned char)min(strlen(str), (size_t)(c_width * c_height)); ++ rect->text_height = min(rect->length, c_height); ++ for (rect->text_width = 0; rect->text_width < c_width; rect->text_width++) ++ if (rect->text_width * rect->text_height >= rect->length) ++ break; ++ rect->width = rect->text_width * font_height; ++ rect->height = rect->text_height * font_width; ++ rect->x1 = x; ++ rect->y2 = rows - 1 - y; ++ rect->x2 = rect->x1 + rect->width - 1; ++ rect->y1 = rect->y2 - rect->height + 1; ++ } ++ } ++ ++#if GFX_MONO_CTRL_PRINT_DEBUG ++ pr_dbg2("str = %s, x = %d, y = %d, transposed = %d, c_width = %d, c_height = %d, length = %d, xy1 = (%d,%d), xy2 = (%d,%d), size = (%d,%d), text size = (%d,%d)\n", ++ str, x, y, transposed, c_width, c_height, rect->length, rect->x1, rect->y1, rect->x2, rect->y2, rect->width, rect->height, rect->text_width, rect->text_height); ++#endif ++} +diff -ruN main/drivers/auxdisplay/openvfd/controllers/gfx_mono_ctrl.h mod/drivers/auxdisplay/openvfd/controllers/gfx_mono_ctrl.h +--- main/drivers/auxdisplay/openvfd/controllers/gfx_mono_ctrl.h 1970-01-01 01:00:00.000000000 +0100 ++++ mod/drivers/auxdisplay/openvfd/controllers/gfx_mono_ctrl.h 2023-03-07 09:42:01.569533660 +0100 +@@ -0,0 +1,58 @@ ++#ifndef __GFXMONOCTRLH__ ++#define __GFXMONOCTRLH__ ++ ++#include "controller.h" ++ ++struct font { ++ unsigned char font_height; ++ unsigned char font_width; ++ unsigned short font_char_size; ++ unsigned char font_offset; ++ unsigned char font_char_count; ++ const unsigned char *font_bitmaps; ++}; ++ ++struct rect { ++ unsigned short x1; ++ unsigned short y1; ++ unsigned short x2; ++ unsigned short y2; ++ unsigned short width; ++ unsigned short height; ++ unsigned char text_width; ++ unsigned char text_height; ++ unsigned char length; ++ const struct font *font; ++}; ++ ++struct screen_view { ++ unsigned short columns; ++ unsigned short rows; ++ unsigned char colomn_offset; ++ unsigned char swap_banks_orientation : 1; ++ unsigned char reserved : 7; ++}; ++ ++struct specific_gfx_mono_ctrl ++{ ++ unsigned char (*init)(void); ++ unsigned char (*set_display_type)(struct vfd_display *display); ++ ++ void (*clear)(void); ++ void (*set_power)(unsigned char state); ++ void (*set_contrast)(unsigned char value); ++ unsigned char (*set_xy)(unsigned short x, unsigned short y); ++ void (*print_char)(char ch, const struct font *font_struct, unsigned char x, unsigned char y); ++ void (*print_string)(const unsigned char *buffer, const struct rect *rect); ++ ++ void (*write_ctrl_command_buf)(const unsigned char *buf, unsigned int length); ++ void (*write_ctrl_command)(unsigned char cmd); ++ void (*write_ctrl_data_buf)(const unsigned char *buf, unsigned int length); ++ void (*write_ctrl_data)(unsigned char data); ++ ++ const struct screen_view *screen_view; ++}; ++ ++struct controller_interface *init_gfx_mono_ctrl(struct vfd_dev *_dev, const struct specific_gfx_mono_ctrl *specific_gfx_mono_ctrl); ++ ++#endif +diff -ruN main/drivers/auxdisplay/openvfd/controllers/hd44780.c mod/drivers/auxdisplay/openvfd/controllers/hd44780.c +--- main/drivers/auxdisplay/openvfd/controllers/hd44780.c 1970-01-01 01:00:00.000000000 +0100 ++++ mod/drivers/auxdisplay/openvfd/controllers/hd44780.c 2023-03-07 09:42:01.581533754 +0100 +@@ -0,0 +1,760 @@ ++#include "../protocols/i2c_sw.h" ++#include "hd44780.h" ++ ++/* **************************** Define HD44780 Constants ****************************** */ ++#define HD44780_CLEAR_RAM 0x01 /* Write mode command */ ++#define HD44780_HOME 0x02 /* Increment or decrement address */ ++#define HD44780_ENTRY_MODE 0x04 /* Write mode command */ ++#define HD44780_EM_ID 0x02 /* Increment or decrement address */ ++#define HD44780_EM_S 0x01 /* Accompanies display shift */ ++#define HD44780_DISPLAY_CONTROL 0x08 /* Write mode command */ ++#define HD44780_DC_D 0x04 /* Increment or decrement address */ ++#define HD44780_DC_C 0x02 /* Accompanies display shift */ ++#define HD44780_DC_B 0x01 /* Accompanies display shift */ ++#define HD44780_CURESOR_SHIFT 0x10 /* Write mode command */ ++#define HD44780_CS 0x08 /* FD650 Display On */ ++#define HD44780_RL 0x04 /* FD650 Display Off */ ++#define HD44780_FUNCTION 0x20 /* Set FD650 to work in 7-segment mode */ ++#define HD44780_F_DL 0x10 /* Set FD650 to work in 8-segment mode */ ++#define HD44780_F_N 0x08 /* Base data address */ ++#define HD44780_F_F 0x04 /* Set display brightness command */ ++#define HD44780_CGRA 0x40 /* Set CGRAM Address */ ++#define HD44780_DDRA 0x80 /* Set DDRAM Address */ ++/* ************************************************************************************ */ ++#define BACKPACK_BACKLIGHT 0x08 ++#define BACKPACK_ENABLE 0x04 ++#define BACKPACK_READ 0x02 ++#define BACKPACK_RS 0x01 ++#define BACKPACK_CMD 0x00 ++ ++#define FLAGS_SHOW_SEC 0x01 ++ ++#define BIG_2L_DOT 0xA5 ++#define BIG_4L_DOT 0x07 ++#define CUSTOM_ELLIPSIS 0x07 ++ ++static const unsigned char cgram_4l_chars[8][8] = { ++ { 0x03, 0x07, 0x0F, 0x1F, 0x00, 0x00, 0x00, 0x00 }, // 0 - Top left ++ { 0x18, 0x1C, 0x1E, 0x1F, 0x00, 0x00, 0x00, 0x00 }, // 1 - Top right ++ { 0x1F, 0x1F, 0x1F, 0x1F, 0x00, 0x00, 0x00, 0x00 }, // 2 - Top center ++ { 0x1F, 0x0F, 0x07, 0x03, 0x00, 0x00, 0x00, 0x00 }, // 3 - Bottom left ++ { 0x1F, 0x1E, 0x1C, 0x18, 0x00, 0x00, 0x00, 0x00 }, // 4 - Bottom right ++ { 0x03, 0x07, 0x0F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F }, // 5 - Long left ++ { 0x18, 0x1C, 0x1E, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F }, // 6 - Long right ++ { 0x00, 0x00, 0x0E, 0x1F, 0x1F, 0x1F, 0x0E, 0x00 }, // 7 - Dot ++}; ++ ++static const unsigned char big_4l_chars[11][9] = { ++ { 5, 2, 6, 255, ' ', 255, 3, 2, 4 }, // 0 ++ { 0, 255, ' ', ' ', 255, ' ', 2, 2, 2 }, // 1 ++ { 0, 2, 6, 5, 2, 4, 3, 2, 4 }, // 2 ++ { 0, 2, 6, ' ', 2, 255, 3, 2, 4 }, // 3 ++ { 255, ' ', 255, 3, 2, 255, ' ', ' ', 2 }, // 4 ++ { 255, 2, 4, 2, 2, 6, 3, 2, 4 }, // 5 ++ { 5, 2, 1, 255, 2, 6, 3, 2, 4 }, // 6 ++ { 3, 2, 255, ' ', 5, 4, ' ', 2, ' ' }, // 7 ++ { 5, 2, 6, 255, 2, 255, 3, 2, 4 }, // 8 ++ { 5, 2, 6, 3, 2, 255, 3, 2, 4 }, // 9 ++ ++ { 5, 2, 1, 255, ' ', ' ', 3, 2, 4 }, // C ++}; ++ ++static const unsigned char cgram_2l_chars[8][8] = { ++ { 0x1F, 0x1F, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00 }, // char 1 ++ { 0x18, 0x1C, 0x1E, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F }, // char 2 ++ { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x0F, 0x07, 0x03 }, // char 3 ++ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x1F, 0x1F }, // char 4 ++ { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1E, 0x1C, 0x18 }, // char 5 ++ { 0x1F, 0x1F, 0x1F, 0x00, 0x00, 0x00, 0x1F, 0x1F }, // char 6 ++ { 0x1F, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x1F, 0x1F }, // char 7 ++ { 0x03, 0x07, 0x0F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F }, // char 8 ++}; ++ ++static const unsigned char big_2l_chars[11][6] = { ++ { 0x07, 0x00, 0x01, 0x02, 0x03, 0x04 }, // 0 ++ { 0x08, 0x01, 0x20, 0x03, 0xFF, 0x03 }, // 1 ++ { 0x05, 0x05, 0x01, 0xFF, 0x06, 0x06 }, // 2 ++ { 0x00, 0x05, 0x01, 0x03, 0x06, 0x04 }, // 3 ++ { 0x02, 0x03, 0xFF, 0x20, 0x20, 0xFF }, // 4 ++ { 0xFF, 0x05, 0x05, 0x06, 0x06, 0x04 }, // 5 ++ { 0x07, 0x05, 0x05, 0x02, 0x06, 0x04 }, // 6 ++ { 0x00, 0x00, 0x01, 0x20, 0x07, 0x20 }, // 7 ++ { 0x07, 0x05, 0x01, 0x02, 0x06, 0x04 }, // 8 ++ { 0x07, 0x05, 0x01, 0x06, 0x06, 0x04 }, // 9 ++ ++ { 0x07, 0x00, 0x00, 0x02, 0x03, 0x03 }, // C ++}; ++ ++static const unsigned char cgram_ellipsis_chars[8] = { ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00 ++}; ++ ++static unsigned char hd47780_init(void); ++static unsigned short hd47780_get_brightness_levels_count(void); ++static unsigned short hd47780_get_brightness_level(void); ++static unsigned char hd47780_set_brightness_level(unsigned short level); ++static unsigned char hd47780_get_power(void); ++static void hd47780_set_power(unsigned char state); ++static void hd47780_power_suspend(void) { hd47780_set_power(0); } ++static void hd47780_power_resume(void) { hd47780_init(); } ++static struct vfd_display *hd47780_get_display_type(void); ++static unsigned char hd47780_set_display_type(struct vfd_display *display); ++static void hd47780_set_icon(const char *name, unsigned char state); ++static size_t hd47780_read_data(unsigned char *data, size_t length); ++static size_t hd47780_write_data(const unsigned char *data, size_t length); ++static size_t hd47780_write_display_data(const struct vfd_display_data *data); ++ ++static struct controller_interface hd47780_interface = { ++ .init = hd47780_init, ++ .get_brightness_levels_count = hd47780_get_brightness_levels_count, ++ .get_brightness_level = hd47780_get_brightness_level, ++ .set_brightness_level = hd47780_set_brightness_level, ++ .get_power = hd47780_get_power, ++ .set_power = hd47780_set_power, ++ .power_suspend = hd47780_power_suspend, ++ .power_resume = hd47780_power_resume, ++ .get_display_type = hd47780_get_display_type, ++ .set_display_type = hd47780_set_display_type, ++ .set_icon = hd47780_set_icon, ++ .read_data = hd47780_read_data, ++ .write_data = hd47780_write_data, ++ .write_display_data = hd47780_write_display_data, ++}; ++ ++static void print_2l_char(unsigned short ch, unsigned char pos, unsigned char is_clock); ++static void print_4l_char(unsigned short ch, unsigned char pos, unsigned char is_clock); ++static void print_clock(const struct vfd_display_data *data, unsigned char print_seconds); ++static void print_channel(const struct vfd_display_data *data); ++static void print_playback_time(const struct vfd_display_data *data); ++static void print_title(const struct vfd_display_data *data); ++static void print_date(const struct vfd_display_data *data); ++static void print_temperature(const struct vfd_display_data *data); ++ ++static struct vfd_dev *dev = NULL; ++static struct protocol_interface *protocol = NULL; ++static unsigned char columns = 16; ++static unsigned char rows = 2; ++static unsigned char backlight = BACKPACK_BACKLIGHT; ++static unsigned char big_dot = BIG_2L_DOT; ++static struct vfd_display_data old_data; ++ ++const char *days[7] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; ++const char *months[12] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", ++ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; ++ ++struct controller_interface *init_hd47780(struct vfd_dev *_dev) ++{ ++ dev = _dev; ++ memset(&old_data, 0, sizeof(old_data)); ++ return &hd47780_interface; ++} ++ ++static void write_4_bits(unsigned char data) { ++ unsigned char buffer[3] = { data, (unsigned char)(data | BACKPACK_ENABLE), data }; ++ protocol->write_data(buffer, 3); ++} ++ ++static void write_lcd(unsigned char data, unsigned char mode) { ++ unsigned char lo = (data & 0x0F) << 4; ++ unsigned char hi = (data & 0xF0); ++ mode |= backlight; ++ write_4_bits(hi | mode); ++ write_4_bits(lo | mode); ++} ++ ++static void write_buf_lcd(const unsigned char *buf, unsigned int length) ++{ ++ while (length--) { ++ write_lcd(*buf, BACKPACK_RS); ++ buf++; ++ } ++} ++ ++static unsigned char read_4_bits(unsigned char mode) { ++ unsigned char data[2] = { (unsigned char)(mode | 0xF0), (unsigned char)(mode | 0xF0 | BACKPACK_ENABLE) }; ++ protocol->write_data(data, 2); ++ protocol->read_byte(data + 1); ++ protocol->write_data(&mode, 1); ++ return data[1]; ++} ++ ++static unsigned char read_lcd(unsigned char mode) { ++ unsigned char lo; ++ unsigned char hi; ++ mode &= ~BACKPACK_ENABLE; ++ mode |= backlight | BACKPACK_READ; ++ hi = read_4_bits(mode); ++ lo = read_4_bits(mode); ++ return ((hi & 0xF0) | (lo >> 4)); ++} ++ ++static unsigned char hd47780_init(void) ++{ ++ unsigned char cmd = 0; ++ protocol = init_sw_i2c(dev->dtb_active.display.reserved & 0x7F, MSB_FIRST, 1, dev->clk_pin, dev->dat_pin, I2C_DELAY_500KHz, NULL); ++ if (!protocol) ++ return 0; ++ ++ old_data.mode = DISPLAY_MODE_NONE; ++ columns = (dev->dtb_active.display.type & 0x1F) << 1; ++ rows = (dev->dtb_active.display.type >> 5) & 0x07; ++ rows++; ++ big_dot = rows > 2 ? BIG_4L_DOT : BIG_2L_DOT; ++ ++ write_4_bits(0x03 << 4); ++ usleep_range(4300, 5000); ++ write_4_bits(0x03 << 4); ++ udelay(150); ++ write_4_bits(0x03 << 4); ++ udelay(150); ++ write_4_bits(0x02 << 4); ++ udelay(150); ++ cmd = HD44780_FUNCTION; ++ if (rows > 1) ++ cmd |= HD44780_F_N | HD44780_F_F; ++ write_lcd(cmd, BACKPACK_CMD); ++ udelay(150); ++ write_lcd(HD44780_DISPLAY_CONTROL, BACKPACK_CMD); ++ write_lcd(HD44780_CLEAR_RAM, BACKPACK_CMD); ++ usleep_range(1600, 2000); ++ write_lcd(HD44780_ENTRY_MODE | HD44780_EM_ID, BACKPACK_CMD); ++ write_lcd(HD44780_DISPLAY_CONTROL | HD44780_DC_D, BACKPACK_CMD); ++ ++ if (rows >= 3) { ++ write_lcd(HD44780_CGRA, BACKPACK_CMD); ++ write_buf_lcd((const unsigned char *)cgram_4l_chars, 64); ++ } else if (rows == 2) { ++ write_lcd(HD44780_CGRA, BACKPACK_CMD); ++ write_buf_lcd((const unsigned char *)cgram_2l_chars, 64); ++ } ++ ++ hd47780_set_brightness_level(dev->brightness); ++ return 1; ++} ++ ++static unsigned short hd47780_get_brightness_levels_count(void) ++{ ++ return 2; ++} ++ ++static unsigned short hd47780_get_brightness_level(void) ++{ ++ return dev->brightness; ++} ++ ++static unsigned char hd47780_set_brightness_level(unsigned short level) ++{ ++ dev->brightness = level; ++ dev->power = 1; ++ backlight = dev->power && dev->brightness > 0 ? BACKPACK_BACKLIGHT : 0; ++ write_lcd(HD44780_DISPLAY_CONTROL | HD44780_DC_D, BACKPACK_CMD); ++ return 1; ++} ++ ++static unsigned char hd47780_get_power(void) ++{ ++ return dev->power; ++} ++ ++static void hd47780_set_power(unsigned char state) ++{ ++ dev->power = state; ++ if (state) ++ hd47780_set_brightness_level(dev->brightness); ++ else { ++ backlight = 0; ++ write_lcd(HD44780_DISPLAY_CONTROL, BACKPACK_CMD); ++ } ++} ++ ++static struct vfd_display *hd47780_get_display_type(void) ++{ ++ return &dev->dtb_active.display; ++} ++ ++static unsigned char hd47780_set_display_type(struct vfd_display *display) ++{ ++ unsigned char ret = 0; ++ if (display->controller == CONTROLLER_HD44780) ++ { ++ dev->dtb_active.display = *display; ++ hd47780_init(); ++ ret = 1; ++ } ++ return ret; ++} ++ ++static void hd47780_set_icon(const char *name, unsigned char state) ++{ ++ if (strncmp(name,"colon",5) == 0) ++ dev->status_led_mask = state ? (dev->status_led_mask | ledDots[LED_DOT_SEC]) : (dev->status_led_mask & ~ledDots[LED_DOT_SEC]); ++} ++ ++static size_t hd47780_read_data(unsigned char *data, size_t length) ++{ ++ size_t count = length; ++ write_lcd(HD44780_HOME, BACKPACK_CMD); ++ while (count--) { ++ *data = read_lcd(BACKPACK_RS); ++ data++; ++ } ++ return length; ++} ++ ++static size_t hd47780_write_data(const unsigned char *data, size_t length) ++{ ++ size_t i; ++ if (length == 0) ++ return 0; ++ ++ if (rows >= 3) { ++ unsigned char dot; ++ const unsigned short *wdata = (const unsigned short *)data; ++ length /= 2; ++ for (i = 1; i < length; i++) ++ print_4l_char(wdata[i] - 0x30, i-1, 1); ++ if ((data[0] | dev->status_led_mask) & ledDots[LED_DOT_SEC]) ++ dot = big_dot; ++ else ++ dot = ' '; ++ write_lcd(HD44780_DDRA + 0x06, BACKPACK_CMD); ++ write_lcd(dot, BACKPACK_RS); ++ write_lcd(HD44780_DDRA + 0x46, BACKPACK_CMD); ++ write_lcd(dot, BACKPACK_RS); ++ } ++ else { ++ write_lcd(HD44780_HOME, BACKPACK_CMD); ++ usleep_range(1600, 2000); ++ if (length > 2) ++ write_lcd(data[2], BACKPACK_RS); ++ if (length > 4) ++ write_lcd(data[4], BACKPACK_RS); ++ if ((data[0] | dev->status_led_mask) & ledDots[LED_DOT_SEC]) ++ write_lcd(':', BACKPACK_RS); ++ else ++ write_lcd(' ', BACKPACK_RS); ++ if (length > 6) ++ write_lcd(data[6], BACKPACK_RS); ++ if (length > 8) ++ write_lcd(data[8], BACKPACK_RS); ++ } ++ ++ return length; ++} ++ ++static size_t hd47780_write_display_data(const struct vfd_display_data *data) ++{ ++ size_t status = sizeof(*data); ++ if (data->mode != old_data.mode) { ++ memset(&old_data, 0, sizeof(old_data)); ++ write_lcd(HD44780_CLEAR_RAM, BACKPACK_CMD); ++ usleep_range(2000, 2500); ++ switch (data->mode) { ++ case DISPLAY_MODE_CLOCK: ++ case DISPLAY_MODE_PLAYBACK_TIME: ++ case DISPLAY_MODE_DATE: ++ write_lcd(HD44780_CGRA | 0x38, BACKPACK_CMD); ++ if (rows != 2) ++ write_buf_lcd(cgram_4l_chars[7], 8); ++ else ++ write_buf_lcd(cgram_2l_chars[7], 8); ++ break; ++ case DISPLAY_MODE_CHANNEL: ++ write_lcd(HD44780_CGRA | 0x38, BACKPACK_CMD); ++ if (rows != 2) ++ write_buf_lcd(cgram_ellipsis_chars, 8); ++ else ++ write_buf_lcd(cgram_2l_chars[7], 8); ++ break; ++ case DISPLAY_MODE_TITLE: ++ write_lcd(HD44780_CGRA | 0x38, BACKPACK_CMD); ++ write_buf_lcd(cgram_ellipsis_chars, 8); ++ break; ++ case DISPLAY_MODE_TEMPERATURE: ++ if (rows == 2) { ++ write_lcd(HD44780_CGRA | 0x38, BACKPACK_CMD); ++ write_buf_lcd(cgram_2l_chars[7], 8); ++ } ++ break; ++ default: ++ break; ++ } ++ } ++ ++ switch (data->mode) { ++ case DISPLAY_MODE_CLOCK: ++ print_clock(data, 1); ++ break; ++ case DISPLAY_MODE_DATE: ++ print_date(data); ++ break; ++ case DISPLAY_MODE_CHANNEL: ++ write_lcd(HD44780_CLEAR_RAM, BACKPACK_CMD); ++ usleep_range(2000, 2500); ++ print_channel(data); ++ break; ++ case DISPLAY_MODE_PLAYBACK_TIME: ++ print_playback_time(data); ++ break; ++ case DISPLAY_MODE_TITLE: ++ print_title(data); ++ break; ++ case DISPLAY_MODE_TEMPERATURE: ++ print_temperature(data); ++ break; ++ default: ++ status = 0; ++ break; ++ } ++ ++ old_data = *data; ++ return status; ++} ++ ++static void set_xy(unsigned short row, unsigned char column) ++{ ++ unsigned char offset = 0x00; ++ if (column < columns && row < rows) { ++ switch (rows) { ++ case 2: ++ if (row == 1) ++ offset = 0x40; ++ break; ++ case 4: ++ if (row % 2) ++ offset = 0x40; ++ if (row >= 2) ++ offset += columns; ++ break; ++ }; ++ ++ offset += column; ++ write_lcd(HD44780_DDRA | offset, BACKPACK_CMD); ++ } ++} ++ ++static void print_2l_char(unsigned short ch, unsigned char pos, unsigned char is_clock) ++{ ++ unsigned char i; ++ if (ch >= 10) { ++ pr_dbg2("print_2l_char: ch = %d, out of bounds\n", ch); ++ return; ++ } ++ pos *= 3; ++ if (is_clock) { ++ if (pos >= 6) ++ pos++; ++ if (pos >= 12) ++ pos++; ++ } ++ for (i = 0; i < 2; i++) { ++ set_xy(i, pos); ++ write_buf_lcd(big_2l_chars[ch] + (i * 3), 3); ++ } ++} ++ ++static void print_4l_char(unsigned short ch, unsigned char pos, unsigned char is_clock) ++{ ++ unsigned char i; ++ if (ch >= 10) { ++ pr_dbg2("print_4l_char: ch = %d, out of bounds\n", ch); ++ return; ++ } ++ pos *= 3; ++ if (is_clock) { ++ if (pos >= 6) ++ pos++; ++ if (pos >= 12) ++ pos++; ++ } ++ for (i = 0; i < 3; i++) { ++ set_xy(i, pos); ++ write_buf_lcd(big_4l_chars[ch] + (i * 3), 3); ++ } ++} ++ ++static void print_colon(unsigned char colon_on, unsigned char print_seconds) ++{ ++ unsigned char dot; ++ if (colon_on != old_data.colon_on) { ++ if (rows >= 2) { ++ dot = colon_on ? big_dot : ' '; ++ write_lcd(HD44780_DDRA + 6, BACKPACK_CMD); ++ write_lcd(dot, BACKPACK_RS); ++ write_lcd(HD44780_DDRA + 0x40 + 6, BACKPACK_CMD); ++ write_lcd(dot, BACKPACK_RS); ++ if (print_seconds) { ++ write_lcd(HD44780_DDRA + 13, BACKPACK_CMD); ++ write_lcd(dot, BACKPACK_RS); ++ write_lcd(HD44780_DDRA + 0x40 + 13, BACKPACK_CMD); ++ write_lcd(dot, BACKPACK_RS); ++ } ++ } else { ++ dot = colon_on ? ':' : ' '; ++ write_lcd(HD44780_DDRA + 2, BACKPACK_CMD); ++ write_lcd(dot, BACKPACK_RS); ++ if (print_seconds) { ++ write_lcd(HD44780_DDRA + 5, BACKPACK_CMD); ++ write_lcd(dot, BACKPACK_RS); ++ } ++ } ++ } ++} ++ ++static void print_number(const char *buffer, size_t length, unsigned char start_index, unsigned char is_clock) ++{ ++ unsigned char i; ++ if (rows > 2) { ++ for (i = 0; i < length; i++) ++ print_4l_char(buffer[i] - 0x30, i + start_index, is_clock); ++ } else if (rows == 2) { ++ for (i = 0; i < length; i++) ++ print_2l_char(buffer[i] - 0x30, i + start_index, is_clock); ++ } else { ++ if (is_clock) { ++ if (start_index >= 2) ++ start_index++; ++ if (start_index >= 4) ++ start_index++; ++ } ++ write_lcd(HD44780_DDRA + start_index, BACKPACK_CMD); ++ for (i = 0; i < length; i++) ++ write_lcd(buffer[i], BACKPACK_RS); ++ } ++} ++ ++static void print_clock(const struct vfd_display_data *data, unsigned char print_seconds) ++{ ++ char buffer[10]; ++ unsigned char force_print = old_data.mode == DISPLAY_MODE_NONE; ++ print_seconds &= (dev->dtb_active.display.flags & FLAGS_SHOW_SEC) && columns >= 20; ++ print_colon(data->colon_on, print_seconds); ++ if (data->time_date.hours != old_data.time_date.hours || force_print) { ++ scnprintf(buffer, sizeof(buffer), "%02d", data->time_date.hours); ++ print_number(buffer, 2, 0, TRUE); ++ } ++ if (data->time_date.minutes != old_data.time_date.minutes || force_print) { ++ scnprintf(buffer, sizeof(buffer), "%02d", data->time_date.minutes); ++ print_number(buffer, 2, 2, TRUE); ++ } ++ if (print_seconds && (data->time_date.seconds != old_data.time_date.seconds || force_print)) { ++ scnprintf(buffer, sizeof(buffer), "%02d", data->time_date.seconds); ++ print_number(buffer, 2, 4, TRUE); ++ } ++ if (rows >= 2 && columns >= 20 && (data->time_date.day != old_data.time_date.day || ++ data->time_date.month != old_data.time_date.month || data->time_date.year != old_data.time_date.year)) { ++ size_t len; ++ len = scnprintf(buffer, sizeof(buffer), "%s %02d", months[data->time_date.month], data->time_date.day); ++ set_xy(0, columns - len); ++ write_buf_lcd(buffer, len); ++ len = scnprintf(buffer, sizeof(buffer), "%d", data->time_date.year); ++ set_xy(1, columns - len); ++ write_buf_lcd(buffer, len); ++ if (rows >= 3) { ++ len = strlen(days[data->time_date.day_of_week]); ++ set_xy(2, columns - len); ++ write_buf_lcd(days[data->time_date.day_of_week], len); ++ } ++ if (rows >= 4) { ++ set_xy(3, 0); ++ write_buf_lcd(data->string_main, min(strlen(data->string_main), (size_t)columns)); ++ } ++ } ++} ++ ++static void print_channel(const struct vfd_display_data *data) ++{ ++ size_t len, max_len = (columns / 3); ++ char buffer[81]; ++ if (rows >= 2) { ++ len = scnprintf(buffer, sizeof(buffer), "%d", data->channel_data.channel); ++ if (len > max_len) { ++ print_number(buffer + (len - max_len), max_len, 0, FALSE); ++ len = max_len; ++ } else ++ print_number(buffer, len, 0, FALSE); ++ len *= 3; ++ if (columns - len >= 7) { ++ unsigned char row = 0; ++ if (rows > 2 && data->channel_data.channel_count > 0) { ++ len = scnprintf(buffer, sizeof(buffer), "/%d", data->channel_data.channel_count); ++ if (len <= 7) { ++ set_xy(row++, columns - len); ++ write_buf_lcd(buffer, len); ++ } ++ } ++ if (data->time_date.hours < 24 && data->time_secondary.hours < 24) { ++ len = scnprintf(buffer, sizeof(buffer), "%02d:%02d-", data->time_date.hours, data->time_date.minutes); ++ set_xy(row++, columns - len); ++ write_buf_lcd(buffer, len); ++ len = scnprintf(buffer, sizeof(buffer), "%02d:%02d ", data->time_secondary.hours, data->time_secondary.minutes); ++ set_xy(row++, columns - len); ++ write_buf_lcd(buffer, len); ++ } ++ if (rows >= 4) { ++ set_xy(3, 0); ++ len = scnprintf(buffer, sizeof(buffer), "%s", data->string_main); ++ if (len > columns) { ++ len = columns; ++ buffer[len - 1] = CUSTOM_ELLIPSIS; ++ } ++ write_buf_lcd(buffer, len); ++ } ++ } ++ } else { ++ write_lcd(HD44780_DDRA, BACKPACK_CMD); ++ len = scnprintf(buffer, sizeof(buffer), "%d/%d", data->channel_data.channel, data->channel_data.channel_count); ++ if (len > columns) { ++ len = columns; ++ buffer[len - 1] = CUSTOM_ELLIPSIS; ++ } ++ write_buf_lcd(buffer, len); ++ } ++} ++ ++static void print_playback_time(const struct vfd_display_data *data) ++{ ++ char buffer[21]; ++ unsigned char force_print = old_data.mode == DISPLAY_MODE_NONE || data->time_date.hours != old_data.time_date.hours; ++ print_colon(data->colon_on, FALSE); ++ if (data->time_date.hours > 0) { ++ if (data->time_date.hours != old_data.time_date.hours || force_print) { ++ scnprintf(buffer, sizeof(buffer), "%02d", data->time_date.hours); ++ print_number(buffer, 2, 0, TRUE); ++ if (rows >= 3) ++ write_lcd('H', BACKPACK_RS); ++ } ++ if (data->time_date.minutes != old_data.time_date.minutes || force_print) { ++ scnprintf(buffer, sizeof(buffer), "%02d", data->time_date.minutes); ++ print_number(buffer, 2, 2, TRUE); ++ write_lcd('M', BACKPACK_RS); ++ } ++ } else { ++ if (data->time_date.minutes != old_data.time_date.minutes || force_print) { ++ scnprintf(buffer, sizeof(buffer), "%02d", data->time_date.minutes); ++ print_number(buffer, 2, 0, TRUE); ++ if (rows >= 3) ++ write_lcd('M', BACKPACK_RS); ++ } ++ if (data->time_date.seconds != old_data.time_date.seconds || force_print) { ++ scnprintf(buffer, sizeof(buffer), "%02d", data->time_date.seconds); ++ print_number(buffer, 2, 2, TRUE); ++ write_lcd('S', BACKPACK_RS); ++ } ++ } ++ ++ if (rows >= 2 && columns >= 20) { ++ size_t len = 0; ++ unsigned char mins = data->time_secondary.minutes + ((data->time_secondary.seconds >= 30) ? 1 : 0); ++ unsigned char hours = data->time_secondary.hours; ++ if (mins >= 60) { ++ mins %= 60; ++ hours++; ++ } ++ len = scnprintf(buffer, sizeof(buffer), "/%02d:%02d", hours, mins); ++ set_xy(0, columns - len); ++ write_buf_lcd(buffer, len); ++ } ++ ++ if (rows >= 4) { ++ set_xy(3, 0); ++ write_buf_lcd(data->string_main, min(strlen(data->string_main), (size_t)columns)); ++ } ++} ++ ++static void print_title(const struct vfd_display_data *data) ++{ ++ size_t len; ++ char buffer[81]; ++ if (rows >= 2) { ++ unsigned char i, row, max_len = columns * (rows - 1); ++ set_xy(0, 0); ++ write_buf_lcd(data->string_secondary, min(strlen(data->string_secondary), (size_t)columns)); ++ ++ len = scnprintf(buffer, sizeof(buffer), "%s", data->string_main); ++ if (len > max_len) { ++ len = max_len; ++ buffer[len - 1] = CUSTOM_ELLIPSIS; ++ } ++ for (i = 0, row = 1; i < len; i += columns, row++) { ++ set_xy(row, 0); ++ write_buf_lcd(buffer + i, min(len - i, (size_t)columns)); ++ } ++ } else { ++ set_xy(0, 0); ++ len = scnprintf(buffer, sizeof(buffer), "%s", data->string_main); ++ if (len > columns) { ++ len = columns; ++ buffer[len - 1] = CUSTOM_ELLIPSIS; ++ } ++ write_buf_lcd(buffer, len); ++ } ++} ++ ++static void print_date(const struct vfd_display_data *data) ++{ ++ char buffer[21]; ++ size_t len; ++ unsigned char i = 0; ++ unsigned char force_print = old_data.mode == DISPLAY_MODE_NONE || data->time_date.month != old_data.time_date.month || data->time_date.day != old_data.time_date.day; ++ if (force_print) { ++ if (rows >= 2) { ++ if (data->time_secondary._reserved) ++ scnprintf(buffer, sizeof(buffer), "%02d%02d", data->time_date.month + 1, data->time_date.day); ++ else ++ scnprintf(buffer, sizeof(buffer), "%02d%02d", data->time_date.day, data->time_date.month + 1); ++ for (i = 0; i < min(rows, (unsigned char)3); i++) { ++ set_xy(i, 6); ++ write_lcd('|', BACKPACK_RS); ++ } ++ print_number(buffer, 4, 0, 1); ++ if (rows >= 4) { ++ len = scnprintf(buffer, sizeof(buffer), "%04d, %s, %s", data->time_date.year, months[data->time_date.month], days[data->time_date.day_of_week]); ++ set_xy(3, 0); ++ write_buf_lcd(buffer, min((size_t)columns, len)); ++ } ++ } else { ++ if (data->time_secondary._reserved) ++ len = scnprintf(buffer, sizeof(buffer), "%02d/%02d", data->time_date.month + 1, data->time_date.day); ++ else ++ len = scnprintf(buffer, sizeof(buffer), "%02d/%02d", data->time_date.day, data->time_date.month + 1); ++ if (columns <= 8) ++ len += scnprintf(buffer + len, sizeof(buffer) - len, "/%02d", data->time_date.year % 100); ++ else ++ len += scnprintf(buffer + len, sizeof(buffer) - len, "/%04d", data->time_date.year); ++ set_xy(0, 0); ++ write_buf_lcd(buffer, min((size_t)columns, len)); ++ } ++ } ++} ++ ++static void print_temperature(const struct vfd_display_data *data) ++{ ++ unsigned char i; ++ char buffer[10]; ++ if (data->temperature != old_data.temperature) { ++ size_t len = scnprintf(buffer, sizeof(buffer), "%d", data->temperature); ++ print_number(buffer, len, 0, FALSE); ++ if (rows >= 2) { ++ len *= 3; ++ set_xy(0, len); ++ write_lcd('o', BACKPACK_RS); ++ len++; ++ if (rows > 2) { ++ for (i = 0; i < 3; i++) { ++ set_xy(i, len); ++ write_buf_lcd(big_4l_chars[10] + (i * 3), 3); ++ } ++ } ++ else { ++ for (i = 0; i < 2; i++) { ++ set_xy(i, len); ++ write_buf_lcd(big_2l_chars[10] + (i * 3), 3); ++ } ++ } ++ } else { ++ size_t len = scnprintf(buffer, sizeof(buffer), "%cC", 0xDF); ++ write_buf_lcd(buffer, len); ++ } ++ } ++} +diff -ruN main/drivers/auxdisplay/openvfd/controllers/hd44780.h mod/drivers/auxdisplay/openvfd/controllers/hd44780.h +--- main/drivers/auxdisplay/openvfd/controllers/hd44780.h 1970-01-01 01:00:00.000000000 +0100 ++++ mod/drivers/auxdisplay/openvfd/controllers/hd44780.h 2023-03-07 09:42:01.585533784 +0100 +@@ -0,0 +1,8 @@ ++#ifndef __HD44780H__ ++#define __HD44780H__ ++ ++#include "controller.h" ++ ++struct controller_interface *init_hd47780(struct vfd_dev *dev); ++ ++#endif +diff -ruN main/drivers/auxdisplay/openvfd/controllers/il3829.c mod/drivers/auxdisplay/openvfd/controllers/il3829.c +--- main/drivers/auxdisplay/openvfd/controllers/il3829.c 1970-01-01 01:00:00.000000000 +0100 ++++ mod/drivers/auxdisplay/openvfd/controllers/il3829.c 2023-03-07 09:42:01.597533878 +0100 +@@ -0,0 +1,513 @@ ++#include ++#include ++#include ++#include ++#include "../protocols/i2c_hw.h" ++#include "../protocols/i2c_sw.h" ++#include "../protocols/spi_sw.h" ++#include "il3829.h" ++#include "gfx_mono_ctrl.h" ++ ++static unsigned char il3829_init(void); ++static unsigned char il3829_set_display_type(struct vfd_display *display); ++static void il3829_clear(void); ++static void il3829_set_power(unsigned char state); ++static void il3829_set_contrast(unsigned char value); ++static unsigned char il3829_set_xy(unsigned short x, unsigned short y); ++static void il3829_set_area(const struct rect *rect); ++static void il3829_print_char(char ch, const struct font *font_struct, unsigned char x, unsigned char y); ++static void il3829_print_string(const unsigned char *buffer, const struct rect *rect); ++static void il3829_write_ctrl_command_data_buf(const unsigned char *buf, unsigned int length); ++static void il3829_write_ctrl_command(unsigned char cmd); ++static void il3829_write_ctrl_data_buf(const unsigned char *buf, unsigned int length); ++static void il3829_write_ctrl_data(unsigned char data); ++ ++static struct screen_view screen_view = { 0 }; ++ ++static struct specific_gfx_mono_ctrl il3829_gfx_mono_ctrl = { ++ .init = il3829_init, ++ .set_display_type = il3829_set_display_type, ++ .clear = il3829_clear, ++ .set_power = il3829_set_power, ++ .set_contrast = il3829_set_contrast, ++ .set_xy = il3829_set_xy, ++ .print_char = il3829_print_char, ++ .print_string = il3829_print_string, ++ .write_ctrl_command_buf = il3829_write_ctrl_command_data_buf, ++ .write_ctrl_command = il3829_write_ctrl_command, ++ .write_ctrl_data_buf = il3829_write_ctrl_data_buf, ++ .write_ctrl_data = il3829_write_ctrl_data, ++ .screen_view = &screen_view, ++}; ++ ++enum { ++ TYPE_IL3829, ++ TYPE_IL3820, ++}; ++ ++struct il3829_display { ++ unsigned char columns : 3; ++ unsigned char banks : 3; ++ unsigned char offset : 2; ++ ++ union { ++ struct { ++ unsigned char address : 7; ++ unsigned char not_i2c : 1; ++ } i2c; ++ struct { ++ unsigned char disp_type : 4; ++ unsigned char reserved1 : 3; ++ unsigned char is_spi : 1; ++ } spi; ++ }; ++ ++ unsigned char flags_secs : 1; ++ unsigned char flags_invert : 1; ++ unsigned char flags_transpose : 1; ++ unsigned char flags_rotate : 1; ++ unsigned char flags_ext_vcc : 1; ++ unsigned char flags_alt_com_conf : 1; ++ unsigned char flags_low_freq : 1; ++ unsigned char reserved2 : 1; ++ ++ unsigned char controller; ++}; ++ ++struct write_list { ++ struct rect rect; ++ unsigned short buffer_length; ++ unsigned char *buffer; ++ struct list_head list; ++}; ++ ++static void il3829_init_display(unsigned char is_full_mode); ++ ++#define GxGDEP015OC1_POWER_DELAY 150 ++#define GxGDEP015OC1_PU_DELAY 325 ++#define GxGDEP015OC1_FU_DELAY 1300 ++ ++const unsigned char LUTDefault_full[] = ++{ ++ 0x32, // command ++ 0x02, 0x02, 0x01, 0x11, 0x12, 0x12, 0x22, 0x22, 0x66, 0x69, 0x69, 0x59, 0x58, 0x99, 0x99, ++ 0x88, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xB4, 0x13, 0x51, 0x35, 0x51, 0x51, 0x19, 0x01, 0x00 ++}; ++ ++const unsigned char LUTDefault_part[] = ++{ ++ 0x32, // command ++ 0x10, 0x18, 0x18, 0x08, 0x18, 0x18, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x14, 0x44, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ++}; ++ ++static struct vfd_dev *dev = NULL; ++static struct protocol_interface *protocol; ++static unsigned short rows = 200; ++static unsigned short banks = 200 / 8; ++static unsigned char row_offset = 0; ++static const unsigned char ram_buffer_blank[] = { [0 ... ((200 * 200 / 8) - 1)] = 0xFF }; ++static const unsigned char is_full_mode = 1; ++static int pin_rst = -1; ++static int pin_dc = -1; ++static int pin_busy = -1; ++static struct il3829_display il3829_display; ++static struct write_list write_list; ++static unsigned char power_state = 0; ++ ++static unsigned char is_needs_transpose(void) ++{ ++ return il3829_display.spi.disp_type == TYPE_IL3820; ++} ++ ++struct controller_interface *init_il3829(struct vfd_dev *_dev) ++{ ++ dev = _dev; ++ INIT_LIST_HEAD(&write_list.list); ++ memcpy(&il3829_display, &dev->dtb_active.display, sizeof(il3829_display)); ++ switch (il3829_display.spi.disp_type) { ++ case TYPE_IL3820: ++ banks = 128 / 8; ++ rows = 296; ++ break; ++ case TYPE_IL3829: ++ banks = 200 / 8; ++ rows = 200; ++ break; ++ } ++ if (is_needs_transpose()) { ++ screen_view.columns = rows / 8; ++ screen_view.rows = banks * 8; ++ } else { ++ screen_view.columns = banks; ++ screen_view.rows = rows; ++ } ++ screen_view.colomn_offset = 0; ++ screen_view.swap_banks_orientation = 1; ++ return init_gfx_mono_ctrl(_dev, &il3829_gfx_mono_ctrl); ++} ++ ++static void il3829_write_ctrl_buf(unsigned char dc, const unsigned char *buf, unsigned int length) ++{ ++ if (il3829_display.spi.is_spi) { ++ gpio_direction_output(pin_dc, dc ? 1 : 0); ++ protocol->write_data(buf, length); ++ } else { ++ protocol->write_cmd_data(&dc, 1, buf, length); ++ } ++} ++ ++static void il3829_write_ctrl_command(unsigned char cmd) ++{ ++ il3829_write_ctrl_buf(0x00, &cmd, 1); ++} ++ ++static void il3829_write_ctrl_command_data_buf(const unsigned char *buf, unsigned int length) ++{ ++ length--; ++ il3829_write_ctrl_command(*buf++); ++ il3829_write_ctrl_buf(0x40, buf, length); ++} ++ ++static void il3829_write_ctrl_data_buf(const unsigned char *buf, unsigned int length) ++{ ++ il3829_write_ctrl_buf(0x40, buf, length); ++} ++ ++static void il3829_write_ctrl_data(unsigned char data) ++{ ++ il3829_write_ctrl_buf(0x40, &data, 1); ++} ++ ++static void il3829_wait_busy(unsigned short max_delay) ++{ ++ if (pin_busy >= 0) { ++ unsigned short delay_count = 0; ++ while (delay_count < max_delay && gpio_get_value(pin_busy)) { ++ msleep(10); ++ delay_count += 10; ++ } ++ } else { ++ msleep(max_delay); ++ } ++} ++ ++static void il3829_full_update(void) ++{ ++ il3829_write_ctrl_command(0x22); ++ il3829_write_ctrl_data(0xC4); ++ il3829_write_ctrl_command(0x20); ++ il3829_write_ctrl_command(0xFF); ++ il3829_wait_busy(GxGDEP015OC1_FU_DELAY); ++} ++ ++static void il3829_part_update(void) ++{ ++ il3829_write_ctrl_command(0x22); ++ il3829_write_ctrl_data(0x04); ++ il3829_write_ctrl_command(0x20); ++ il3829_write_ctrl_command(0xFF); ++ il3829_wait_busy(GxGDEP015OC1_PU_DELAY); ++} ++ ++inline static void il3829_update(unsigned char is_full_mode) ++{ ++ if (is_full_mode) ++ il3829_full_update(); ++ else ++ il3829_part_update(); ++} ++ ++struct task_struct *refresh_thread = NULL; ++ ++static int refresh_thread_loop(void *data) ++{ ++ unsigned int prev_msecs, delay; ++ while (!kthread_should_stop()) ++ { ++ if (!mutex_trylock(dev->mutex)) { ++ msleep(1); ++ continue; ++ } ++ prev_msecs = jiffies_to_msecs(jiffies); ++ if (power_state) { ++ if (!list_empty(&write_list.list)) { ++ struct write_list *item, *tmp; ++ il3829_update(!is_full_mode); ++ list_for_each_entry_safe(item, tmp, &write_list.list, list) { ++ il3829_set_area(&item->rect); ++ il3829_set_xy(item->rect.x1, item->rect.y1); ++ il3829_write_ctrl_command(0x24); ++ il3829_write_ctrl_data_buf(item->buffer, item->buffer_length); ++ list_del(&item->list); ++ kfree(item->buffer); ++ kfree(item); ++ } ++ } ++ } ++ delay = min((unsigned int)500, (jiffies_to_msecs(jiffies) - prev_msecs)); ++ mutex_unlock(dev->mutex); ++ if (!kthread_should_stop()) ++ msleep(500 - delay); ++ } ++ ++ return 0; ++} ++ ++static void stop_refresh_thread(void) ++{ ++ if (refresh_thread) ++ { ++ kthread_stop(refresh_thread); ++ refresh_thread = NULL; ++ } ++} ++ ++static void start_refresh_thread(void) ++{ ++ if (!refresh_thread) ++ { ++ refresh_thread = kthread_create(refresh_thread_loop, NULL, "%s_e-ink_refresh_thread_loop", DEV_NAME); ++ wake_up_process(refresh_thread); ++ } ++} ++ ++static void clear_write_list(void) ++{ ++ struct write_list *item, *tmp; ++ list_for_each_entry_safe(item, tmp, &write_list.list, list) { ++ list_del(&item->list); ++ kfree(item->buffer); ++ kfree(item); ++ } ++} ++ ++static void clear(unsigned char is_full_mode) ++{ ++ struct rect full_rect = { ++ .x1 = 0x00, .x2 = banks - 1, .y1 = 0x00, .y2 = rows - 1 ++ }; ++ il3829_set_area(&full_rect); ++ il3829_set_xy(0, 0); ++ il3829_write_ctrl_command(0x24); ++ il3829_write_ctrl_data_buf(ram_buffer_blank, sizeof(ram_buffer_blank)); ++ il3829_update(is_full_mode); ++} ++ ++static void il3829_clear(void) ++{ ++ clear_write_list(); ++ il3829_init_display(is_full_mode); ++ clear(is_full_mode); ++ clear(is_full_mode); ++ il3829_init_display(!is_full_mode); ++} ++ ++static void il3829_set_power(unsigned char state) ++{ ++ power_state = state; ++ if (state) { ++ start_refresh_thread(); ++ il3829_init_display(!is_full_mode); ++ } else { ++ stop_refresh_thread(); ++ il3829_init_display(is_full_mode); ++ il3829_update(is_full_mode); ++ clear_write_list(); ++ } ++ ++ il3829_write_ctrl_command(0x22); ++ il3829_write_ctrl_data(state ? 0xC0 : 0xC3); ++ il3829_write_ctrl_command(0x20); ++ il3829_wait_busy(GxGDEP015OC1_POWER_DELAY); ++} ++ ++static void il3829_set_contrast(unsigned char value) ++{ ++} ++ ++static unsigned char il3829_set_xy(unsigned short x, unsigned short y) ++{ ++ unsigned char ret = 0; ++ y += row_offset; ++ if (x < banks || y < rows + row_offset) { ++ unsigned char x_buf[] = { 0x4E, x }; ++ unsigned char y_buf[] = { 0x4F, (y & 0xFF), y >> 8 }; ++ il3829_write_ctrl_command_data_buf(x_buf, sizeof(x_buf)); ++ il3829_write_ctrl_command_data_buf(y_buf, sizeof(y_buf)); ++ ret = 1; ++ } ++ ++ return ret; ++} ++ ++static void il3829_set_area(const struct rect *rect) ++{ ++ unsigned char x_buf[] = { 0x44, rect->x1, rect->x2 }; ++ unsigned char y_buf[] = { 0x45, rect->y1 & 0xFF, rect->y1 >> 8, rect->y2 & 0xFF, rect->y2 >> 8 }; ++ il3829_write_ctrl_command_data_buf(x_buf, sizeof(x_buf)); ++ il3829_write_ctrl_command_data_buf(y_buf, sizeof(y_buf)); ++} ++ ++static void il3829_print_char(char ch, const struct font *font_struct, unsigned char x, unsigned char y) ++{ ++ unsigned short offset = 0; ++ struct rect rect = { ++ .x1 = x, .x2 = x + font_struct->font_width - 1, .y1 = y, .y2 = y + font_struct->font_height - 1, ++ .font = font_struct, .length = 1, .width = font_struct->font_width, .height = font_struct->font_height, ++ }; ++ if (is_needs_transpose()) ++ swap(x, y); ++ if (x >= banks || y >= rows || ch < font_struct->font_offset || ch >= font_struct->font_offset + font_struct->font_char_count) ++ return; ++ ++ ch -= font_struct->font_offset; ++ offset = ch * font_struct->font_char_size; ++ offset += 4; ++ il3829_print_string(&font_struct->font_bitmaps[offset], &rect); ++} ++ ++static inline void il3829_adjust_buffer(const struct write_list *item) ++{ ++ unsigned short i; ++ for (i = 0; i < item->buffer_length; i++) ++ item->buffer[i] = ~item->buffer[i]; ++} ++ ++static void transpose_rect(struct rect *rect) ++{ ++ struct rect tmp = *rect; ++ rect->x1 = (tmp.y1 / 8); ++ rect->x2 = (tmp.y2 / 8); ++ rect->y1 = rows - 8 - (tmp.x2 * 8); ++ rect->y2 = rows - (tmp.x1 * 8); ++ rect->width = tmp.height / 8; ++ rect->height = tmp.width * 8; ++} ++ ++extern void transpose_buffer(unsigned char *buffer, const struct rect *rect); ++static void il3829_print_string(const unsigned char *buffer, const struct rect *_rect) ++{ ++ struct write_list *new_write; ++ ++ if (!power_state) ++ return; ++ ++ new_write = kmalloc(sizeof(*new_write), GFP_KERNEL); ++ if (new_write) { ++ new_write->rect = *_rect; ++ new_write->buffer_length = _rect->length * _rect->font->font_char_size; ++ new_write->buffer = kmalloc(new_write->buffer_length, GFP_KERNEL); ++ if (new_write->buffer) { ++ list_add_tail(&new_write->list, &write_list.list); ++ memcpy(new_write->buffer, buffer, new_write->buffer_length); ++ il3829_adjust_buffer(new_write); ++ ++ if (is_needs_transpose()) { ++ transpose_buffer(new_write->buffer, &new_write->rect); ++ transpose_rect(&new_write->rect); ++ } ++ il3829_set_area(&new_write->rect); ++ il3829_set_xy(new_write->rect.x1, new_write->rect.y1); ++ il3829_write_ctrl_command(0x24); ++ il3829_write_ctrl_data_buf(new_write->buffer, new_write->buffer_length); ++ } else { ++ kfree(new_write); ++ } ++ } ++} ++ ++static void il3829_init_display(unsigned char is_full_mode) ++{ ++ unsigned char gate_buf[] = { ++ 0x01, // [00] Gate setting ++ 0xC7, // [01] MUX [7:0] *x200 (200-1) ++ 0x00, // [02] MUX [8] ++ 0x00, // [03] Gate scan direction, order, output ++ }; ++ unsigned char bssc_buf[] = { ++ 0x0C, // [04] Booster Soft start Control ++ 0xD7, // [05] Phase1 ++ 0xD6, // [06] Phase2 ++ 0x9D, // [07] Phase3 ++ }; ++ unsigned char vcom_buf[] = { ++ 0x2C, // [08] VCOM ++ 0x9B, // [09] ++ }; ++ unsigned char dummy_buf[] = { ++ 0x3A, // [10] Set dummy line period ++ 0x1A, // [11] 4 dummy line per gate ++ }; ++ unsigned char gate_line_buf[] = { ++ 0x3B, // [12] Set Gate line width ++ 0x08, // [13] 2us per line ++ }; ++ unsigned char data_entry_buf[] = { ++ 0x11, // [1] Data Entry mode setting ++ 0x03, // [1] Y increment, X increment ++ }; ++ ++ if (il3829_display.spi.disp_type == TYPE_IL3820) { ++ gate_buf[1] = 0x27; ++ gate_buf[2] = 0x01; ++ } ++ il3829_write_ctrl_command_data_buf(gate_buf, sizeof(gate_buf)); ++ il3829_write_ctrl_command_data_buf(bssc_buf, sizeof(bssc_buf)); ++ il3829_write_ctrl_command_data_buf(vcom_buf, sizeof(vcom_buf)); ++ il3829_write_ctrl_command_data_buf(dummy_buf, sizeof(dummy_buf)); ++ il3829_write_ctrl_command_data_buf(gate_line_buf, sizeof(gate_line_buf)); ++ il3829_write_ctrl_command_data_buf(data_entry_buf, sizeof(data_entry_buf)); ++ if (is_full_mode) ++ il3829_write_ctrl_command_data_buf(LUTDefault_full, sizeof(LUTDefault_full)); ++ else ++ il3829_write_ctrl_command_data_buf(LUTDefault_part, sizeof(LUTDefault_part)); ++} ++ ++static unsigned char il3829_init(void) ++{ ++ if (il3829_display.spi.is_spi) { ++ if (dev->gpio1_pin.pin >= 0) { ++ protocol = init_sw_spi_3w(MSB_FIRST, dev->clk_pin, dev->dat_pin, dev->stb_pin, il3829_display.flags_low_freq ? SPI_DELAY_100KHz : SPI_DELAY_500KHz); ++ if (protocol) { ++ pin_rst = dev->gpio0_pin.pin; ++ pin_dc = dev->gpio1_pin.pin; ++ pin_busy = dev->gpio2_pin.pin; ++ if (pin_rst >= 0) { ++ gpio_direction_output(pin_rst, 0); ++ udelay(5); ++ gpio_direction_output(pin_rst, 1); ++ } ++ if (pin_busy >= 0) ++ gpio_direction_input(pin_busy); ++ } ++ } else { ++ pr_dbg2("IL3829 controller failed to intialize. Invalid DC (%d) pin\n", dev->gpio1_pin.pin); ++ } ++ } else { ++ if (dev->hw_protocol.protocol == PROTOCOL_I2C) ++ protocol = init_hw_i2c(il3829_display.i2c.address, dev->hw_protocol.device_id); ++ else ++ protocol = init_sw_i2c(il3829_display.i2c.address, MSB_FIRST, 1, dev->clk_pin, dev->dat_pin, il3829_display.flags_low_freq ? I2C_DELAY_100KHz : I2C_DELAY_500KHz, NULL); ++ } ++ if (!protocol) ++ return 0; ++ ++ il3829_write_ctrl_command(0x12); // SW Reset. ++ il3829_clear(); ++ il3829_wait_busy(GxGDEP015OC1_PU_DELAY); ++ ++ return 1; ++} ++ ++static unsigned char il3829_set_display_type(struct vfd_display *display) ++{ ++ unsigned char ret = 0; ++ if (display->controller == CONTROLLER_IL3829) { ++ dev->dtb_active.display = *display; ++ il3829_init(); ++ ret = 1; ++ } ++ ++ return ret; ++} +diff -ruN main/drivers/auxdisplay/openvfd/controllers/il3829.h mod/drivers/auxdisplay/openvfd/controllers/il3829.h +--- main/drivers/auxdisplay/openvfd/controllers/il3829.h 1970-01-01 01:00:00.000000000 +0100 ++++ mod/drivers/auxdisplay/openvfd/controllers/il3829.h 2023-03-07 09:42:01.605533940 +0100 +@@ -0,0 +1,8 @@ ++#ifndef __il3829H__ ++#define __il3829H__ ++ ++#include "controller.h" ++ ++struct controller_interface *init_il3829(struct vfd_dev *_dev); ++ ++#endif +diff -ruN main/drivers/auxdisplay/openvfd/controllers/pcd8544.c mod/drivers/auxdisplay/openvfd/controllers/pcd8544.c +--- main/drivers/auxdisplay/openvfd/controllers/pcd8544.c 1970-01-01 01:00:00.000000000 +0100 ++++ mod/drivers/auxdisplay/openvfd/controllers/pcd8544.c 2023-03-07 09:42:01.613534001 +0100 +@@ -0,0 +1,210 @@ ++#include ++#include "../protocols/i2c_hw.h" ++#include "../protocols/i2c_sw.h" ++#include "../protocols/spi_sw.h" ++#include "pcd8544.h" ++#include "gfx_mono_ctrl.h" ++ ++static unsigned char pcd8544_init(void); ++static unsigned char pcd8544_set_display_type(struct vfd_display *display); ++static void pcd8544_clear(void); ++static void pcd8544_set_power(unsigned char state); ++static void pcd8544_set_contrast(unsigned char value); ++static unsigned char pcd8544_set_xy(unsigned short x, unsigned short y); ++static void pcd8544_print_string(const unsigned char *buffer, const struct rect *rect); ++static void pcd8544_write_ctrl_command_buf(const unsigned char *buf, unsigned int length); ++static void pcd8544_write_ctrl_command(unsigned char cmd); ++static void pcd8544_write_ctrl_data_buf(const unsigned char *buf, unsigned int length); ++static void pcd8544_write_ctrl_data(unsigned char data); ++ ++static struct specific_gfx_mono_ctrl pcd8544_gfx_mono_ctrl = { ++ .init = pcd8544_init, ++ .set_display_type = pcd8544_set_display_type, ++ .clear = pcd8544_clear, ++ .set_power = pcd8544_set_power, ++ .set_contrast = pcd8544_set_contrast, ++ .set_xy = pcd8544_set_xy, ++ .print_char = NULL, ++ .print_string = pcd8544_print_string, ++ .write_ctrl_command_buf = pcd8544_write_ctrl_command_buf, ++ .write_ctrl_command = pcd8544_write_ctrl_command, ++ .write_ctrl_data_buf = pcd8544_write_ctrl_data_buf, ++ .write_ctrl_data = pcd8544_write_ctrl_data, ++ .screen_view = NULL, ++}; ++ ++struct pcd8544_display { ++ unsigned char columns : 3; ++ unsigned char banks : 3; ++ unsigned char offset : 2; ++ ++ union { ++ struct { ++ unsigned char address : 7; ++ unsigned char not_i2c : 1; ++ } i2c; ++ struct { ++ unsigned char reserved1 : 7; ++ unsigned char is_spi : 1; ++ } spi; ++ }; ++ ++ unsigned char flags_secs : 1; ++ unsigned char flags_invert : 1; ++ unsigned char flags_transpose : 1; ++ unsigned char flags_rotate : 1; ++ unsigned char flags_ext_vcc : 1; ++ unsigned char flags_alt_com_conf : 1; ++ unsigned char flags_low_freq : 1; ++ unsigned char reserved2 : 1; ++ ++ unsigned char controller; ++}; ++ ++static struct vfd_dev *dev = NULL; ++static struct protocol_interface *protocol; ++static unsigned char columns = 80; ++static unsigned char banks = 6; ++static unsigned char col_offset = 2; ++static const unsigned char ram_buffer_blank[504] = { 0 }; ++static int pin_rst = 0; ++static int pin_dc = 0; ++struct pcd8544_display pcd8544_display; ++ ++struct controller_interface *init_pcd8544(struct vfd_dev *_dev) ++{ ++ dev = _dev; ++ memcpy(&pcd8544_display, &dev->dtb_active.display, sizeof(pcd8544_display)); ++ columns = (pcd8544_display.columns + 1) * 16; ++ banks = pcd8544_display.banks + 1; ++ col_offset = pcd8544_display.offset << 1; ++ return init_gfx_mono_ctrl(_dev, &pcd8544_gfx_mono_ctrl); ++} ++ ++static void pcd8544_write_ctrl_buf(unsigned char dc, const unsigned char *buf, unsigned int length) ++{ ++ if (pcd8544_display.spi.is_spi) { ++ gpio_direction_output(pin_dc, dc ? 1 : 0); ++ protocol->write_data(buf, length); ++ } else { ++ protocol->write_cmd_data(&dc, 1, buf, length); ++ } ++} ++ ++static void pcd8544_write_ctrl_command_buf(const unsigned char *buf, unsigned int length) ++{ ++ pcd8544_write_ctrl_buf(0x00, buf, length); ++} ++ ++static void pcd8544_write_ctrl_command(unsigned char cmd) ++{ ++ pcd8544_write_ctrl_buf(0x00, &cmd, 1); ++} ++ ++static void pcd8544_write_ctrl_data_buf(const unsigned char *buf, unsigned int length) ++{ ++ pcd8544_write_ctrl_buf(0x40, buf, length); ++} ++ ++static void pcd8544_write_ctrl_data(unsigned char data) ++{ ++ pcd8544_write_ctrl_buf(0x40, &data, 1); ++} ++ ++static void pcd8544_clear(void) ++{ ++ unsigned char cmd_buf[] = { 0x40, 0x80, 0x08 }; ++ pcd8544_write_ctrl_command_buf(cmd_buf, sizeof(cmd_buf)); ++ pcd8544_write_ctrl_data_buf(ram_buffer_blank, sizeof(ram_buffer_blank)); ++ pcd8544_write_ctrl_command(0x0C | pcd8544_display.flags_invert); ++} ++ ++static void pcd8544_set_power(unsigned char state) ++{ ++ if (state) ++ pcd8544_write_ctrl_command(0x0C | pcd8544_display.flags_invert); // Set display On ++ else ++ pcd8544_write_ctrl_command(0x08); // Set display OFF ++} ++ ++static void pcd8544_set_contrast(unsigned char value) ++{ ++ unsigned char cmd_buf[] = { 0x21, 0x80 | (value >> 1), 0x20 }; ++ pcd8544_write_ctrl_command_buf(cmd_buf, sizeof(cmd_buf)); ++} ++ ++static unsigned char pcd8544_set_xy(unsigned short x, unsigned short y) ++{ ++ unsigned char ret = 0; ++ x += col_offset; ++ if (x < columns + col_offset || y < banks) { ++ unsigned char cmd_buf[] = { 0x40 | (y & 0x7), 0x80 | (x & 0x7F) }; ++ pcd8544_write_ctrl_command_buf(cmd_buf, sizeof(cmd_buf)); ++ ret = 1; ++ } ++ ++ return ret; ++} ++ ++static void pcd8544_print_string(const unsigned char *buffer, const struct rect *rect) ++{ ++ unsigned char i; ++ for (i = 0; i < rect->height; i++) { ++ pcd8544_set_xy(rect->x1, rect->y1 + i); ++ pcd8544_write_ctrl_data_buf(buffer + (i * rect->width), rect->width); ++ } ++} ++ ++static unsigned char pcd8544_init(void) ++{ ++ unsigned char cmd_buf[] = { ++ 0x21, // [00] Enable extended instruction set ++ 0xB1, // [01] Set LCD Vop (Contrast) ++ 0x06, // [02] Set Temp coefficent ++ 0x12, // [03] LCD bias mode ++ ++ 0x20, // [04] Disable extended instruction set ++ 0x0C, // [05] Set display On ++ }; ++ ++ if (pcd8544_display.spi.is_spi) { ++ if (dev->gpio0_pin.pin >= 0 && dev->gpio1_pin.pin >= 0) { ++ protocol = init_sw_spi_3w(MSB_FIRST, dev->clk_pin, dev->dat_pin, dev->stb_pin, pcd8544_display.flags_low_freq ? SPI_DELAY_100KHz : SPI_DELAY_500KHz); ++ if (protocol) { ++ pin_rst = dev->gpio0_pin.pin; ++ pin_dc = dev->gpio1_pin.pin; ++ gpio_direction_output(pin_rst, 0); ++ udelay(5); ++ gpio_direction_output(pin_rst, 1); ++ } ++ } else { ++ pr_dbg2("PCD8544 controller failed to intialize. Invalid RESET (%d) and/or DC (%d) pins\n", dev->gpio0_pin.pin, dev->gpio1_pin.pin); ++ } ++ } else { ++ if (dev->hw_protocol.protocol == PROTOCOL_I2C) ++ protocol = init_hw_i2c(pcd8544_display.i2c.address, dev->hw_protocol.device_id); ++ else ++ protocol = init_sw_i2c(pcd8544_display.i2c.address, MSB_FIRST, 1, dev->clk_pin, dev->dat_pin, pcd8544_display.flags_low_freq ? I2C_DELAY_100KHz : I2C_DELAY_500KHz, NULL); ++ } ++ if (!protocol) ++ return 0; ++ ++ cmd_buf[01] = (dev->brightness * 36) + 1; // [01] Contrast ++ cmd_buf[05] |= pcd8544_display.flags_invert ? 0x01 : 0x00; // [05] Set display inverted state ++ pcd8544_write_ctrl_command_buf(cmd_buf, sizeof(cmd_buf)); ++ pcd8544_clear(); ++ ++ return 1; ++} ++ ++static unsigned char pcd8544_set_display_type(struct vfd_display *display) ++{ ++ unsigned char ret = 0; ++ if (display->controller == CONTROLLER_PCD8544) { ++ dev->dtb_active.display = *display; ++ pcd8544_init(); ++ ret = 1; ++ } ++ ++ return ret; ++} +diff -ruN main/drivers/auxdisplay/openvfd/controllers/pcd8544.h mod/drivers/auxdisplay/openvfd/controllers/pcd8544.h +--- main/drivers/auxdisplay/openvfd/controllers/pcd8544.h 1970-01-01 01:00:00.000000000 +0100 ++++ mod/drivers/auxdisplay/openvfd/controllers/pcd8544.h 2023-03-07 09:42:01.625534096 +0100 +@@ -0,0 +1,8 @@ ++#ifndef __PCD8544H__ ++#define __PCD8544H__ ++ ++#include "controller.h" ++ ++struct controller_interface *init_pcd8544(struct vfd_dev *_dev); ++ ++#endif +diff -ruN main/drivers/auxdisplay/openvfd/controllers/seg7_ctrl.c mod/drivers/auxdisplay/openvfd/controllers/seg7_ctrl.c +--- main/drivers/auxdisplay/openvfd/controllers/seg7_ctrl.c 1970-01-01 01:00:00.000000000 +0100 ++++ mod/drivers/auxdisplay/openvfd/controllers/seg7_ctrl.c 2023-03-07 09:42:01.633534158 +0100 +@@ -0,0 +1,106 @@ ++#include "controller.h" ++ ++#define LEDCODES_LEN (sizeof(LED_decode_tab1)/sizeof(LED_decode_tab1[0])) ++const led_bitmap *ledCodes = LED_decode_tab1; ++unsigned char ledDot = p1; ++ ++/** ++ * Source for the transpose algorithm: ++ http://www.hackersdelight.org/hdcodetxt/transpose8.c.txt ++ */ ++void transpose8rS64(unsigned char* A, unsigned char* B) { ++ unsigned long long x = 0, t; ++ int i; ++ ++ for (i = 0; i <= 7; i++) // Load 8 bytes from the input ++ x = x << 8 | A[i]; // array and pack them into x. ++ ++ t = (x ^ (x >> 7)) & 0x00AA00AA00AA00AALL; ++ x = x ^ t ^ (t << 7); ++ t = (x ^ (x >> 14)) & 0x0000CCCC0000CCCCLL; ++ x = x ^ t ^ (t << 14); ++ t = (x ^ (x >> 28)) & 0x00000000F0F0F0F0LL; ++ x = x ^ t ^ (t << 28); ++ ++ memcpy(B, &x, sizeof(x)); // Store result into output array B. ++} ++ ++static unsigned char char_to_mask(unsigned char ch) ++{ ++ unsigned int index = 0; ++ for (index = 0; index < LEDCODES_LEN; index++) { ++ if (ledCodes[index].character == ch) { ++ return ledCodes[index].bitmap; ++ } ++ } ++ ++ return 0; ++} ++ ++size_t seg7_write_display_data(const struct vfd_display_data *data, unsigned short *raw_wdata, size_t sz) ++{ ++ size_t i, len; ++ char buffer[8]; ++ size_t status = sizeof(*data); ++ ++ if (sz < sizeof(unsigned char[7])) ++ return 0; ++ ++ memset(raw_wdata, 0, sz); ++ switch (data->mode) { ++ case DISPLAY_MODE_CLOCK: ++ case DISPLAY_MODE_PLAYBACK_TIME: ++ raw_wdata[0] = data->colon_on ? ledDots[LED_DOT_SEC] : 0; ++ if (data->mode == DISPLAY_MODE_PLAYBACK_TIME && data->time_date.hours == 0) { ++ raw_wdata[1] = char_to_mask(data->time_date.minutes / 10); ++ raw_wdata[2] = char_to_mask(data->time_date.minutes % 10); ++ raw_wdata[3] = char_to_mask(data->time_date.seconds / 10); ++ raw_wdata[4] = char_to_mask(data->time_date.seconds % 10); ++ } else { ++ raw_wdata[1] = char_to_mask(data->time_date.hours / 10); ++ raw_wdata[2] = char_to_mask(data->time_date.hours % 10); ++ raw_wdata[3] = char_to_mask(data->time_date.minutes / 10); ++ raw_wdata[4] = char_to_mask(data->time_date.minutes % 10); ++ } ++ break; ++ case DISPLAY_MODE_CHANNEL: ++ len = scnprintf(buffer, sizeof(buffer), "%*d", 4, data->channel_data.channel % 10000); ++ for (i = 0; i < len; i++) ++ raw_wdata[i + 1] = char_to_mask(buffer[i]); ++ break; ++ case DISPLAY_MODE_TITLE: ++ raw_wdata[0] = 0; ++ for (i = 1; i <= 4; i++) ++ raw_wdata[i] = data->string_main[i - 1] ? char_to_mask(data->string_main[i - 1]) : 0; ++ break; ++ case DISPLAY_MODE_TEMPERATURE: ++ len = scnprintf(buffer, sizeof(buffer), "%d%c%c", data->temperature % 1000, 0xB0, 'c'); // ascii 176 = degree ++ if (len > 4) ++ len = 4; ++ for (i = 0; i < len; i++) ++ raw_wdata[i + 1] = char_to_mask(buffer[i]); ++ break; ++ case DISPLAY_MODE_DATE: ++ { ++ unsigned char day = data->time_date.day; ++ unsigned char month = data->time_date.month + 1; ++ if (data->time_secondary._reserved) { ++ raw_wdata[1] = char_to_mask(month / 10); ++ raw_wdata[2] = char_to_mask(month % 10); ++ raw_wdata[3] = char_to_mask(day / 10); ++ raw_wdata[4] = char_to_mask(day % 10); ++ } else { ++ raw_wdata[1] = char_to_mask(day / 10); ++ raw_wdata[2] = char_to_mask(day % 10); ++ raw_wdata[3] = char_to_mask(month / 10); ++ raw_wdata[4] = char_to_mask(month % 10); ++ } ++ } ++ break; ++ default: ++ status = 0; ++ break; ++ } ++ ++ return status; ++} +diff -ruN main/drivers/auxdisplay/openvfd/controllers/ssd1306.c mod/drivers/auxdisplay/openvfd/controllers/ssd1306.c +--- main/drivers/auxdisplay/openvfd/controllers/ssd1306.c 1970-01-01 01:00:00.000000000 +0100 ++++ mod/drivers/auxdisplay/openvfd/controllers/ssd1306.c 2023-03-07 09:42:01.645534249 +0100 +@@ -0,0 +1,353 @@ ++#include ++#include "../protocols/i2c_hw.h" ++#include "../protocols/i2c_sw.h" ++#include "../protocols/spi_sw.h" ++#include "ssd1306.h" ++#include "gfx_mono_ctrl.h" ++ ++static unsigned char sh1106_init(void); ++static unsigned char ssd1306_init(void); ++static unsigned char ssd1306_set_display_type(struct vfd_display *display); ++static void sh1106_clear(void); ++static void ssd1306_clear(void); ++static void ssd1306_set_power(unsigned char state); ++static void ssd1306_set_contrast(unsigned char value); ++static unsigned char ssd1306_set_xy(unsigned short x, unsigned short y); ++static void ssd1306_print_string(const unsigned char *buffer, const struct rect *rect); ++static void ssd1306_write_ctrl_command_buf(const unsigned char *buf, unsigned int length); ++static void ssd1306_write_ctrl_command(unsigned char cmd); ++static void ssd1306_write_ctrl_data_buf(const unsigned char *buf, unsigned int length); ++static void ssd1306_write_ctrl_data(unsigned char data); ++ ++static struct specific_gfx_mono_ctrl ssd1306_gfx_mono_ctrl = { ++ .init = ssd1306_init, ++ .set_display_type = ssd1306_set_display_type, ++ .clear = ssd1306_clear, ++ .set_power = ssd1306_set_power, ++ .set_contrast = ssd1306_set_contrast, ++ .set_xy = ssd1306_set_xy, ++ .print_char = NULL, ++ .print_string = ssd1306_print_string, ++ .write_ctrl_command_buf = ssd1306_write_ctrl_command_buf, ++ .write_ctrl_command = ssd1306_write_ctrl_command, ++ .write_ctrl_data_buf = ssd1306_write_ctrl_data_buf, ++ .write_ctrl_data = ssd1306_write_ctrl_data, ++ .screen_view = NULL, ++}; ++ ++struct ssd1306_display { ++ unsigned char columns : 3; ++ unsigned char banks : 3; ++ unsigned char offset : 2; ++ ++ union { ++ struct { ++ unsigned char address : 7; ++ unsigned char not_i2c : 1; ++ } i2c; ++ struct { ++ unsigned char is_4w : 1; ++ unsigned char reserved1 : 6; ++ unsigned char is_spi : 1; ++ } spi; ++ }; ++ ++ unsigned char flags_secs : 1; ++ unsigned char flags_invert : 1; ++ unsigned char flags_transpose : 1; ++ unsigned char flags_rotate : 1; ++ unsigned char flags_ext_vcc : 1; ++ unsigned char flags_alt_com_conf : 1; ++ unsigned char flags_low_freq : 1; ++ unsigned char reserved2 : 1; ++ ++ unsigned char controller; ++}; ++ ++static struct vfd_dev *dev = NULL; ++static struct protocol_interface *protocol; ++static unsigned char columns = 128; ++static unsigned char rows = 32; ++static unsigned char banks = 32 / 8; ++static unsigned char col_offset = 0; ++static const unsigned char ram_buffer_blank[1024] = { 0 }; ++static int pin_rst = 0; ++static int pin_dc = 0; ++static struct ssd1306_display ssd1306_display; ++ ++static void (*clear)(void); ++ ++struct controller_interface *init_ssd1306(struct vfd_dev *_dev) ++{ ++ dev = _dev; ++ memcpy(&ssd1306_display, &dev->dtb_active.display, sizeof(ssd1306_display)); ++ columns = (ssd1306_display.columns + 1) * 16; ++ banks = ssd1306_display.banks + 1; ++ rows = banks * 8; ++ col_offset = ssd1306_display.offset << 1; ++ switch (ssd1306_display.controller) { ++ case CONTROLLER_SH1106: ++ clear = sh1106_clear; ++ ssd1306_gfx_mono_ctrl.init = sh1106_init; ++ break; ++ case CONTROLLER_SSD1306: ++ default: ++ clear = ssd1306_clear; ++ ssd1306_gfx_mono_ctrl.init = ssd1306_init; ++ break; ++ } ++ ssd1306_gfx_mono_ctrl.clear = clear; ++ return init_gfx_mono_ctrl(_dev, &ssd1306_gfx_mono_ctrl); ++} ++ ++static void ssd1306_write_ctrl_buf(unsigned char dc, const unsigned char *buf, unsigned int length) ++{ ++ if (ssd1306_display.spi.is_spi && ssd1306_display.spi.is_4w) { ++ gpio_direction_output(pin_dc, dc ? 1 : 0); ++ protocol->write_data(buf, length); ++ } else { ++ protocol->write_cmd_data(&dc, 1, buf, length); ++ } ++} ++ ++static void ssd1306_write_ctrl_command_buf(const unsigned char *buf, unsigned int length) ++{ ++ ssd1306_write_ctrl_buf(0x00, buf, length); ++} ++ ++static void ssd1306_write_ctrl_command(unsigned char cmd) ++{ ++ ssd1306_write_ctrl_buf(0x00, &cmd, 1); ++} ++ ++static void ssd1306_write_ctrl_data_buf(const unsigned char *buf, unsigned int length) ++{ ++ ssd1306_write_ctrl_buf(0x40, buf, length); ++} ++ ++static void ssd1306_write_ctrl_data(unsigned char data) ++{ ++ ssd1306_write_ctrl_buf(0x40, &data, 1); ++} ++ ++static void ssd1306_clear(void) ++{ ++ unsigned char cmd_buf[] = { 0x21, col_offset, col_offset + columns - 1, 0x22, 0x00, banks - 1, 0xAE }; ++ ssd1306_write_ctrl_command_buf(cmd_buf, sizeof(cmd_buf)); ++ ssd1306_write_ctrl_data_buf(ram_buffer_blank, min((size_t)(columns * banks), sizeof(ram_buffer_blank))); ++ ssd1306_write_ctrl_command(0xAF); ++} ++ ++static void sh1106_clear(void) ++{ ++ unsigned char i; ++ ssd1306_write_ctrl_command(0xAE); ++ for (i = 0; i < banks; i++) { ++ ssd1306_set_xy(0, i); ++ ssd1306_write_ctrl_data_buf(ram_buffer_blank, columns); ++ } ++ ssd1306_write_ctrl_command(0xAF); ++} ++ ++static void ssd1306_set_power(unsigned char state) ++{ ++ if (state) ++ ssd1306_write_ctrl_command(0xAF); // Set display On ++ else ++ ssd1306_write_ctrl_command(0xAE); // Set display OFF ++} ++ ++static void ssd1306_set_contrast(unsigned char value) ++{ ++ unsigned char cmd_buf[] = { 0x81, ++value }; ++ ssd1306_write_ctrl_command_buf(cmd_buf, sizeof(cmd_buf)); ++} ++ ++static unsigned char ssd1306_set_xy(unsigned short x, unsigned short y) ++{ ++ unsigned char ret = 0; ++ x += col_offset; ++ if (x < columns + col_offset || y < banks) { ++ unsigned char cmd_buf[] = { 0xB0 | (y & 0xF), x & 0xF, 0x10 | (x >> 4) }; ++ ssd1306_write_ctrl_command_buf(cmd_buf, sizeof(cmd_buf)); ++ ret = 1; ++ } ++ ++ return ret; ++} ++ ++static void ssd1306_print_string(const unsigned char *buffer, const struct rect *rect) ++{ ++ unsigned char i; ++ if (ssd1306_display.controller == CONTROLLER_SH1106) { ++ for (i = 0; i < rect->height; i++) { ++ ssd1306_set_xy(rect->x1, rect->y1 + i); ++ ssd1306_write_ctrl_data_buf(buffer + (i * rect->width), rect->width); ++ } ++ } else { ++ unsigned char cmd_set_addr_range[] = { 0x21, rect->x1 + col_offset, rect->x2 + col_offset, 0x22, rect->y1, rect->y2 }; ++ unsigned char cmd_reset_addr_range[] = { 0x21, col_offset, col_offset + columns - 1, 0x22, 0x00, banks - 1 }; ++ ssd1306_write_ctrl_command_buf(cmd_set_addr_range, sizeof(cmd_set_addr_range)); ++ ssd1306_write_ctrl_data_buf(buffer, rect->length * rect->font->font_char_size); ++ ssd1306_write_ctrl_command_buf(cmd_reset_addr_range, sizeof(cmd_reset_addr_range)); ++ } ++} ++ ++static void init_protocol(void) ++{ ++ if (ssd1306_display.spi.is_spi) { ++ if (dev->gpio0_pin.pin >= 0 && (!ssd1306_display.spi.is_4w || dev->gpio1_pin.pin >= 0)) { ++ protocol = init_sw_spi_3w(MSB_FIRST, dev->clk_pin, dev->dat_pin, dev->stb_pin, ssd1306_display.flags_low_freq ? SPI_DELAY_100KHz : SPI_DELAY_500KHz); ++ if (protocol) { ++ pin_rst = dev->gpio0_pin.pin; ++ pin_dc = dev->gpio1_pin.pin; ++ gpio_direction_output(pin_rst, 0); ++ udelay(5); ++ gpio_direction_output(pin_rst, 1); ++ } ++ } else { ++ pr_dbg2("SSD1306 controller failed to intialize. Invalid RESET (%d) and/or DC (%d) pins\n", dev->gpio0_pin.pin, dev->gpio1_pin.pin); ++ } ++ } else { ++ if (dev->hw_protocol.protocol == PROTOCOL_I2C) ++ protocol = init_hw_i2c(ssd1306_display.i2c.address, dev->hw_protocol.device_id); ++ else ++ protocol = init_sw_i2c(ssd1306_display.i2c.address, MSB_FIRST, 1, dev->clk_pin, dev->dat_pin, ssd1306_display.flags_low_freq ? I2C_DELAY_100KHz : I2C_DELAY_500KHz, NULL); ++ } ++} ++ ++static unsigned char sh1106_init(void) ++{ ++ unsigned char cmd_buf[] = { ++ 0xAE, // [00] Set display OFF ++ ++ 0xA0, // [01] Set Segment Re-Map ++ ++ 0xDA, // [02] Set COM Hardware Configuration ++ 0x02, // [03] COM Hardware Configuration ++ ++ 0xC0, // [04] Set Com Output Scan Direction ++ ++ 0xA8, // [05] Set Multiplex Ratio ++ 0x3F, // [06] Multiplex Ratio for 128x64 (64-1) ++ ++ 0xD5, // [07] Set Display Clock Divide Ratio / OSC Frequency ++ 0x80, // [08] Display Clock Divide Ratio / OSC Frequency ++ ++ 0xDB, // [09] Set VCOMH Deselect Level ++ 0x35, // [10] VCOMH Deselect Level ++ ++ 0x81, // [11] Set Contrast ++ 0x8F, // [12] Contrast ++ ++ 0x30, // [13] Set Vpp ++ ++ 0xAD, // [14] Set DC-DC ++ 0x8A, // [15] DC-DC ON/OFF ++ ++ 0x40, // [16] Set Display Start Line ++ ++ 0xA4, // [17] Set all pixels OFF ++ 0xA6, // [18] Set display not inverted ++ 0xAF, // [19] Set display On ++ }; ++ ++ init_protocol(); ++ if (!protocol) ++ return 0; ++ ++ cmd_buf[1] |= ssd1306_display.flags_rotate ? 0x01 : 0x00; // [01] Set Segment Re-Map ++ cmd_buf[3] |= ssd1306_display.flags_alt_com_conf ? 0x10 : 0x00; // [03] COM Hardware Configuration ++ cmd_buf[4] |= ssd1306_display.flags_rotate ? 0x08 : 0x00; // [04] Set Com Output Scan Direction ++ cmd_buf[6] = max(min(rows-1, 63), 15); // [06] Multiplex Ratio for 128 x rows (rows-1) ++ cmd_buf[12] = (dev->brightness * 36) + 1; // [12] Contrast ++ cmd_buf[15] |= ssd1306_display.flags_ext_vcc ? 0x00 : 0x01; // [15] DC-DC ON/OFF ++ cmd_buf[18] |= ssd1306_display.flags_invert ? 0x01 : 0x00; // [18] Set display not inverted ++ ssd1306_write_ctrl_command_buf(cmd_buf, sizeof(cmd_buf)); ++ clear(); ++ ++ return 1; ++} ++ ++static unsigned char ssd1306_init(void) ++{ ++ unsigned char cmd_buf[] = { ++ 0xAE, // [00] Set display OFF ++ ++ 0xD5, // [01] Set Display Clock Divide Ratio / OSC Frequency ++ 0x80, // [02] Display Clock Divide Ratio / OSC Frequency ++ ++ 0xA8, // [03] Set Multiplex Ratio ++ 0x3F, // [04] Multiplex Ratio for 128x64 (64-1) ++ ++ 0xD3, // [05] Set Display Offset ++ 0x00, // [06] Display Offset ++ ++ 0x8D, // [07] Set Charge Pump ++ 0x14, // [08] Charge Pump (0x10 External, 0x14 Internal DC/DC) ++ ++ 0xA0, // [09] Set Segment Re-Map ++ 0xC0, // [10] Set Com Output Scan Direction ++ ++ 0xDA, // [11] Set COM Hardware Configuration ++ 0x02, // [12] COM Hardware Configuration ++ ++ 0x81, // [13] Set Contrast ++ 0x8F, // [14] Contrast ++ ++ 0xD9, // [15] Set Pre-Charge Period ++ 0xF1, // [16] Set Pre-Charge Period (0x22 External, 0xF1 Internal) ++ ++ 0xDB, // [17] Set VCOMH Deselect Level ++ 0x30, // [18] VCOMH Deselect Level ++ ++ 0x40, // [19] Set Display Start Line ++ ++ 0x20, // [20] Set Memory Addressing Mode ++ 0x00, // [21] Set Horizontal Mode ++ ++ 0x21, // [22] Set Column Address ++ 0x00, // [23] First column ++ 0x7F, // [24] Last column ++ ++ 0x22, // [25] Set Page Address ++ 0x00, // [26] First page ++ 0x07, // [27] Last page ++ ++ 0xA4, // [28] Set all pixels OFF ++ 0xA6, // [29] Set display not inverted ++ 0xAF, // [30] Set display On ++ }; ++ ++ init_protocol(); ++ if (!protocol) ++ return 0; ++ ++ cmd_buf[4] = max(min(rows-1, 63), 15); // [04] Multiplex Ratio for 128 x rows (rows-1) ++ cmd_buf[8] = ssd1306_display.flags_ext_vcc ? 0x10 : 0x14; // [08] Charge Pump (0x10 External, 0x14 Internal DC/DC) ++ cmd_buf[9] |= ssd1306_display.flags_rotate ? 0x01 : 0x00; // [09] Set Segment Re-Map ++ cmd_buf[10] |= ssd1306_display.flags_rotate ? 0x08 : 0x00; // [10] Set Com Output Scan Direction ++ cmd_buf[12] |= ssd1306_display.flags_alt_com_conf ? 0x10 : 0x00; // [12] COM Hardware Configuration ++ cmd_buf[14] = (dev->brightness * 36) + 1; // [14] Contrast ++ cmd_buf[16] = ssd1306_display.flags_ext_vcc ? 0x22 : 0xF1; // [16] Set Pre-Charge Period (0x22 External, 0xF1 Internal) ++ cmd_buf[23] = col_offset; // [23] First column ++ cmd_buf[24] = col_offset + columns - 1; // [24] Last column ++ cmd_buf[27] = banks - 1; // [27] Last page ++ cmd_buf[29] |= ssd1306_display.flags_invert ? 0x01 : 0x00; // [29] Set display not inverted ++ ssd1306_write_ctrl_command_buf(cmd_buf, sizeof(cmd_buf)); ++ clear(); ++ ++ return 1; ++} ++ ++static unsigned char ssd1306_set_display_type(struct vfd_display *display) ++{ ++ unsigned char ret = 0; ++ if (display->controller == CONTROLLER_SSD1306 || display->controller == CONTROLLER_SH1106) { ++ dev->dtb_active.display = *display; ++ ssd1306_init(); ++ ret = 1; ++ } ++ ++ return ret; ++} +diff -ruN main/drivers/auxdisplay/openvfd/controllers/ssd1306.h mod/drivers/auxdisplay/openvfd/controllers/ssd1306.h +--- main/drivers/auxdisplay/openvfd/controllers/ssd1306.h 1970-01-01 01:00:00.000000000 +0100 ++++ mod/drivers/auxdisplay/openvfd/controllers/ssd1306.h 2023-03-07 09:42:01.653534311 +0100 +@@ -0,0 +1,8 @@ ++#ifndef __SSD1306H__ ++#define __SSD1306H__ ++ ++#include "controller.h" ++ ++struct controller_interface *init_ssd1306(struct vfd_dev *_dev); ++ ++#endif +diff -ruN main/drivers/auxdisplay/openvfd/glyphs.h mod/drivers/auxdisplay/openvfd/glyphs.h +--- main/drivers/auxdisplay/openvfd/glyphs.h 1970-01-01 01:00:00.000000000 +0100 ++++ mod/drivers/auxdisplay/openvfd/glyphs.h 2023-03-07 09:42:01.397532327 +0100 +@@ -0,0 +1,339 @@ ++#ifndef __GLYPHS__ ++#define __GLYPHS__ ++ ++typedef unsigned char u_int8; ++typedef unsigned short u_int16; ++typedef unsigned long u_int32; ++ ++/** Character conversion of digital tube display code*/ ++typedef struct _led_bitmap { ++ u_int8 character; ++ u_int8 bitmap; ++}led_bitmap; ++ ++/** Character conversion of digital tube display code array*/ ++ ++#define a1 0x01 ++#define b1 0x02 ++#define c1 0x04 ++#define d1 0x08 ++#define e1 0x10 ++#define f1 0x20 ++#define g1 0x40 ++#define p1 0x80 ++ ++static const led_bitmap LED_decode_tab1[] = { ++/* ++ * Most displays have 5 sections, 1 - 4 are the digits, ++ * the 5th is mapped to indicators (5A-5G). ++ * The 7 segment sequences are shown below. ++ * ++ * dp ++ * +--d/08--+ ++ * | | ++ * c/04 | | e/10 ++ * +--g/40--+ ++ * | | ++ * b/02 | | f/20 ++ * +--a/01--+ ++ * ++ */ ++ ++ {0, a1|b1|c1|d1|e1|f1 }, {1, e1|f1 }, ++ {2, a1|b1|d1|e1|g1 }, {3, a1|d1|e1|f1|g1 }, ++ {4, c1|e1|f1|g1 }, {5, a1|c1|d1|f1|g1 }, ++ {6, a1|b1|c1|d1|f1|g1 }, {7, d1|e1|f1 }, ++ {8, a1|b1|c1|d1|e1|f1|g1}, {9, a1|c1|d1|e1|f1|g1 }, ++ ++ {'0', a1|b1|c1|d1|e1|f1 }, {'1', e1|f1 }, ++ {'2', a1|b1|d1|e1|g1 }, {'3', a1|d1|e1|f1|g1 }, ++ {'4', c1|e1|f1|g1 }, {'5', a1|c1|d1|f1|g1 }, ++ {'6', a1|b1|c1|d1|f1|g1 }, {'7', d1|e1|f1 }, ++ {'8', a1|b1|c1|d1|e1|f1|g1}, {'9', a1|c1|d1|e1|f1|g1 }, ++ ++ {'a', b1|c1|d1|e1|f1|g1 }, {'A', b1|c1|d1|e1|f1|g1 }, ++ {'b', a1|b1|c1|f1|g1 }, {'B', a1|b1|c1|f1|g1 }, ++ {'c', a1|b1|c1|d1 }, {'C', a1|b1|c1|d1 }, ++ {'d', a1|b1|e1|f1|g1 }, {'D', a1|b1|e1|f1|g1 }, ++ {'e', a1|b1|c1|d1|g1 }, {'E', a1|b1|c1|d1|g1 }, ++ {'f', b1|c1|d1|g1 }, {'F', b1|c1|d1|g1 }, ++ {'g', a1|b1|c1|d1|f1 }, {'G', a1|b1|c1|d1|f1 }, ++ {'h', b1|c1|f1|g1 }, {'H', b1|c1|f1|g1 }, ++ {'i', b1|c1 }, {'I', b1|c1 }, ++ {'j', a1|b1|e1|f1 }, {'J', a1|b1|e1|f1 }, ++ {'k', b1|c1|d1|f1|g1 }, {'K', b1|c1|d1|f1|g1 }, ++ {'l', a1|b1|c1 }, {'L', a1|b1|c1 }, ++ {'m', b1|d1|f1 }, {'M', b1|d1|f1 }, ++ {'n', b1|c1|d1|e1|f1 }, {'N', b1|c1|d1|e1|f1 }, ++ {'o', a1|b1|f1|g1 }, {'O', a1|b1|f1|g1 }, ++ {'p', b1|c1|d1|e1|g1 }, {'P', b1|c1|d1|e1|g1 }, ++ {'q', c1|d1|e1|f1|g1 }, {'Q', c1|d1|e1|f1|g1 }, ++ {'r', b1|g1 }, {'R', b1|g1 }, ++ {'s', a1|c1|d1|f1|g1 }, {'S', a1|c1|d1|f1|g1 }, ++ {'t', a1|b1|c1|g1 }, {'T', a1|b1|c1|g1 }, ++ {'u', a1|b1|f1 }, {'U', a1|b1|f1 }, ++ {'v', a1|b1|c1|e1|f1 }, {'V', a1|b1|c1|e1|f1 }, ++ {'w', a1|c1|e1 }, {'W', a1|c1|e1 }, ++ {'x', b1|c1|e1|f1|g1 }, {'X', b1|c1|e1|f1|g1 }, ++ {'y', a1|c1|e1|f1|g1 }, {'Y', a1|c1|e1|f1|g1 }, ++ {'z', a1|b1|d1|e1|g1 }, {'Z', a1|b1|d1|e1|g1 }, ++ {'_', a1}, {'-', g1}, {' ', 0}, { 0xB0, c1|d1|e1|g1 } ++}; ++ ++#define a2 0x08 ++#define b2 0x10 ++#define c2 0x20 ++#define d2 0x01 ++#define e2 0x02 ++#define f2 0x04 ++#define g2 0x40 ++#define p2 0x80 ++ ++static const led_bitmap LED_decode_tab2[] = { ++/* ++ * ++ * dp ++ * +--d/01--+ ++ * | | ++ * c/20 | | e/02 ++ * +--g/40--+ ++ * | | ++ * b/10 | | f/04 ++ * +--a/08--+ ++ * ++ */ ++ ++ {0, a2|b2|c2|d2|e2|f2 }, {1, e2|f2 }, ++ {2, a2|b2|d2|e2|g2 }, {3, a2|d2|e2|f2|g2 }, ++ {4, c2|e2|f2|g2 }, {5, a2|c2|d2|f2|g2 }, ++ {6, a2|b2|c2|d2|f2|g2 }, {7, d2|e2|f2 }, ++ {8, a2|b2|c2|d2|e2|f2|g2}, {9, a2|c2|d2|e2|f2|g2 }, ++ ++ {'0', a2|b2|c2|d2|e2|f2 }, {'1', e2|f2 }, ++ {'2', a2|b2|d2|e2|g2 }, {'3', a2|d2|e2|f2|g2 }, ++ {'4', c2|e2|f2|g2 }, {'5', a2|c2|d2|f2|g2 }, ++ {'6', a2|b2|c2|d2|f2|g2 }, {'7', d2|e2|f2 }, ++ {'8', a2|b2|c2|d2|e2|f2|g2}, {'9', a2|c2|d2|e2|f2|g2 }, ++ ++ {'a', b2|c2|d2|e2|f2|g2 }, {'A', b2|c2|d2|e2|f2|g2 }, ++ {'b', a2|b2|c2|f2|g2 }, {'B', a2|b2|c2|f2|g2 }, ++ {'c', a2|b2|c2|d2 }, {'C', a2|b2|c2|d2 }, ++ {'d', a2|b2|e2|f2|g2 }, {'D', a2|b2|e2|f2|g2 }, ++ {'e', a2|b2|c2|d2|g2 }, {'E', a2|b2|c2|d2|g2 }, ++ {'f', b2|c2|d2|g2 }, {'F', b2|c2|d2|g2 }, ++ {'g', a2|b2|c2|d2|f2 }, {'G', a2|b2|c2|d2|f2 }, ++ {'h', b2|c2|f2|g2 }, {'H', b2|c2|f2|g2 }, ++ {'i', b2|c2 }, {'I', b2|c2 }, ++ {'j', a2|b2|e2|f2 }, {'J', a2|b2|e2|f2 }, ++ {'k', b2|c2|d2|f2|g2 }, {'K', b2|c2|d2|f2|g2 }, ++ {'l', a2|b2|c2 }, {'L', a2|b2|c2 }, ++ {'m', b2|d2|f2 }, {'M', b2|d2|f2 }, ++ {'n', b2|c2|d2|e2|f2 }, {'N', b2|c2|d2|e2|f2 }, ++ {'o', a2|b2|f2|g2 }, {'O', a2|b2|f2|g2 }, ++ {'p', b2|c2|d2|e2|g2 }, {'P', b2|c2|d2|e2|g2 }, ++ {'q', c2|d2|e2|f2|g2 }, {'Q', c2|d2|e2|f2|g2 }, ++ {'r', b2|g2 }, {'R', b2|g2 }, ++ {'s', a2|c2|d2|f2|g2 }, {'S', a2|c2|d2|f2|g2 }, ++ {'t', a2|b2|c2|g2 }, {'T', a2|b2|c2|g2 }, ++ {'u', a2|b2|f2 }, {'U', a2|b2|f2 }, ++ {'v', a2|b2|c2|e2|f2 }, {'V', a2|b2|c2|e2|f2 }, ++ {'w', a2|c2|e2 }, {'W', a2|c2|e2 }, ++ {'x', b2|c2|e2|f2|g2 }, {'X', b2|c2|e2|f2|g2 }, ++ {'y', a2|c2|e2|f2|g2 }, {'Y', a2|c2|e2|f2|g2 }, ++ {'z', a2|b2|d2|e2|g2 }, {'Z', a2|b2|d2|e2|g2 }, ++ {'_', a2}, {'-', g2}, {' ', 0}, { 0xB0, c2|d2|e2|g2 } ++}; ++ ++#define a3 0x01 ++#define b3 0x08 ++#define c3 0x20 ++#define d3 0x02 ++#define e3 0x10 ++#define f3 0x04 ++#define g3 0x40 ++#define p3 0x80 ++ ++static const led_bitmap LED_decode_tab3[] = { ++/* ++ * ++ * dp ++ * +--d/02--+ ++ * | | ++ * c/20 | | e/10 ++ * +--g/40--+ ++ * | | ++ * b/08 | | f/04 ++ * +--a/01--+ ++ * ++ */ ++ ++ {0, a3|b3|c3|d3|e3|f3 }, {1, e3|f3 }, ++ {2, a3|b3|d3|e3|g3 }, {3, a3|d3|e3|f3|g3 }, ++ {4, c3|e3|f3|g3 }, {5, a3|c3|d3|f3|g3 }, ++ {6, a3|b3|c3|d3|f3|g3 }, {7, d3|e3|f3 }, ++ {8, a3|b3|c3|d3|e3|f3|g3}, {9, a3|c3|d3|e3|f3|g3 }, ++ ++ {'0', a3|b3|c3|d3|e3|f3 }, {'1', e3|f3 }, ++ {'2', a3|b3|d3|e3|g3 }, {'3', a3|d3|e3|f3|g3 }, ++ {'4', c3|e3|f3|g3 }, {'5', a3|c3|d3|f3|g3 }, ++ {'6', a3|b3|c3|d3|f3|g3 }, {'7', d3|e3|f3 }, ++ {'8', a3|b3|c3|d3|e3|f3|g3}, {'9', a3|c3|d3|e3|f3|g3 }, ++ ++ {'a', b3|c3|d3|e3|f3|g3 }, {'A', b3|c3|d3|e3|f3|g3 }, ++ {'b', a3|b3|c3|f3|g3 }, {'B', a3|b3|c3|f3|g3 }, ++ {'c', a3|b3|c3|d3 }, {'C', a3|b3|c3|d3 }, ++ {'d', a3|b3|e3|f3|g3 }, {'D', a3|b3|e3|f3|g3 }, ++ {'e', a3|b3|c3|d3|g3 }, {'E', a3|b3|c3|d3|g3 }, ++ {'f', b3|c3|d3|g3 }, {'F', b3|c3|d3|g3 }, ++ {'g', a3|b3|c3|d3|f3 }, {'G', a3|b3|c3|d3|f3 }, ++ {'h', b3|c3|f3|g3 }, {'H', b3|c3|f3|g3 }, ++ {'i', b3|c3 }, {'I', b3|c3 }, ++ {'j', a3|b3|e3|f3 }, {'J', a3|b3|e3|f3 }, ++ {'k', b3|c3|d3|f3|g3 }, {'K', b3|c3|d3|f3|g3 }, ++ {'l', a3|b3|c3 }, {'L', a3|b3|c3 }, ++ {'m', b3|d3|f3 }, {'M', b3|d3|f3 }, ++ {'n', b3|c3|d3|e3|f3 }, {'N', b3|c3|d3|e3|f3 }, ++ {'o', a3|b3|f3|g3 }, {'O', a3|b3|f3|g3 }, ++ {'p', b3|c3|d3|e3|g3 }, {'P', b3|c3|d3|e3|g3 }, ++ {'q', c3|d3|e3|f3|g3 }, {'Q', c3|d3|e3|f3|g3 }, ++ {'r', b3|g3 }, {'R', b3|g3 }, ++ {'s', a3|c3|d3|f3|g3 }, {'S', a3|c3|d3|f3|g3 }, ++ {'t', a3|b3|c3|g3 }, {'T', a3|b3|c3|g3 }, ++ {'u', a3|b3|f3 }, {'U', a3|b3|f3 }, ++ {'v', a3|b3|c3|e3|f3 }, {'V', a3|b3|c3|e3|f3 }, ++ {'w', a3|c3|e3 }, {'W', a3|c3|e3 }, ++ {'x', b3|c3|e3|f3|g3 }, {'X', b3|c3|e3|f3|g3 }, ++ {'y', a3|c3|e3|f3|g3 }, {'Y', a3|c3|e3|f3|g3 }, ++ {'z', a3|b3|d3|e3|g3 }, {'Z', a3|b3|d3|e3|g3 }, ++ {'_', a3}, {'-', g3}, {' ', 0}, { 0xB0, c3|d3|e3|g3 } ++}; ++ ++#define a4 0x04 ++#define b4 0x02 ++#define c4 0x80 ++#define d4 0x01 ++#define e4 0x40 ++#define f4 0x10 ++#define g4 0x20 ++#define p4 0x08 ++ ++static const led_bitmap LED_decode_tab4[] = { ++/* ++ * ++ * dp ++ * +--d/01--+ ++ * | | ++ * c/80 | | e/40 ++ * +--g/20--+ ++ * | | ++ * b/02 | | f/10 ++ * +--a/04--+.p/08 ++ * ++ */ ++ ++ {0, a4|b4|c4|d4|e4|f4 }, {1, e4|f4 }, ++ {2, a4|b4|d4|e4|g4 }, {3, a4|d4|e4|f4|g4 }, ++ {4, c4|e4|f4|g4 }, {5, a4|c4|d4|f4|g4 }, ++ {6, a4|b4|c4|d4|f4|g4 }, {7, d4|e4|f4 }, ++ {8, a4|b4|c4|d4|e4|f4|g4}, {9, a4|c4|d4|e4|f4|g4 }, ++ ++ {'0', a4|b4|c4|d4|e4|f4 }, {'1', e4|f4 }, ++ {'2', a4|b4|d4|e4|g4 }, {'3', a4|d4|e4|f4|g4 }, ++ {'4', c4|e4|f4|g4 }, {'5', a4|c4|d4|f4|g4 }, ++ {'6', a4|b4|c4|d4|f4|g4 }, {'7', d4|e4|f4 }, ++ {'8', a4|b4|c4|d4|e4|f4|g4}, {'9', a4|c4|d4|e4|f4|g4 }, ++ ++ {'a', b4|c4|d4|e4|f4|g4 }, {'A', b4|c4|d4|e4|f4|g4 }, ++ {'b', a4|b4|c4|f4|g4 }, {'B', a4|b4|c4|f4|g4 }, ++ {'c', a4|b4|c4|d4 }, {'C', a4|b4|c4|d4 }, ++ {'d', a4|b4|e4|f4|g4 }, {'D', a4|b4|e4|f4|g4 }, ++ {'e', a4|b4|c4|d4|g4 }, {'E', a4|b4|c4|d4|g4 }, ++ {'f', b4|c4|d4|g4 }, {'F', b4|c4|d4|g4 }, ++ {'g', a4|b4|c4|d4|f4 }, {'G', a4|b4|c4|d4|f4 }, ++ {'h', b4|c4|f4|g4 }, {'H', b4|c4|f4|g4 }, ++ {'i', b4|c4 }, {'I', b4|c4 }, ++ {'j', a4|b4|e4|f4 }, {'J', a4|b4|e4|f4 }, ++ {'k', b4|c4|d4|f4|g4 }, {'K', b4|c4|d4|f4|g4 }, ++ {'l', a4|b4|c4 }, {'L', a4|b4|c4 }, ++ {'m', b4|d4|f4 }, {'M', b4|d4|f4 }, ++ {'n', b4|c4|d4|e4|f4 }, {'N', b4|c4|d4|e4|f4 }, ++ {'o', a4|b4|f4|g4 }, {'O', a4|b4|f4|g4 }, ++ {'p', b4|c4|d4|e4|g4 }, {'P', b4|c4|d4|e4|g4 }, ++ {'q', c4|d4|e4|f4|g4 }, {'Q', c4|d4|e4|f4|g4 }, ++ {'r', b4|g4 }, {'R', b4|g4 }, ++ {'s', a4|c4|d4|f4|g4 }, {'S', a4|c4|d4|f4|g4 }, ++ {'t', a4|b4|c4|g4 }, {'T', a4|b4|c4|g4 }, ++ {'u', a4|b4|f4 }, {'U', a4|b4|f4 }, ++ {'v', a4|b4|c4|e4|f4 }, {'V', a4|b4|c4|e4|f4 }, ++ {'w', a4|c4|e4 }, {'W', a4|c4|e4 }, ++ {'x', b4|c4|e4|f4|g4 }, {'X', b4|c4|e4|f4|g4 }, ++ {'y', a4|c4|e4|f4|g4 }, {'Y', a4|c4|e4|f4|g4 }, ++ {'z', a4|b4|d4|e4|g4 }, {'Z', a4|b4|d4|e4|g4 }, ++ {'_', a4}, {'-', g4}, {' ', 0}, { 0xB0, c4|d4|e4|g4 } ++}; ++ ++#define a5 0x40 ++#define b5 0x20 ++#define c5 0x10 ++#define d5 0x01 ++#define e5 0x02 ++#define f5 0x04 ++#define g5 0x08 ++#define p5 0x80 ++ ++static const led_bitmap LED_decode_tab5[] = { ++/* ++ * ++ * dp ++ * +--d/01--+ ++ * | | ++ * c/10 | | e/02 ++ * +--g/08--+ ++ * | | ++ * b/20 | | f/04 ++ * +--a/40--+ ++ * ++ */ ++ ++ {0, a5|b5|c5|d5|e5|f5 }, {1, e5|f5 }, ++ {2, a5|b5|d5|e5|g5 }, {3, a5|d5|e5|f5|g5 }, ++ {4, c5|e5|f5|g5 }, {5, a5|c5|d5|f5|g5 }, ++ {6, a5|b5|c5|d5|f5|g5 }, {7, d5|e5|f5 }, ++ {8, a5|b5|c5|d5|e5|f5|g5}, {9, a5|c5|d5|e5|f5|g5 }, ++ ++ {'0', a5|b5|c5|d5|e5|f5 }, {'1', e5|f5 }, ++ {'2', a5|b5|d5|e5|g5 }, {'3', a5|d5|e5|f5|g5 }, ++ {'4', c5|e5|f5|g5 }, {'5', a5|c5|d5|f5|g5 }, ++ {'6', a5|b5|c5|d5|f5|g5 }, {'7', d5|e5|f5 }, ++ {'8', a5|b5|c5|d5|e5|f5|g5}, {'9', a5|c5|d5|e5|f5|g5 }, ++ ++ {'a', b5|c5|d5|e5|f5|g5 }, {'A', b5|c5|d5|e5|f5|g5 }, ++ {'b', a5|b5|c5|f5|g5 }, {'B', a5|b5|c5|f5|g5 }, ++ {'c', a5|b5|c5|d5 }, {'C', a5|b5|c5|d5 }, ++ {'d', a5|b5|e5|f5|g5 }, {'D', a5|b5|e5|f5|g5 }, ++ {'e', a5|b5|c5|d5|g5 }, {'E', a5|b5|c5|d5|g5 }, ++ {'f', b5|c5|d5|g5 }, {'F', b5|c5|d5|g5 }, ++ {'g', a5|b5|c5|d5|f5 }, {'G', a5|b5|c5|d5|f5 }, ++ {'h', b5|c5|f5|g5 }, {'H', b5|c5|f5|g5 }, ++ {'i', b5|c5 }, {'I', b5|c5 }, ++ {'j', a5|b5|e5|f5 }, {'J', a5|b5|e5|f5 }, ++ {'k', b5|c5|d5|f5|g5 }, {'K', b5|c5|d5|f5|g5 }, ++ {'l', a5|b5|c5 }, {'L', a5|b5|c5 }, ++ {'m', b5|d5|f5 }, {'M', b5|d5|f5 }, ++ {'n', b5|c5|d5|e5|f5 }, {'N', b5|c5|d5|e5|f5 }, ++ {'o', a5|b5|f5|g5 }, {'O', a5|b5|f5|g5 }, ++ {'p', b5|c5|d5|e5|g5 }, {'P', b5|c5|d5|e5|g5 }, ++ {'q', c5|d5|e5|f5|g5 }, {'Q', c5|d5|e5|f5|g5 }, ++ {'r', b5|g5 }, {'R', b5|g5 }, ++ {'s', a5|c5|d5|f5|g5 }, {'S', a5|c5|d5|f5|g5 }, ++ {'t', a5|b5|c5|g5 }, {'T', a5|b5|c5|g5 }, ++ {'u', a5|b5|f5 }, {'U', a5|b5|f5 }, ++ {'v', a5|b5|c5|e5|f5 }, {'V', a5|b5|c5|e5|f5 }, ++ {'w', a5|c5|e5 }, {'W', a5|c5|e5 }, ++ {'x', b5|c5|e5|f5|g5 }, {'X', b5|c5|e5|f5|g5 }, ++ {'y', a5|c5|e5|f5|g5 }, {'Y', a5|c5|e5|f5|g5 }, ++ {'z', a5|b5|d5|e5|g5 }, {'Z', a5|b5|d5|e5|g5 }, ++ {'_', a5}, {'-', g5}, {' ', 0}, { 0xB0, c5|d5|e5|g5 } ++}; ++ ++#endif +diff -ruN main/drivers/auxdisplay/openvfd/Makefile mod/drivers/auxdisplay/openvfd/Makefile +--- main/drivers/auxdisplay/openvfd/Makefile 1970-01-01 01:00:00.000000000 +0100 ++++ mod/drivers/auxdisplay/openvfd/Makefile 2023-03-07 09:42:01.425532543 +0100 +@@ -0,0 +1,14 @@ ++obj-$(CONFIG_OPENVFD) := openvfd.o ++openvfd-objs += protocols/i2c_sw.o ++openvfd-objs += protocols/i2c_hw.o ++openvfd-objs += protocols/spi_sw.o ++openvfd-objs += controllers/dummy.o ++openvfd-objs += controllers/seg7_ctrl.o ++openvfd-objs += controllers/fd628.o ++openvfd-objs += controllers/fd650.o ++openvfd-objs += controllers/hd44780.o ++openvfd-objs += controllers/gfx_mono_ctrl.o ++openvfd-objs += controllers/ssd1306.o ++openvfd-objs += controllers/pcd8544.o ++openvfd-objs += controllers/il3829.o ++openvfd-objs += openvfd_drv.o +diff -ruN main/drivers/auxdisplay/openvfd/openvfd_drv.c mod/drivers/auxdisplay/openvfd/openvfd_drv.c +--- main/drivers/auxdisplay/openvfd/openvfd_drv.c 1970-01-01 01:00:00.000000000 +0100 ++++ mod/drivers/auxdisplay/openvfd/openvfd_drv.c 2023-03-07 09:42:01.437532636 +0100 +@@ -0,0 +1,1043 @@ ++/* ++ * Open VFD Driver ++ * ++ * Copyright (C) 2018 Arthur Liberman (arthur_liberman (at) hotmail.com) ++ * ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "openvfd_drv.h" ++#include "controllers/controller_list.h" ++ ++#ifdef CONFIG_HAS_EARLYSUSPEND ++#include ++static struct early_suspend openvfd_early_suspend; ++#elif CONFIG_AMLOGIC_LEGACY_EARLY_SUSPEND ++#include ++static struct early_suspend openvfd_early_suspend; ++#endif ++ ++unsigned char vfd_display_auto_power = 1; ++ ++static struct vfd_platform_data *pdata = NULL; ++struct kp { ++ struct led_classdev cdev; ++}; ++ ++static struct kp *kp; ++ ++static struct controller_interface *controller = NULL; ++static struct mutex mutex; ++ ++/**************************************************************** ++ * Function Name: FD628_GetKey ++ * Description: Read key code value ++ * Parameters: void ++ * Return value: INT32U returns the key value ++ ************************************************************************************************************************************** ++Key value encoding ++ | 0 | 0 | 0 | 0 | 0 | 0 | KS10 | KS9 | KS8 | KS7 | KS6 | KS5 | KS4 | KS3 | KS2 | KS1 | ++KEYI1 | bit15 | bit14 | bit13 | bit12 | bit11 | bit10 | bit9 | bit8 | bit7 | bit6 | bit5 | bit4 | bit3 | bit2 | bit1 | bit0 | ++KEYI2 | bit31 | bit30 | bit29 | bit28 | bit27 | bit26 | bit25 | bit24 | bit23 | bit22 | bit21 | bit20 | bit19 | bit18 | bit17 | bit16 | ++***************************************************************************************************************************************/ ++static u_int32 FD628_GetKey(struct vfd_dev *dev) ++{ ++ u_int8 i, keyDataBytes[5]; ++ u_int32 FD628_KeyData = 0; ++ mutex_lock(&mutex); ++ controller->read_data(keyDataBytes, sizeof(keyDataBytes)); ++ mutex_unlock(&mutex); ++ for (i = 0; i != 5; i++) { /* Pack 5 bytes of key code values into 2 words */ ++ if (keyDataBytes[i] & 0x01) ++ FD628_KeyData |= (0x00000001 << i * 2); ++ if (keyDataBytes[i] & 0x02) ++ FD628_KeyData |= (0x00010000 << i * 2); ++ if (keyDataBytes[i] & 0x08) ++ FD628_KeyData |= (0x00000002 << i * 2); ++ if (keyDataBytes[i] & 0x10) ++ FD628_KeyData |= (0x00020000 << i * 2); ++ } ++ ++ return (FD628_KeyData); ++} ++ ++static void unlocked_set_power(unsigned char state) ++{ ++ if (vfd_display_auto_power && controller) { ++ controller->set_power(state); ++ if (state && pdata) ++ controller->set_brightness_level(pdata->dev->brightness); ++ } ++} ++ ++static void set_power(unsigned char state) ++{ ++ mutex_lock(&mutex); ++ unlocked_set_power(state); ++ mutex_unlock(&mutex); ++} ++ ++static void init_controller(struct vfd_dev *dev) ++{ ++ struct controller_interface *temp_ctlr; ++ ++ switch (dev->dtb_active.display.controller) { ++ case CONTROLLER_FD628: ++ case CONTROLLER_FD620: ++ case CONTROLLER_TM1618: ++ pr_dbg2("Select FD628 controller\n"); ++ temp_ctlr = init_fd628(dev); ++ break; ++ case CONTROLLER_HBS658: ++ pr_dbg2("Select HBS658 controller\n"); ++ temp_ctlr = init_fd628(dev); ++ break; ++ case CONTROLLER_FD650: ++ pr_dbg2("Select FD650 controller\n"); ++ temp_ctlr = init_fd650(dev); ++ break; ++ case CONTROLLER_FD655: ++ pr_dbg2("Select FD655 controller\n"); ++ temp_ctlr = init_fd650(dev); ++ break; ++ case CONTROLLER_FD6551: ++ pr_dbg2("Select FD6551 controller\n"); ++ temp_ctlr = init_fd650(dev); ++ break; ++ case CONTROLLER_IL3829: ++ pr_dbg2("Select IL3829 controller\n"); ++ temp_ctlr = init_il3829(dev); ++ break; ++ case CONTROLLER_PCD8544: ++ pr_dbg2("Select PCD8544 controller\n"); ++ temp_ctlr = init_pcd8544(dev); ++ break; ++ case CONTROLLER_SH1106: ++ pr_dbg2("Select SH1106 controller\n"); ++ temp_ctlr = init_ssd1306(dev); ++ break; ++ case CONTROLLER_SSD1306: ++ pr_dbg2("Select SSD1306 controller\n"); ++ temp_ctlr = init_ssd1306(dev); ++ break; ++ case CONTROLLER_HD44780: ++ pr_dbg2("Select HD44780 controller\n"); ++ temp_ctlr = init_hd47780(dev); ++ break; ++ default: ++ pr_dbg2("Select Dummy controller\n"); ++ temp_ctlr = init_dummy(dev); ++ break; ++ } ++ ++ if (controller != temp_ctlr) { ++ unlocked_set_power(0); ++ controller = temp_ctlr; ++ if (!controller->init()) { ++ pr_dbg2("Failed to initialize the controller, reverting to Dummy controller\n"); ++ controller = init_dummy(dev); ++ dev->dtb_active.display.controller = CONTROLLER_7S_MAX; ++ } ++ } ++} ++ ++static int openvfd_dev_open(struct inode *inode, struct file *file) ++{ ++ struct vfd_dev *dev = NULL; ++ file->private_data = pdata->dev; ++ dev = file->private_data; ++ memset(dev->wbuf, 0x00, sizeof(dev->wbuf)); ++ set_power(1); ++ pr_dbg("openvfd_dev_open now.............................\r\n"); ++ return 0; ++} ++ ++static int openvfd_dev_release(struct inode *inode, struct file *file) ++{ ++ set_power(0); ++ file->private_data = NULL; ++ pr_dbg("succes to close openvfd_dev.............\n"); ++ return 0; ++} ++ ++static ssize_t openvfd_dev_read(struct file *filp, char __user * buf, ++ size_t count, loff_t * f_pos) ++{ ++ __u32 disk = 0; ++ struct vfd_dev *dev = filp->private_data; ++ __u32 diskvalue = 0; ++ int ret = 0; ++ int rbuf[2] = { 0 }; ++ //pr_dbg("start read keyboard value...............\r\n"); ++ if (dev->Keyboard_diskstatus == 1) { ++ diskvalue = FD628_GetKey(dev); ++ if (diskvalue == 0) ++ return 0; ++ } ++ dev->key_respond_status = 0; ++ rbuf[1] = dev->key_fg; ++ if (dev->key_fg) ++ rbuf[0] = disk; ++ else ++ rbuf[0] = diskvalue; ++ //pr_dbg("Keyboard value:%d\n, status : %d\n",rbuf[0],rbuf[1]); ++ ret = copy_to_user(buf, rbuf, sizeof(rbuf)); ++ if (ret == 0) ++ return sizeof(rbuf); ++ else ++ return ret; ++} ++ ++/** ++ * @param buf: Incoming LED codes. ++ * [0] Display indicators mask (wifi, eth, usb, etc.) ++ * [1-4] 7 segment characters, to be displayed left to right. ++ * @return ++ */ ++static ssize_t openvfd_dev_write(struct file *filp, const char __user * buf, ++ size_t count, loff_t * f_pos) ++{ ++ ssize_t status = 0; ++ unsigned long missing; ++ static struct vfd_display_data data; ++ ++ if (count == sizeof(data)) { ++ missing = copy_from_user(&data, buf, count); ++ if (missing == 0 && count > 0) { ++ mutex_lock(&mutex); ++ if (controller->write_display_data(&data)) ++ pr_dbg("openvfd_dev_write count : %ld\n", count); ++ else { ++ status = -1; ++ pr_error("openvfd_dev_write failed to write %ld bytes (display_data)\n", count); ++ } ++ mutex_unlock(&mutex); ++ } ++ } else if (count > 0) { ++ unsigned char *raw_data; ++ pr_dbg2("openvfd_dev_write: count = %ld, sizeof(data) = %ld\n", count, sizeof(data)); ++ raw_data = kzalloc(count, GFP_KERNEL); ++ if (raw_data) { ++ missing = copy_from_user(raw_data, buf, count); ++ mutex_lock(&mutex); ++ if (controller->write_data((unsigned char*)raw_data, count)) ++ pr_dbg("openvfd_dev_write count : %ld\n", count); ++ else { ++ status = -1; ++ pr_error("openvfd_dev_write failed to write %ld bytes (raw_data)\n", count); ++ } ++ mutex_unlock(&mutex); ++ kfree(raw_data); ++ } ++ else { ++ status = -1; ++ pr_error("openvfd_dev_write failed to allocate %ld bytes (raw_data)\n", count); ++ } ++ } ++ ++ return status; ++} ++ ++static int set_display_brightness(struct vfd_dev *dev, u_int8 new_brightness) ++{ ++ return controller->set_brightness_level(new_brightness); ++} ++ ++static void set_display_type(struct vfd_dev *dev, int new_display_type) ++{ ++ memcpy(&dev->dtb_active.display, &new_display_type, sizeof(struct vfd_display)); ++ init_controller(dev); ++} ++ ++static long openvfd_dev_ioctl(struct file *filp, unsigned int cmd, ++ unsigned long arg) ++{ ++ int err = 0, ret = 0, temp = 0; ++ struct vfd_dev *dev; ++ __u8 val = 1; ++ __u8 temp_chars_order[sizeof(dev->dtb_active.dat_index)]; ++ dev = filp->private_data; ++ ++ if (_IOC_TYPE(cmd) != VFD_IOC_MAGIC) ++ return -ENOTTY; ++ if (_IOC_NR(cmd) >= VFD_IOC_MAXNR) ++ return -ENOTTY; ++ if (_IOC_DIR(cmd) & _IOC_READ) ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5,0,0)) ++ err = !access_ok((void __user *)arg, _IOC_SIZE(cmd)); ++#else ++ err = !access_ok(VERIFY_WRITE, (void __user *)arg, _IOC_SIZE(cmd)); ++#endif ++ else if (_IOC_DIR(cmd) & _IOC_WRITE) ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5,0,0)) ++ err = !access_ok((void __user *)arg, _IOC_SIZE(cmd)); ++#else ++ err = !access_ok(VERIFY_READ, (void __user *)arg, _IOC_SIZE(cmd)); ++#endif ++ if (err) ++ return -EFAULT; ++ ++ mutex_lock(&mutex); ++ switch (cmd) { ++ case VFD_IOC_USE_DTB_CONFIG: ++ dev->dtb_active = dev->dtb_default; ++ init_controller(dev); ++ break; ++ case VFD_IOC_GDISPLAY_TYPE: ++ memcpy(&temp, &dev->dtb_active.display, sizeof(int)); ++ ret = __put_user(temp, (int __user *)arg); ++ break; ++ case VFD_IOC_SDISPLAY_TYPE: ++ ret = __get_user(temp, (int __user *)arg); ++ if (!ret) ++ set_display_type(dev, temp); ++ break; ++ case VFD_IOC_SCHARS_ORDER: ++ ret = __copy_from_user(temp_chars_order, (__u8 __user *)arg, sizeof(dev->dtb_active.dat_index)); ++ if (!ret) ++ memcpy(dev->dtb_active.dat_index, temp_chars_order, sizeof(dev->dtb_active.dat_index)); ++ break; ++ case VFD_IOC_SMODE: /* Set: arg points to the value */ ++ ret = __get_user(dev->mode, (int __user *)arg); ++ //FD628_SET_DISPLAY_MODE(dev->mode, dev); ++ break; ++ case VFD_IOC_GMODE: /* Get: arg is pointer to result */ ++ ret = __put_user(dev->mode, (int __user *)arg); ++ break; ++ case VFD_IOC_GVER: ++ ret = ++ copy_to_user((unsigned char __user *)arg, ++ OPENVFD_DRIVER_VERSION, ++ sizeof(OPENVFD_DRIVER_VERSION)); ++ break; ++ case VFD_IOC_SBRIGHT: ++ ret = __get_user(temp, (int __user *)arg); ++ if (!ret && !set_display_brightness(dev, (u_int8)temp)) ++ ret = -ERANGE; ++ break; ++ case VFD_IOC_GBRIGHT: ++ ret = __put_user(dev->brightness, (int __user *)arg); ++ break; ++ case VFD_IOC_POWER: ++ ret = __get_user(val, (int __user *)arg); ++ controller->set_power(val); ++ break; ++ case VFD_IOC_STATUS_LED: ++ ret = __get_user(dev->status_led_mask, (int __user *)arg); ++ break; ++ default: /* redundant, as cmd was checked against MAXNR */ ++ ret = -ENOTTY; ++ break; ++ } ++ ++ mutex_unlock(&mutex); ++ return ret; ++} ++ ++static unsigned int openvfd_dev_poll(struct file *filp, poll_table * wait) ++{ ++ unsigned int mask = 0; ++ struct vfd_dev *dev = filp->private_data; ++ poll_wait(filp, &dev->kb_waitq, wait); ++ if (dev->key_respond_status) ++ mask |= POLLIN | POLLRDNORM; ++ return mask; ++} ++ ++static struct file_operations openvfd_fops = { ++ .owner = THIS_MODULE, ++ .open = openvfd_dev_open, ++ .release = openvfd_dev_release, ++ .read = openvfd_dev_read, ++ .write = openvfd_dev_write, ++ .unlocked_ioctl = openvfd_dev_ioctl, ++ .compat_ioctl = openvfd_dev_ioctl, ++ .poll = openvfd_dev_poll, ++}; ++ ++static struct miscdevice openvfd_device = { ++ .minor = MISC_DYNAMIC_MINOR, ++ .name = DEV_NAME, ++ .fops = &openvfd_fops, ++}; ++ ++static int register_openvfd_driver(void) ++{ ++ int ret = 0; ++ ret = misc_register(&openvfd_device); ++ if (ret) ++ pr_dbg("%s: failed to add openvfd module\n", __func__); ++ else ++ pr_dbg("%s: Succeeded to add openvfd module \n", __func__); ++ return ret; ++} ++ ++static void deregister_openvfd_driver(void) ++{ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4,0,0) ++ int ret = 0; ++ ret = misc_deregister(&openvfd_device); ++ if (ret) ++ pr_dbg("%s: failed to deregister openvfd module\n", __func__); ++ else ++ pr_dbg("%s: Succeeded to deregister openvfd module \n", __func__); ++#else ++ misc_deregister(&openvfd_device); ++#endif ++} ++ ++ ++static void openvfd_brightness_set(struct led_classdev *cdev, ++ enum led_brightness brightness) ++{ ++ pr_info("brightness = %d\n", brightness); ++ ++ if(pdata == NULL) ++ return; ++} ++ ++static int led_cmd_ioc = 0; ++ ++static ssize_t led_cmd_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ ssize_t ret = 0; ++ *buf = '\0'; ++ ++ switch(led_cmd_ioc) { ++ case VFD_IOC_GMODE: ++ ret = scnprintf(buf, PAGE_SIZE, "%d", pdata->dev->mode); ++ break; ++ case VFD_IOC_GBRIGHT: ++ ret = scnprintf(buf, PAGE_SIZE, "%d", pdata->dev->brightness); ++ break; ++ case VFD_IOC_GVER: ++ ret = scnprintf(buf, PAGE_SIZE, "%s", OPENVFD_DRIVER_VERSION); ++ break; ++ case VFD_IOC_GDISPLAY_TYPE: ++ ret = scnprintf(buf, PAGE_SIZE, "0x%02X%02X%02X%02X", pdata->dev->dtb_active.display.reserved, pdata->dev->dtb_active.display.flags, ++ pdata->dev->dtb_active.display.controller, pdata->dev->dtb_active.display.type); ++ break; ++ } ++ ++ led_cmd_ioc = 0; ++ return ret; ++} ++ ++static ssize_t led_cmd_store(struct device *_dev, ++ struct device_attribute *attr, const char *buf, size_t size) ++{ ++ struct vfd_dev *dev = pdata->dev; ++ int cmd, temp; ++ led_cmd_ioc = 0; ++ ++ if (size < 2*sizeof(int)) ++ return -EFAULT; ++ memcpy(&cmd, buf, sizeof(int)); ++ if (_IOC_TYPE(cmd) != VFD_IOC_MAGIC) ++ return -ENOTTY; ++ if (_IOC_NR(cmd) >= VFD_IOC_MAXNR) ++ return -ENOTTY; ++ ++ buf += sizeof(int); ++ memcpy(&temp, buf, sizeof(int)); ++ mutex_lock(&mutex); ++ switch (cmd) { ++ case VFD_IOC_SMODE: ++ dev->mode = (u_int8)temp; ++ //FD628_SET_DISPLAY_MODE(dev->mode, dev); ++ break; ++ case VFD_IOC_SBRIGHT: ++ if (!set_display_brightness(dev, (u_int8)temp)) ++ size = -ERANGE; ++ break; ++ case VFD_IOC_POWER: ++ controller->set_power(temp); ++ break; ++ case VFD_IOC_STATUS_LED: ++ dev->status_led_mask = (u_int8)temp; ++ break; ++ case VFD_IOC_SDISPLAY_TYPE: ++ set_display_type(dev, temp); ++ break; ++ case VFD_IOC_SCHARS_ORDER: ++ if (size >= sizeof(dev->dtb_active.dat_index)+sizeof(int)) ++ memcpy(dev->dtb_active.dat_index, buf, sizeof(dev->dtb_active.dat_index)); ++ else ++ size = -EFAULT; ++ break; ++ case VFD_IOC_USE_DTB_CONFIG: ++ pdata->dev->dtb_active = pdata->dev->dtb_default; ++ init_controller(dev); ++ break; ++ case VFD_IOC_GMODE: ++ case VFD_IOC_GBRIGHT: ++ case VFD_IOC_GVER: ++ case VFD_IOC_GDISPLAY_TYPE: ++ led_cmd_ioc = cmd; ++ break; ++ } ++ ++ mutex_unlock(&mutex); ++ return size; ++} ++ ++static ssize_t led_on_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ return scnprintf(buf, PAGE_SIZE, "led status is 0x%x\n", pdata->dev->status_led_mask); ++} ++ ++static ssize_t led_on_store(struct device *dev, ++ struct device_attribute *attr, const char *buf, size_t size) ++{ ++ mutex_lock(&mutex); ++ controller->set_icon(buf, 1); ++ mutex_unlock(&mutex); ++ return size; ++} ++ ++static ssize_t led_off_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ return scnprintf(buf, PAGE_SIZE, "led status is 0x%x\n", pdata->dev->status_led_mask); ++} ++ ++static ssize_t led_off_store(struct device *dev, ++ struct device_attribute *attr, const char *buf, size_t size) ++{ ++ mutex_lock(&mutex); ++ controller->set_icon(buf, 0); ++ mutex_unlock(&mutex); ++ return size; ++} ++ ++static DEVICE_ATTR(led_cmd , S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP, led_cmd_show , led_cmd_store); ++static DEVICE_ATTR(led_on , S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP, led_on_show , led_on_store); ++static DEVICE_ATTR(led_off , S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP, led_off_show , led_off_store); ++ ++#if defined(CONFIG_HAS_EARLYSUSPEND) || defined(CONFIG_AMLOGIC_LEGACY_EARLY_SUSPEND) ++static void openvfd_suspend(struct early_suspend *h) ++{ ++ pr_info("%s!\n", __func__); ++ set_power(0); ++} ++ ++static void openvfd_resume(struct early_suspend *h) ++{ ++ pr_info("%s!\n", __func__); ++ set_power(1); ++} ++#endif ++ ++char *vfd_gpio_chip_name = NULL; ++unsigned int vfd_gpio_clk[3]; ++unsigned int vfd_gpio_dat[3]; ++unsigned int vfd_gpio_stb[3]; ++unsigned int vfd_gpio0[3] = { 0x00, 0x00, 0xFF }; ++unsigned int vfd_gpio1[3] = { 0x00, 0x00, 0xFF }; ++unsigned int vfd_gpio2[3] = { 0x00, 0x00, 0xFF }; ++unsigned int vfd_gpio3[3] = { 0x00, 0x00, 0xFF }; ++unsigned int vfd_gpio_protocol[2] = { 0x00, 0x00 }; ++unsigned int vfd_chars[7] = { 0, 1, 2, 3, 4, 5, 6 }; ++unsigned int vfd_dot_bits[8] = { 0, 1, 2, 3, 4, 5, 6, 0 }; ++unsigned int vfd_display_type[4] = { 0x00, 0x00, 0x00, 0x00 }; ++int vfd_gpio_clk_argc = 0; ++int vfd_gpio_dat_argc = 0; ++int vfd_gpio_stb_argc = 0; ++int vfd_gpio0_argc = 3; ++int vfd_gpio1_argc = 3; ++int vfd_gpio2_argc = 3; ++int vfd_gpio3_argc = 3; ++int vfd_gpio_protocol_argc = 2; ++int vfd_chars_argc = 0; ++int vfd_dot_bits_argc = 0; ++int vfd_display_type_argc = 0; ++ ++module_param(vfd_gpio_chip_name, charp, 0000); ++module_param_array(vfd_gpio_clk, uint, &vfd_gpio_clk_argc, 0000); ++module_param_array(vfd_gpio_dat, uint, &vfd_gpio_dat_argc, 0000); ++module_param_array(vfd_gpio_stb, uint, &vfd_gpio_stb_argc, 0000); ++module_param_array(vfd_gpio0, uint, &vfd_gpio0_argc, 0000); ++module_param_array(vfd_gpio1, uint, &vfd_gpio1_argc, 0000); ++module_param_array(vfd_gpio2, uint, &vfd_gpio2_argc, 0000); ++module_param_array(vfd_gpio3, uint, &vfd_gpio3_argc, 0000); ++module_param_array(vfd_gpio_protocol, uint, &vfd_gpio_protocol_argc, 0000); ++module_param_array(vfd_chars, uint, &vfd_chars_argc, 0000); ++module_param_array(vfd_dot_bits, uint, &vfd_dot_bits_argc, 0000); ++module_param_array(vfd_display_type, uint, &vfd_display_type_argc, 0000); ++module_param(vfd_display_auto_power, byte, 0000); ++ ++static void print_param_debug(const char *label, int argc, unsigned int param[]) ++{ ++ int i, len = 0; ++ char buffer[1024]; ++ len = scnprintf(buffer, sizeof(buffer), "%s", label); ++ if (argc) ++ for (i = 0; i < argc; i++) ++ len += scnprintf(buffer + len, sizeof(buffer), "#%d = 0x%02X; ", i, param[i]); ++ else ++ len += scnprintf(buffer + len, sizeof(buffer), "Empty."); ++ pr_dbg2("%s\n", buffer); ++} ++ ++static int is_right_chip(struct gpio_chip *chip, void *data) ++{ ++ pr_dbg("is_right_chip %s | %s | %d\n", chip->label, (char*)data, strcmp(data, chip->label)); ++ if (strcmp(data, chip->label) == 0) ++ return 1; ++ return 0; ++} ++ ++static int get_chip_pin_number(const unsigned int gpio[]) ++{ ++ int pin = -1; ++ struct gpio_chip *chip; ++ const char *bank_name = vfd_gpio_chip_name; ++ if (!bank_name && gpio[0] < 6) { ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4,0,0) ++ const char *pin_banks[] = { "banks", "ao-bank", "gpio0", "gpio1", "gpio2", "gpio3" }; ++#else ++ const char *pin_banks[] = { "periphs-banks", "aobus-banks", "gpio0", "gpio1", "gpio2", "gpio3" }; ++#endif ++ bank_name = pin_banks[gpio[0]]; ++ } ++ ++ if (bank_name) { ++ chip = gpiochip_find((char *)bank_name, is_right_chip); ++ if (chip) { ++ if (chip->ngpio > gpio[1]) ++ pin = chip->base + gpio[1]; ++ pr_dbg2("\"%s\" chip found.\tbase = %d, pin count = %d, pin = %d, offset = %d\n", bank_name, chip->base, chip->ngpio, gpio[1], pin); ++ } else { ++ pr_dbg2("\"%s\" chip was not found\n", bank_name); ++ } ++ } else { ++ pr_dbg2("gpiochip name was not provided or gpiochip index %d is out of bounds\n", gpio[0]); ++ } ++ ++ return pin; ++} ++ ++int evaluate_pin(const char *name, const unsigned int *vfd_arg, struct vfd_pin *pin, unsigned char enable_skip_evaluation) ++{ ++ int ret = 0; ++ if (enable_skip_evaluation && vfd_arg[2] == 0xFF) { ++ pin->pin = -2; ++ pr_dbg2("Skipping %s evaluation (0xFF)\n", name); ++ } ++ else if ((ret = pin->pin = get_chip_pin_number(vfd_arg)) >= 0) ++ pin->flags.value = vfd_arg[2]; ++ else ++ pr_error("Could not get pin number for %s\n", name); ++ return ret; ++} ++ ++char gpio_chip_names[1024] = { 0 }; ++ ++static int enum_gpio_chips(struct gpio_chip *chip, void *data) ++{ ++ static unsigned char first_iteration = 1; ++ const char *sep = ", "; ++ size_t str_len = strlen(gpio_chip_names); ++ if (first_iteration) ++ sep = ""; ++ scnprintf(gpio_chip_names + str_len, sizeof(gpio_chip_names) - str_len, "%s%s", sep, chip->label); ++ first_iteration = 0; ++ return 0; ++} ++ ++static int verify_module_params(struct vfd_dev *dev) ++{ ++ int ret = (vfd_gpio_clk_argc == 3 && vfd_gpio_dat_argc == 3 && vfd_gpio_stb_argc == 3 && ++ vfd_chars_argc >= 5 && vfd_dot_bits_argc >= 7 && vfd_display_type_argc == 4) ? 1 : -1; ++ u_int8 allow_skip_clk_dat_evaluation = vfd_gpio_protocol[0] > 0; ++ ++ print_param_debug("vfd_gpio_clk:\t\t", vfd_gpio_clk_argc, vfd_gpio_clk); ++ print_param_debug("vfd_gpio_dat:\t\t", vfd_gpio_dat_argc, vfd_gpio_dat); ++ print_param_debug("vfd_gpio_stb:\t\t", vfd_gpio_stb_argc, vfd_gpio_stb); ++ print_param_debug("vfd_gpio0:\t\t", vfd_gpio0_argc, vfd_gpio0); ++ print_param_debug("vfd_gpio1:\t\t", vfd_gpio1_argc, vfd_gpio1); ++ print_param_debug("vfd_gpio2:\t\t", vfd_gpio2_argc, vfd_gpio2); ++ print_param_debug("vfd_gpio3:\t\t", vfd_gpio3_argc, vfd_gpio3); ++ print_param_debug("vfd_gpio_protocol:\t", vfd_gpio_protocol_argc, vfd_gpio_protocol); ++ print_param_debug("vfd_chars:\t\t", vfd_chars_argc, vfd_chars); ++ print_param_debug("vfd_dot_bits:\t\t", vfd_dot_bits_argc, vfd_dot_bits); ++ print_param_debug("vfd_display_type:\t", vfd_display_type_argc, vfd_display_type); ++ ++ dev->hw_protocol.protocol = (u_int8)vfd_gpio_protocol[0]; ++ dev->hw_protocol.device_id = (u_int8)vfd_gpio_protocol[1]; ++ ++ gpiochip_find(NULL, enum_gpio_chips); ++ pr_dbg2("Detected gpio chips:\t%s.\n", gpio_chip_names); ++ if (ret >= 0) ++ ret = evaluate_pin("vfd_gpio_clk", vfd_gpio_clk, &dev->clk_pin, allow_skip_clk_dat_evaluation); ++ if (ret >= 0) ++ ret = evaluate_pin("vfd_gpio_dat", vfd_gpio_dat, &dev->dat_pin, allow_skip_clk_dat_evaluation); ++ if (ret >= 0) ++ ret = evaluate_pin("vfd_gpio_stb", vfd_gpio_stb, &dev->stb_pin, 1); ++ if (ret >= 0) ++ ret = evaluate_pin("vfd_gpio0", vfd_gpio0, &dev->gpio0_pin, 1); ++ if (ret >= 0) ++ ret = evaluate_pin("vfd_gpio1", vfd_gpio1, &dev->gpio1_pin, 1); ++ if (ret >= 0) ++ ret = evaluate_pin("vfd_gpio2", vfd_gpio2, &dev->gpio2_pin, 1); ++ if (ret >= 0) ++ ret = evaluate_pin("vfd_gpio3", vfd_gpio3, &dev->gpio3_pin, 1); ++ ++ if (ret >= 0) { ++ int i; ++ for (i = 0; i < 7; i++) ++ dev->dtb_active.dat_index[i] = (u_int8)vfd_chars[i]; ++ for (i = 0; i < 8; i++) ++ dev->dtb_active.led_dots[i] = (u_int8)ledDots[vfd_dot_bits[i]]; ++ dev->dtb_active.display.type = (u_int8)vfd_display_type[0]; ++ dev->dtb_active.display.reserved = (u_int8)vfd_display_type[1]; ++ dev->dtb_active.display.flags = (u_int8)vfd_display_type[2]; ++ dev->dtb_active.display.controller = (u_int8)vfd_display_type[3]; ++ } ++ ++ return ret >= 0; ++} ++ ++void get_pin_from_dt(const char *name, const struct platform_device *pdev, struct vfd_pin *pin) ++{ ++ if (of_find_property(pdev->dev.of_node, name, NULL)) { ++ pin->pin = of_get_named_gpio_flags(pdev->dev.of_node, name, 0, &pin->flags.value); ++ pr_dbg2("%s: pin = %d, flags = 0x%02X\n", name, pin->pin, pin->flags.value); ++ } else { ++ pin->pin = -2; ++ pr_dbg2("%s pin entry not found\n", name); ++ } ++} ++ ++int request_pin(const char *name, struct vfd_pin *pin, unsigned char enable_skip) ++{ ++ int ret = 0; ++ pin->flags.bits.is_requested = 0; ++ if (!enable_skip || pin->pin != -2) { ++ ret = -1; ++ if (pin->pin >= 0) ++ ret = gpio_request(pin->pin, DEV_NAME); ++ if (!ret) ++ pin->flags.bits.is_requested = 1; ++ else ++ pr_error("can't request gpio of %s", name); ++ } ++ return ret; ++} ++ ++static int openvfd_driver_probe(struct platform_device *pdev) ++{ ++ int state = -EINVAL; ++ struct property *chars_prop = NULL; ++ struct property *dot_bits_prop = NULL; ++ struct property *display_type_prop = NULL; ++ int ret = 0; ++ u_int8 allow_skip_clk_dat_request = vfd_gpio_protocol[0] > 0; ++ ++ pr_dbg("%s get in\n", __func__); ++ ++ if (!pdev->dev.of_node) { ++ pr_error("openvfd_driver: pdev->dev.of_node == NULL!\n"); ++ state = -EINVAL; ++ goto get_openvfd_node_fail; ++ } ++ ++ pdata = kzalloc(sizeof(struct vfd_platform_data), GFP_KERNEL); ++ if (!pdata) { ++ pr_error("platform data is required!\n"); ++ state = -EINVAL; ++ goto get_openvfd_mem_fail; ++ } ++ ++ pdata->dev = kzalloc(sizeof(*(pdata->dev)), GFP_KERNEL); ++ if (!(pdata->dev)) { ++ pr_error("platform dev is required!\n"); ++ goto get_param_mem_fail; ++ } ++ ++ pdata->dev->mutex = &mutex; ++ pr_dbg2("Version: %s\n", OPENVFD_DRIVER_VERSION); ++ if (!verify_module_params(pdata->dev)) { ++ int i; ++ __u8 j; ++ pr_error("Failed to verify VFD configuration file, attempt using device tree as fallback.\n"); ++ get_pin_from_dt(MOD_NAME_CLK, pdev, &pdata->dev->clk_pin); ++ get_pin_from_dt(MOD_NAME_DAT, pdev, &pdata->dev->dat_pin); ++ get_pin_from_dt(MOD_NAME_STB, pdev, &pdata->dev->stb_pin); ++ get_pin_from_dt(MOD_NAME_GPIO0, pdev, &pdata->dev->gpio0_pin); ++ get_pin_from_dt(MOD_NAME_GPIO1, pdev, &pdata->dev->gpio1_pin); ++ get_pin_from_dt(MOD_NAME_GPIO2, pdev, &pdata->dev->gpio2_pin); ++ get_pin_from_dt(MOD_NAME_GPIO3, pdev, &pdata->dev->gpio3_pin); ++ ++ chars_prop = of_find_property(pdev->dev.of_node, MOD_NAME_CHARS, NULL); ++ if (!chars_prop || !chars_prop->value) { ++ pr_error("can't find %s list, falling back to defaults.", MOD_NAME_CHARS); ++ chars_prop = NULL; ++ } ++ else if (chars_prop->length < 5) { ++ pr_error("%s list is too short, falling back to defaults.", MOD_NAME_CHARS); ++ chars_prop = NULL; ++ } ++ ++ for (j = 0; j < (sizeof(pdata->dev->dtb_active.dat_index) / sizeof(char)); j++) ++ pdata->dev->dtb_active.dat_index[j] = j; ++ pr_dbg2("chars_prop = %p\n", chars_prop); ++ if (chars_prop) { ++ __u8 *c = (__u8*)chars_prop->value; ++ const int length = min(chars_prop->length, (int)(sizeof(pdata->dev->dtb_active.dat_index) / sizeof(char))); ++ pr_dbg2("chars_prop->length = %d\n", chars_prop->length); ++ for (i = 0; i < length; i++) { ++ pdata->dev->dtb_active.dat_index[i] = c[i]; ++ pr_dbg2("char #%d: %d\n", i, c[i]); ++ } ++ } ++ ++ dot_bits_prop = of_find_property(pdev->dev.of_node, MOD_NAME_DOTS, NULL); ++ if (!dot_bits_prop || !dot_bits_prop->value) { ++ pr_error("can't find %s list, falling back to defaults.", MOD_NAME_DOTS); ++ dot_bits_prop = NULL; ++ } ++ else if (dot_bits_prop->length < LED_DOT_MAX) { ++ pr_error("%s list is too short, falling back to defaults.", MOD_NAME_DOTS); ++ dot_bits_prop = NULL; ++ } ++ ++ for (i = 0; i < LED_DOT_MAX; i++) ++ pdata->dev->dtb_active.led_dots[i] = ledDots[i]; ++ pr_dbg2("dot_bits_prop = %p\n", dot_bits_prop); ++ if (dot_bits_prop) { ++ __u8 *d = (__u8*)dot_bits_prop->value; ++ pr_dbg2("dot_bits_prop->length = %d\n", dot_bits_prop->length); ++ for (i = 0; i < dot_bits_prop->length; i++) { ++ pdata->dev->dtb_active.led_dots[i] = ledDots[d[i]]; ++ pr_dbg2("dot_bit #%d: %d\n", i, d[i]); ++ } ++ } ++ ++ memset(&pdata->dev->dtb_active.display, 0, sizeof(struct vfd_display)); ++ display_type_prop = of_find_property(pdev->dev.of_node, MOD_NAME_TYPE, NULL); ++ if (display_type_prop && display_type_prop->value) ++ of_property_read_u32(pdev->dev.of_node, MOD_NAME_TYPE, (int*)&pdata->dev->dtb_active.display); ++ pr_dbg2("display.type = %d, display.controller = %d, pdata->dev->dtb_active.display.flags = 0x%02X\n", ++ pdata->dev->dtb_active.display.type, pdata->dev->dtb_active.display.controller, pdata->dev->dtb_active.display.flags); ++ } ++ ++ if (request_pin("gpio_clk", &pdata->dev->clk_pin, allow_skip_clk_dat_request)) ++ goto get_gpio_req_fail; ++ if (request_pin("dat_pin", &pdata->dev->dat_pin, allow_skip_clk_dat_request)) ++ goto get_gpio_req_fail; ++ if (request_pin("stb_pin", &pdata->dev->stb_pin, 1)) ++ goto get_gpio_req_fail; ++ if (request_pin("gpio0_pin", &pdata->dev->gpio0_pin, 1)) ++ goto get_gpio_req_fail; ++ if (request_pin("gpio1_pin", &pdata->dev->gpio1_pin, 1)) ++ goto get_gpio_req_fail; ++ if (request_pin("gpio2_pin", &pdata->dev->gpio2_pin, 1)) ++ goto get_gpio_req_fail; ++ if (request_pin("gpio3_pin", &pdata->dev->gpio3_pin, 1)) ++ goto get_gpio_req_fail; ++ ++ pdata->dev->dtb_default = pdata->dev->dtb_active; ++ pdata->dev->brightness = 0xFF; ++ ++ mutex_lock(&mutex); ++ register_openvfd_driver(); ++ kp = kzalloc(sizeof(struct kp) , GFP_KERNEL); ++ if (!kp) { ++ kfree(kp); ++ mutex_unlock(&mutex); ++ return -ENOMEM; ++ } ++ kp->cdev.name = DEV_NAME; ++ kp->cdev.brightness_set = openvfd_brightness_set; ++ ret = led_classdev_register(&pdev->dev, &kp->cdev); ++ if (ret < 0) { ++ kfree(kp); ++ mutex_unlock(&mutex); ++ return ret; ++ } ++ ++ device_create_file(kp->cdev.dev, &dev_attr_led_on); ++ device_create_file(kp->cdev.dev, &dev_attr_led_off); ++ device_create_file(kp->cdev.dev, &dev_attr_led_cmd); ++ init_controller(pdata->dev); ++#if 0 ++ // TODO: Display 'boot' during POST/boot. ++ // 'boot' ++ // 1 1 0 0 1 1 1 b => 0x7C ++ // 1 1 0 0 0 1 1 o => 0x5C ++ // 1 0 0 0 1 1 1 t => 0x78 ++ __u8 data[7]; ++ data[0] = 0x00; ++ data[1] = pdata->dev->dtb_active.display.flags & DISPLAY_TYPE_TRANSPOSED ? 0x7C : 0x67; ++ data[2] = pdata->dev->dtb_active.display.flags & DISPLAY_TYPE_TRANSPOSED ? 0x5C : 0x63; ++ data[3] = pdata->dev->dtb_active.display.flags & DISPLAY_TYPE_TRANSPOSED ? 0x5C : 0x63; ++ data[4] = pdata->dev->dtb_active.display.flags & DISPLAY_TYPE_TRANSPOSED ? 0x78 : 0x47; ++ for (i = 0; i < 5; i++) { ++ pdata->dev->wbuf[pdata->dev->dtb_active.dat_index[i]] = data[i]; ++ } ++ // Write data in incremental mode ++ FD628_WrDisp_AddrINC(0x00, 2*5, pdata->dev); ++#endif ++ ++#if defined(CONFIG_HAS_EARLYSUSPEND) || defined(CONFIG_AMLOGIC_LEGACY_EARLY_SUSPEND) ++ openvfd_early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN; ++ openvfd_early_suspend.suspend = openvfd_suspend; ++ openvfd_early_suspend.resume = openvfd_resume; ++ register_early_suspend(&openvfd_early_suspend); ++#endif ++ ++ mutex_unlock(&mutex); ++ return 0; ++ ++ get_gpio_req_fail: ++ if (pdata->dev->gpio3_pin.flags.bits.is_requested) ++ gpio_free(pdata->dev->gpio3_pin.pin); ++ if (pdata->dev->gpio2_pin.flags.bits.is_requested) ++ gpio_free(pdata->dev->gpio2_pin.pin); ++ if (pdata->dev->gpio1_pin.flags.bits.is_requested) ++ gpio_free(pdata->dev->gpio1_pin.pin); ++ if (pdata->dev->gpio0_pin.flags.bits.is_requested) ++ gpio_free(pdata->dev->gpio0_pin.pin); ++ if (pdata->dev->stb_pin.flags.bits.is_requested) ++ gpio_free(pdata->dev->stb_pin.pin); ++ if (pdata->dev->dat_pin.flags.bits.is_requested) ++ gpio_free(pdata->dev->dat_pin.pin); ++ if (pdata->dev->clk_pin.flags.bits.is_requested) ++ gpio_free(pdata->dev->clk_pin.pin); ++ get_param_mem_fail: ++ kfree(pdata->dev); ++ get_openvfd_mem_fail: ++ kfree(pdata); ++ get_openvfd_node_fail: ++ if (pdata && pdata->dev) ++ mutex_unlock(&mutex); ++ return state; ++} ++ ++static int openvfd_driver_remove(struct platform_device *pdev) ++{ ++ set_power(0); ++#if defined(CONFIG_HAS_EARLYSUSPEND) || defined(CONFIG_AMLOGIC_LEGACY_EARLY_SUSPEND) ++ unregister_early_suspend(&openvfd_early_suspend); ++#endif ++ led_classdev_unregister(&kp->cdev); ++ deregister_openvfd_driver(); ++#ifdef CONFIG_OF ++ if (pdata->dev->gpio3_pin.flags.bits.is_requested) ++ gpio_free(pdata->dev->gpio3_pin.pin); ++ if (pdata->dev->gpio2_pin.flags.bits.is_requested) ++ gpio_free(pdata->dev->gpio2_pin.pin); ++ if (pdata->dev->gpio1_pin.flags.bits.is_requested) ++ gpio_free(pdata->dev->gpio1_pin.pin); ++ if (pdata->dev->gpio0_pin.flags.bits.is_requested) ++ gpio_free(pdata->dev->gpio0_pin.pin); ++ if (pdata->dev->stb_pin.flags.bits.is_requested) ++ gpio_free(pdata->dev->stb_pin.pin); ++ if (pdata->dev->dat_pin.flags.bits.is_requested) ++ gpio_free(pdata->dev->dat_pin.pin); ++ if (pdata->dev->clk_pin.flags.bits.is_requested) ++ gpio_free(pdata->dev->clk_pin.pin); ++ kfree(pdata->dev); ++ kfree(pdata); ++ pdata = NULL; ++#endif ++ return 0; ++} ++ ++static void openvfd_driver_shutdown(struct platform_device *dev) ++{ ++ pr_dbg("openvfd_driver_shutdown"); ++ set_power(0); ++} ++ ++static int openvfd_driver_suspend(struct platform_device *dev, pm_message_t state) ++{ ++ pr_dbg("openvfd_driver_suspend"); ++ if (vfd_display_auto_power && controller && controller->power_suspend) { ++ controller->power_suspend(); ++ } ++ return 0; ++} ++ ++static int openvfd_driver_resume(struct platform_device *dev) ++{ ++ pr_dbg("openvfd_driver_resume"); ++ if (vfd_display_auto_power && controller && controller->power_resume) { ++ controller->power_resume(); ++ } ++ return 0; ++} ++ ++#ifdef CONFIG_OF ++static const struct of_device_id openvfd_dt_match[] = { ++ {.compatible = "open,vfd",}, ++ {}, ++}; ++#else ++#define openvfd_dt_match NULL ++#endif ++ ++static struct platform_driver openvfd_driver = { ++ .probe = openvfd_driver_probe, ++ .remove = openvfd_driver_remove, ++ .suspend = openvfd_driver_suspend, ++ .shutdown = openvfd_driver_shutdown, ++ .resume = openvfd_driver_resume, ++ .driver = { ++ .name = DEV_NAME, ++ .owner = THIS_MODULE, ++ .of_match_table = openvfd_dt_match, ++ }, ++}; ++ ++static int __init openvfd_driver_init(void) ++{ ++ pr_dbg("OpenVFD Driver init.\n"); ++ mutex_init(&mutex); ++ return platform_driver_register(&openvfd_driver); ++} ++ ++static void __exit openvfd_driver_exit(void) ++{ ++ pr_dbg("OpenVFD Driver exit.\n"); ++ mutex_destroy(&mutex); ++ platform_driver_unregister(&openvfd_driver); ++} ++ ++module_init(openvfd_driver_init); ++module_exit(openvfd_driver_exit); ++ ++MODULE_AUTHOR("Arthur Liberman"); ++MODULE_DESCRIPTION("OpenVFD Driver"); ++MODULE_LICENSE("GPL"); +diff -ruN main/drivers/auxdisplay/openvfd/openvfd_drv.h mod/drivers/auxdisplay/openvfd/openvfd_drv.h +--- main/drivers/auxdisplay/openvfd/openvfd_drv.h 1970-01-01 01:00:00.000000000 +0100 ++++ mod/drivers/auxdisplay/openvfd/openvfd_drv.h 2023-03-07 09:42:01.441532668 +0100 +@@ -0,0 +1,302 @@ ++#ifndef __OPENVFD_DRV_H__ ++#define __OPENVFD_DRV_H__ ++ ++#ifdef MODULE ++#include ++#include ++#include ++#endif ++#include "glyphs.h" ++ ++#ifdef MODULE ++#if 0 ++#define pr_dbg(args...) printk(KERN_ALERT "OpenVFD: " args) ++#else ++#define pr_dbg(args...) ++#endif ++#endif ++ ++#define pr_error(args...) printk(KERN_ALERT "OpenVFD: " args) ++#define pr_dbg2(args...) printk(KERN_DEBUG "OpenVFD: " args) ++ ++#ifndef CONFIG_OF ++#define CONFIG_OF ++#endif ++ ++#ifndef TRUE ++#define TRUE 1 ++#endif ++ ++#ifndef FALSE ++#define FALSE 0 ++#endif ++ ++#define OPENVFD_DRIVER_VERSION "V1.4.2" ++ ++/* ++ * Ioctl definitions ++ */ ++ ++/* Use 'M' as magic number */ ++#define VFD_IOC_MAGIC 'M' ++#define VFD_IOC_SMODE _IOW(VFD_IOC_MAGIC, 1, int) ++#define VFD_IOC_GMODE _IOR(VFD_IOC_MAGIC, 2, int) ++#define VFD_IOC_SBRIGHT _IOW(VFD_IOC_MAGIC, 3, int) ++#define VFD_IOC_GBRIGHT _IOR(VFD_IOC_MAGIC, 4, int) ++#define VFD_IOC_POWER _IOW(VFD_IOC_MAGIC, 5, int) ++#define VFD_IOC_GVER _IOR(VFD_IOC_MAGIC, 6, int) ++#define VFD_IOC_STATUS_LED _IOW(VFD_IOC_MAGIC, 7, int) ++#define VFD_IOC_GDISPLAY_TYPE _IOR(VFD_IOC_MAGIC, 8, int) ++#define VFD_IOC_SDISPLAY_TYPE _IOW(VFD_IOC_MAGIC, 9, int) ++#define VFD_IOC_SCHARS_ORDER _IOW(VFD_IOC_MAGIC, 10, u_int8[7]) ++#define VFD_IOC_USE_DTB_CONFIG _IOW(VFD_IOC_MAGIC, 11, int) ++#define VFD_IOC_MAXNR 12 ++ ++#ifdef MODULE ++ ++#define MOD_NAME_CLK "openvfd_gpio_clk" ++#define MOD_NAME_DAT "openvfd_gpio_dat" ++#define MOD_NAME_STB "openvfd_gpio_stb" ++#define MOD_NAME_GPIO0 "openvfd_gpio0" ++#define MOD_NAME_GPIO1 "openvfd_gpio1" ++#define MOD_NAME_GPIO2 "openvfd_gpio2" ++#define MOD_NAME_GPIO3 "openvfd_gpio3" ++#define MOD_NAME_PROT "openvfd_gpio_protocol" ++#define MOD_NAME_CHARS "openvfd_chars" ++#define MOD_NAME_DOTS "openvfd_dot_bits" ++#define MOD_NAME_TYPE "openvfd_display_type" ++ ++#endif ++ ++#define DEV_NAME "openvfd" ++ ++struct vfd_display { ++ u_int8 type; ++ u_int8 reserved; ++ u_int8 flags; ++ u_int8 controller; ++}; ++ ++#ifdef MODULE ++ ++struct vfd_dtb_config { ++ u_int8 dat_index[7]; ++ u_int8 led_dots[8]; ++ struct vfd_display display; ++}; ++ ++struct vfd_pin { ++ int pin; ++ union { ++ struct { ++ u_int8 active_low : 1; ++ u_int8 single_ended : 1; ++ u_int8 open_drain : 1; ++ u_int8 sleep_keep : 1; ++ u_int8 pullup_on : 1; ++ u_int8 pulldown_on : 1; ++ u_int8 kick_high : 1; ++ u_int8 kick_low : 1; ++ u_int8 reserved2; ++ u_int8 reserved3; ++ u_int8 reserved4 : 7; ++ u_int8 is_requested : 1; ++ } bits; ++ unsigned int value; ++ } flags; ++}; ++ ++struct vfd_protocol { ++ u_int8 protocol; ++ u_int8 device_id; ++}; ++ ++struct vfd_dev { ++ struct vfd_pin clk_pin; ++ struct vfd_pin dat_pin; ++ struct vfd_pin stb_pin; ++ struct vfd_pin gpio0_pin; ++ struct vfd_pin gpio1_pin; ++ struct vfd_pin gpio2_pin; ++ struct vfd_pin gpio3_pin; ++ struct vfd_protocol hw_protocol; ++ u_int16 wbuf[7]; ++ struct vfd_dtb_config dtb_active; ++ struct vfd_dtb_config dtb_default; ++ u_int8 mode; ++ u_int8 power; ++ u_int8 brightness; ++ struct mutex *mutex; ++ wait_queue_head_t kb_waitq; /* read and write queues */ ++ struct timer_list timer; ++ int key_respond_status; ++ int Keyboard_diskstatus; ++ u_int8 KeyPressCnt; ++ u_int8 key_fg; ++ u_int8 key_val; ++ u_int8 status_led_mask; /* Indicators mask */ ++}; ++ ++struct vfd_platform_data { ++ struct vfd_dev *dev; ++}; ++ ++#endif ++ ++struct vfd_display_data { ++ u_int16 mode; ++ u_int8 colon_on; ++ u_int8 temperature; ++ ++ struct { ++ u_int8 seconds; ++ u_int8 minutes; ++ u_int8 hours; ++ u_int8 day_of_week; ++ u_int8 day; ++ u_int8 month; ++ u_int16 year; ++ } time_date; ++ struct { ++ u_int8 seconds; ++ u_int8 minutes; ++ u_int8 hours; ++ u_int8 _reserved; ++ } time_secondary; ++ struct { ++ u_int16 channel; ++ u_int16 channel_count; ++ } channel_data; ++ ++ char string_main[512]; ++ char string_secondary[128]; ++}; ++ ++enum { ++ PROTOCOL_NONE, ++ PROTOCOL_I2C, ++ PROTOCOL_MAX ++}; ++ ++enum { ++ DISPLAY_MODE_NONE, ++ DISPLAY_MODE_CLOCK, ++ DISPLAY_MODE_CHANNEL, ++ DISPLAY_MODE_PLAYBACK_TIME, ++ DISPLAY_MODE_TITLE, ++ DISPLAY_MODE_TEMPERATURE, ++ DISPLAY_MODE_DATE, ++ DISPLAY_MODE_MAX, ++}; ++ ++enum { ++ CONTROLLER_FD628 = 0x00, ++ CONTROLLER_FD620, ++ CONTROLLER_TM1618, ++ CONTROLLER_FD650, ++ CONTROLLER_HBS658, ++ CONTROLLER_FD655, ++ CONTROLLER_FD6551, ++ CONTROLLER_7S_MAX, ++ CONTROLLER_IL3829 = 0xFA, ++ CONTROLLER_PCD8544, ++ CONTROLLER_SH1106, ++ CONTROLLER_SSD1306, ++ CONTROLLER_HD44780, ++}; ++ ++enum { ++ DISPLAY_TYPE_5D_7S_NORMAL, // T95U ++ DISPLAY_TYPE_5D_7S_T95, // T95K is different. ++ DISPLAY_TYPE_5D_7S_X92, ++ DISPLAY_TYPE_5D_7S_ABOX, ++ DISPLAY_TYPE_FD620_REF, ++ DISPLAY_TYPE_4D_7S_COL, ++ DISPLAY_TYPE_5D_7S_M9_PRO, ++ DISPLAY_TYPE_5D_7S_G9SX, ++ DISPLAY_TYPE_4D_7S_FREESATGTC, ++ DISPLAY_TYPE_5D_7S_TAP1, ++ DISPLAY_TYPE_MAX, ++}; ++ ++#define DISPLAY_FLAG_TRANSPOSED 0x01 ++#define DISPLAY_FLAG_TRANSPOSED_INT 0x00010000 ++#define DISPLAY_FLAG_LOW_FREQ 0x40 ++#define DISPLAY_FLAG_LOW_FREQ_INT 0x00400000 ++ ++enum { ++ LED_DOT1_ALARM, ++ LED_DOT1_USB, ++ LED_DOT1_PLAY, ++ LED_DOT1_PAUSE, ++ LED_DOT1_SEC, ++ LED_DOT1_ETH, ++ LED_DOT1_WIFI, ++ LED_DOT1_MAX ++}; ++ ++enum { ++ LED_DOT2_APPS, ++ LED_DOT2_SETUP, ++ LED_DOT2_USB, ++ LED_DOT2_CARD, ++ LED_DOT2_SEC, ++ LED_DOT2_HDMI, ++ LED_DOT2_CVBS, ++ LED_DOT2_MAX ++}; ++ ++enum { ++ LED_DOT3_UNUSED1, ++ LED_DOT3_UNUSED2, ++ LED_DOT3_POWER, ++ LED_DOT3_LAN, ++ LED_DOT3_SEC, ++ LED_DOT3_WIFIHI, ++ LED_DOT3_WIFILO, ++ LED_DOT3_MAX ++}; ++ ++enum { ++ LED_DOT4_BT, ++ LED_DOT4_ETH, ++ LED_DOT4_WIFI, ++ LED_DOT4_SPDIF, ++ LED_DOT4_SEC, ++ LED_DOT4_HDMI, ++ LED_DOT4_AV, ++ LED_DOT4_MAX ++}; ++ ++#define LED_DOT_SEC LED_DOT1_SEC ++#define LED_DOT_MAX LED_DOT1_MAX ++ ++static const u_int8 ledDots[LED_DOT_MAX] = { ++ 0x01, ++ 0x02, ++ 0x04, ++ 0x08, ++ 0x10, ++ 0x20, ++ 0x40 ++}; ++ ++/* *************************************************************************************************************************************** * ++* Status Description | bit7 | bit6 | bit5 | bit4 | bit3 | bit2 | bit1 | bit0 | Display_EN: Display enable bit, 1: Turn on display; 0: Turn off display ++* | 0 | 0 | 0 | 0 | Display_EN | brightness[3:0] | Brightness: display brightness control bits, 000 ~ 111 represents brightness of 1 (min) ~ 8 (max) ++* *************************************************************************************************************************************** */ ++#define FD628_DISP_ON 0x08 /* FD628 Display On */ ++#define FD628_DISP_OFF 0x00 /* FD628 Display Off */ ++ ++typedef enum _Brightness { /* FD628 Brightness levels */ ++ FD628_Brightness_1 = 0x00, ++ FD628_Brightness_2, ++ FD628_Brightness_3, ++ FD628_Brightness_4, ++ FD628_Brightness_5, ++ FD628_Brightness_6, ++ FD628_Brightness_7, ++ FD628_Brightness_8 ++}Brightness; ++ ++#endif +diff -ruN main/drivers/auxdisplay/openvfd/protocols/i2c_hw.c mod/drivers/auxdisplay/openvfd/protocols/i2c_hw.c +--- main/drivers/auxdisplay/openvfd/protocols/i2c_hw.c 1970-01-01 01:00:00.000000000 +0100 ++++ mod/drivers/auxdisplay/openvfd/protocols/i2c_hw.c 2023-03-07 09:42:01.681534529 +0100 +@@ -0,0 +1,161 @@ ++ ++#include ++#include ++#include ++ ++#include "i2c_hw.h" ++ ++#define pr_dbg2(args...) printk(KERN_DEBUG "OpenVFD: " args) ++#define LOW 0 ++#define HIGH 1 ++ ++static unsigned char i2c_hw_read_cmd_data(const unsigned char *cmd, unsigned short cmd_length, unsigned char *data, unsigned short data_length); ++static unsigned char i2c_hw_read_data(unsigned char *data, unsigned short length); ++static unsigned char i2c_hw_read_byte(unsigned char *bdata); ++static unsigned char i2c_hw_write_cmd_data(const unsigned char *cmd, unsigned short cmd_length, const unsigned char *data, unsigned short data_length); ++static unsigned char i2c_hw_write_data(const unsigned char *data, unsigned short length); ++static unsigned char i2c_hw_write_byte(unsigned char bdata); ++ ++static struct protocol_interface i2c_hw_interface = { ++ .read_cmd_data = i2c_hw_read_cmd_data, ++ .read_data = i2c_hw_read_data, ++ .read_byte = i2c_hw_read_byte, ++ .write_cmd_data = i2c_hw_write_cmd_data, ++ .write_data = i2c_hw_write_data, ++ .write_byte = i2c_hw_write_byte, ++ .protocol_type = PROTOCOL_TYPE_I2C ++}; ++ ++union address { ++ struct { ++ unsigned char low; ++ unsigned char high; ++ } nibbles; ++ unsigned short value; ++}; ++ ++static union address i2c_address = { 0 }; ++static struct i2c_adapter *i2c; ++static unsigned char use_address = 0; ++static unsigned short long_address_flag = 0; ++ ++static unsigned char i2c_hw_test_connection(void) ++{ ++ return i2c_hw_write_cmd_data(NULL, 0, NULL, 0); ++} ++ ++struct protocol_interface *init_hw_i2c(unsigned short _address, unsigned char _device_id) ++{ ++ struct protocol_interface *i2c_hw_ptr = NULL; ++ i2c = i2c_get_adapter(_device_id); ++ if (i2c) { ++ pr_dbg2("Found I2C-%d adapter: %s\n", _device_id , i2c->name); ++ if (_address) { ++ use_address = 1; ++ long_address_flag = _address > 0xFF ? I2C_M_TEN : 0; // A valid 10-bit address always starts with b11110. ++ i2c_address.value = _address == 0xFF ? 0x0000 : _address; // General call. ++ } else { ++ use_address = 0; ++ } ++ if (!i2c_hw_test_connection()) { ++ i2c_hw_ptr = &i2c_hw_interface; ++ pr_dbg2("HW I2C interface intialized (address = 0x%04X%s)\n", i2c_address.value, !use_address ? " (N/A)" : ""); ++ } else { ++ pr_dbg2("HW I2C interface failed to intialize. Could not establish communication with I2C slave\n"); ++ } ++ } else { ++ pr_dbg2("HW I2C interface failed to intialize. Could not get I2C-%d adapter\n", _device_id); ++ } ++ return i2c_hw_ptr; ++} ++ ++static int i2c_hw_writereg(unsigned char *data, unsigned short size) ++{ ++ int ret; ++ struct i2c_msg msg[1] = { ++ { ++ .addr = i2c_address.value, ++ .flags = long_address_flag, ++ .buf = data, ++ .len = size, ++ } ++ }; ++ ++ ret = i2c_transfer(i2c, msg, 1); ++ if (ret == 1) { ++ ret = 0; ++ } else { ++ dev_warn(&i2c->dev, "i2c wr failed=%d", ret); ++ ret = -EREMOTEIO; ++ } ++ ++ return ret; ++} ++ ++static int i2c_hw_readreg(unsigned char *data, unsigned short size) ++{ ++ int ret; ++ struct i2c_msg msg[1] = { ++ { ++ .addr = i2c_address.value, ++ .flags = I2C_M_RD | long_address_flag, ++ .buf = data, ++ .len = size, ++ } ++ }; ++ ++ ret = i2c_transfer(i2c, msg, 1); ++ if (ret == 1) { ++ ret = 0; ++ } else { ++ dev_warn(&i2c->dev, "i2c rd failed=%d", ret); ++ ret = -EREMOTEIO; ++ } ++ ++ return ret; ++} ++ ++static unsigned char i2c_hw_read_cmd_data(const unsigned char *cmd, unsigned short cmd_length, unsigned char *data, unsigned short data_length) ++{ ++ unsigned char status = 0; ++ ++ status = i2c_hw_readreg(data, data_length); ++ return status; ++} ++ ++static unsigned char i2c_hw_read_data(unsigned char *data, unsigned short length) ++{ ++ return i2c_hw_read_cmd_data(NULL, 0, data, length); ++} ++ ++static unsigned char i2c_hw_read_byte(unsigned char *bdata) ++{ ++ return i2c_hw_read_cmd_data(NULL, 0, bdata, 1); ++} ++ ++static unsigned char i2c_hw_write_cmd_data(const unsigned char *cmd, unsigned short cmd_length, const unsigned char *data, unsigned short data_length) ++{ ++ unsigned char status = 0; ++ unsigned short total_length = max(cmd_length + data_length, 4); ++ char *buf = kmalloc(total_length, GFP_KERNEL); ++ ++ if (cmd) ++ memcpy(buf, cmd, cmd_length); ++ ++ if (data) ++ memcpy(buf + cmd_length, data, data_length); ++ ++ status = i2c_hw_writereg(buf, cmd_length + data_length); ++ kfree(buf); ++ return status; ++} ++ ++static unsigned char i2c_hw_write_data(const unsigned char *data, unsigned short length) ++{ ++ return i2c_hw_write_cmd_data(NULL, 0, data, length); ++} ++ ++static unsigned char i2c_hw_write_byte(unsigned char bdata) ++{ ++ return i2c_hw_write_cmd_data(NULL, 0, &bdata, 1); ++} +diff -ruN main/drivers/auxdisplay/openvfd/protocols/i2c_hw.h mod/drivers/auxdisplay/openvfd/protocols/i2c_hw.h +--- main/drivers/auxdisplay/openvfd/protocols/i2c_hw.h 1970-01-01 01:00:00.000000000 +0100 ++++ mod/drivers/auxdisplay/openvfd/protocols/i2c_hw.h 2023-03-07 09:42:01.701534684 +0100 +@@ -0,0 +1,8 @@ ++#ifndef __I2C_HW_H__ ++#define __I2C_HW_H__ ++ ++#include "protocol.h" ++ ++struct protocol_interface *init_hw_i2c(unsigned short _address, unsigned char _device_id); ++ ++#endif +diff -ruN main/drivers/auxdisplay/openvfd/protocols/i2c_sw.c mod/drivers/auxdisplay/openvfd/protocols/i2c_sw.c +--- main/drivers/auxdisplay/openvfd/protocols/i2c_sw.c 1970-01-01 01:00:00.000000000 +0100 ++++ mod/drivers/auxdisplay/openvfd/protocols/i2c_sw.c 2023-03-07 09:42:01.709534746 +0100 +@@ -0,0 +1,257 @@ ++#include ++#include ++#include "i2c_sw.h" ++ ++#define pr_dbg2(args...) printk(KERN_DEBUG "OpenVFD: " args) ++#define LOW 0 ++#define HIGH 1 ++ ++static unsigned char i2c_sw_read_cmd_data(const unsigned char *cmd, unsigned short cmd_length, unsigned char *data, unsigned short data_length); ++static unsigned char i2c_sw_read_data(unsigned char *data, unsigned short length); ++static unsigned char i2c_sw_read_byte(unsigned char *bdata); ++static unsigned char i2c_sw_write_cmd_data(const unsigned char *cmd, unsigned short cmd_length, const unsigned char *data, unsigned short data_length); ++static unsigned char i2c_sw_write_data(const unsigned char *data, unsigned short length); ++static unsigned char i2c_sw_write_byte(unsigned char bdata); ++ ++static struct protocol_interface i2c_sw_interface = { ++ .read_cmd_data = i2c_sw_read_cmd_data, ++ .read_data = i2c_sw_read_data, ++ .read_byte = i2c_sw_read_byte, ++ .write_cmd_data = i2c_sw_write_cmd_data, ++ .write_data = i2c_sw_write_data, ++ .write_byte = i2c_sw_write_byte, ++ .protocol_type = PROTOCOL_TYPE_I2C ++}; ++ ++union address { ++ struct { ++ unsigned char low; ++ unsigned char high; ++ } nibbles; ++ unsigned short value; ++}; ++ ++static void i2c_sw_stop_condition(void); ++ ++static union address i2c_sw_address = { 0 }; ++static unsigned char use_address = 0; ++static unsigned char long_address = 0; ++static unsigned long i2c_sw_delay = I2C_DELAY_100KHz; ++static unsigned char lsb_first = 0; ++static unsigned short clk_stretch_timeout = 0; ++static struct vfd_pin pin_scl = { 0 }; ++static struct vfd_pin pin_sda = { 0 }; ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,0,0) ++inline void gpio_set_pullup(unsigned gpio, int value) ++{ ++ gpio_direction_input(gpio); ++ gpio_set_value(gpio, value); ++} ++#endif ++ ++static unsigned char i2c_sw_test_connection(const struct protocol_interface *protocol) ++{ ++ return i2c_sw_write_cmd_data(NULL, 0, NULL, 0); ++} ++ ++struct protocol_interface *init_sw_i2c(unsigned short _address, unsigned char _lsb_first, unsigned char _clock_stretch_support, struct vfd_pin _pin_scl, struct vfd_pin _pin_sda, unsigned long _i2c_sw_delay, unsigned char(*test_connection)(const struct protocol_interface *protocol)) ++{ ++ struct protocol_interface *i2c_sw_ptr = NULL; ++ if (_pin_scl.pin >= 0 && _pin_sda.pin >= 0) { ++ if (_address) { ++ use_address = 1; ++ long_address = _address > 0xFF; // A valid 10-bit address always starts with b11110. ++ i2c_sw_address.value = _address == 0xFF ? 0x0000 : _address; // General call. ++ } else { ++ use_address = 0; ++ } ++ lsb_first = _lsb_first; ++ pin_scl = _pin_scl; ++ pin_sda = _pin_sda; ++ i2c_sw_delay = _i2c_sw_delay; ++ clk_stretch_timeout = _clock_stretch_support ? (10 * _i2c_sw_delay) : 0; ++ if (_pin_scl.flags.bits.pullup_on) ++ gpio_set_pullup(_pin_scl.pin, 1); ++ if (_pin_sda.flags.bits.pullup_on) ++ gpio_set_pullup(_pin_sda.pin, 1); ++ i2c_sw_stop_condition(); ++ if (!test_connection) ++ test_connection = i2c_sw_test_connection; ++ if (!test_connection(&i2c_sw_interface)) { ++ i2c_sw_ptr = &i2c_sw_interface; ++ pr_dbg2("SW I2C interface intialized (address = 0x%04X%s, %s mode, pull-ups %s)\n", i2c_sw_address.value, !use_address ? " (N/A)" : "", ++ lsb_first ? "LSB" : "MSB", _pin_scl.flags.bits.pullup_on ? "on" : "off" ); ++ } else { ++ pr_dbg2("SW I2C interface failed to intialize. Could not establish communication with I2C slave\n"); ++ } ++ } else { ++ pr_dbg2("SW I2C interface failed to intialize. Invalid SCL (%d) and/or SDA (%d) pins\n", _pin_scl.pin, _pin_sda.pin); ++ } ++ return i2c_sw_ptr; ++} ++ ++static inline void gpio_set_pin_low(const struct vfd_pin *pin) ++{ ++ gpio_direction_output(pin->pin, LOW); ++} ++ ++static inline void gpio_set_pin_high(const struct vfd_pin *pin) ++{ ++ if (pin->flags.bits.kick_high) ++ gpio_direction_output(pin->pin, HIGH); ++ gpio_direction_input(pin->pin); ++} ++ ++static void i2c_sw_start_condition(void) ++{ ++ gpio_set_pin_low(&pin_sda); ++ udelay(i2c_sw_delay); ++ gpio_set_pin_low(&pin_scl); ++ udelay(i2c_sw_delay); ++} ++ ++static void i2c_sw_stop_condition(void) ++{ ++ gpio_set_pin_high(&pin_scl); ++ udelay(i2c_sw_delay); ++ gpio_set_pin_high(&pin_sda); ++ udelay(i2c_sw_delay); ++ udelay(i2c_sw_delay); ++} ++ ++static inline unsigned char i2c_sw_ack(void) ++{ ++ unsigned char ret = 1, scl = 1; ++ unsigned short timeout = clk_stretch_timeout; ++ gpio_set_pin_low(&pin_scl); ++ gpio_set_pin_high(&pin_sda); ++ udelay(i2c_sw_delay); ++ gpio_set_pin_high(&pin_scl); ++ udelay(i2c_sw_delay); ++ if (timeout) { ++ do { ++ scl = gpio_get_value(pin_scl.pin) ? 1 : 0; ++ udelay(1); ++ } while (!scl && timeout--); ++ ret = gpio_get_value(pin_sda.pin) ? 1 : 0; ++ } else { ++ ret = 0; ++ } ++ gpio_set_pin_low(&pin_scl); ++ gpio_set_pin_low(&pin_sda); ++ udelay(i2c_sw_delay); ++ return ret; ++} ++ ++static unsigned char i2c_sw_write_raw_byte(unsigned char data) ++{ ++ unsigned char i = 8; ++ unsigned char mask = lsb_first ? 0x01 : 0x80; ++ gpio_set_pin_low(&pin_scl); ++ while (i--) { ++ if (data & mask) ++ gpio_set_pin_high(&pin_sda); ++ else ++ gpio_set_pin_low(&pin_sda); ++ udelay(i2c_sw_delay); ++ gpio_set_pin_high(&pin_scl); ++ udelay(i2c_sw_delay); ++ gpio_set_pin_low(&pin_scl); ++ if (lsb_first) ++ data >>= 1; ++ else ++ data <<= 1; ++ } ++ return i2c_sw_ack(); ++} ++ ++static unsigned char i2c_sw_read_raw_byte(unsigned char *data) ++{ ++ unsigned char i = 8; ++ unsigned char mask = lsb_first ? 0x80 : 0x01; ++ *data = 0; ++ gpio_set_pin_high(&pin_sda); ++ while (i--) { ++ if (lsb_first) ++ *data >>= 1; ++ else ++ *data <<= 1; ++ gpio_set_pin_high(&pin_scl); ++ udelay(i2c_sw_delay); ++ if (gpio_get_value(pin_sda.pin)) ++ *data |= mask; ++ gpio_set_pin_low(&pin_scl); ++ udelay(i2c_sw_delay); ++ } ++ return i2c_sw_ack(); ++} ++ ++static unsigned char i2c_sw_write_address(union address _address, unsigned char rw) ++{ ++ unsigned char ret = 0; ++ if (long_address) { ++ _address.nibbles.high <<= 1; ++ _address.nibbles.high |= rw ? 0x01 : 0x00; ++ ret = i2c_sw_write_raw_byte(_address.nibbles.high); ++ if (!ret) ++ ret = i2c_sw_write_raw_byte(_address.nibbles.low); ++ } else { ++ _address.nibbles.low <<= 1; ++ _address.nibbles.low |= rw ? 0x01 : 0x00; ++ ret = i2c_sw_write_raw_byte(_address.nibbles.low); ++ } ++ return ret; ++} ++ ++static unsigned char i2c_sw_read_cmd_data(const unsigned char *cmd, unsigned short cmd_length, unsigned char *data, unsigned short data_length) ++{ ++ unsigned char status = 0; ++ i2c_sw_start_condition(); ++ if (use_address) ++ status = i2c_sw_write_address(i2c_sw_address, 1); ++ if (cmd) { ++ while (!status && cmd_length--) ++ status |= i2c_sw_write_raw_byte(*cmd++); ++ } ++ while (!status && data_length--) ++ status |= i2c_sw_read_raw_byte(data++); ++ i2c_sw_stop_condition(); ++ return status; ++} ++ ++static unsigned char i2c_sw_read_data(unsigned char *data, unsigned short length) ++{ ++ return i2c_sw_read_cmd_data(NULL, 0, data, length); ++} ++ ++static unsigned char i2c_sw_read_byte(unsigned char *bdata) ++{ ++ return i2c_sw_read_cmd_data(NULL, 0, bdata, 1); ++} ++ ++static unsigned char i2c_sw_write_cmd_data(const unsigned char *cmd, unsigned short cmd_length, const unsigned char *data, unsigned short data_length) ++{ ++ unsigned char status = 0; ++ i2c_sw_start_condition(); ++ if (use_address) ++ status = i2c_sw_write_address(i2c_sw_address, 0); ++ if (cmd) { ++ while (!status && cmd_length--) ++ status |= i2c_sw_write_raw_byte(*cmd++); ++ } ++ while (!status && data_length--) ++ status |= i2c_sw_write_raw_byte(*data++); ++ i2c_sw_stop_condition(); ++ return status; ++} ++ ++static unsigned char i2c_sw_write_data(const unsigned char *data, unsigned short length) ++{ ++ return i2c_sw_write_cmd_data(NULL, 0, data, length); ++} ++ ++static unsigned char i2c_sw_write_byte(unsigned char bdata) ++{ ++ return i2c_sw_write_cmd_data(NULL, 0, &bdata, 1); ++} +diff -ruN main/drivers/auxdisplay/openvfd/protocols/i2c_sw.h mod/drivers/auxdisplay/openvfd/protocols/i2c_sw.h +--- main/drivers/auxdisplay/openvfd/protocols/i2c_sw.h 1970-01-01 01:00:00.000000000 +0100 ++++ mod/drivers/auxdisplay/openvfd/protocols/i2c_sw.h 2023-03-07 09:42:01.725534870 +0100 +@@ -0,0 +1,13 @@ ++#ifndef __I2C_SW_H__ ++#define __I2C_SW_H__ ++ ++#include "protocol.h" ++ ++#define I2C_DELAY_500KHz 1 ++#define I2C_DELAY_250KHz 2 ++#define I2C_DELAY_100KHz 5 ++#define I2C_DELAY_20KHz 25 ++ ++struct protocol_interface *init_sw_i2c(unsigned short address, unsigned char lsb_first, unsigned char clock_stretch_support, struct vfd_pin pin_scl, struct vfd_pin pin_sda, unsigned long i2c_delay, unsigned char(*test_connection)(const struct protocol_interface *protocol)); ++ ++#endif +diff -ruN main/drivers/auxdisplay/openvfd/protocols/protocol.h mod/drivers/auxdisplay/openvfd/protocols/protocol.h +--- main/drivers/auxdisplay/openvfd/protocols/protocol.h 1970-01-01 01:00:00.000000000 +0100 ++++ mod/drivers/auxdisplay/openvfd/protocols/protocol.h 2023-03-07 09:42:01.733534932 +0100 +@@ -0,0 +1,25 @@ ++#ifndef __PROTOCOLS__ ++#define __PROTOCOLS__ ++ ++#include "../openvfd_drv.h" ++ ++#define MSB_FIRST 0 ++#define LSB_FIRST 1 ++ ++enum protocol_types { ++ PROTOCOL_TYPE_I2C, ++ PROTOCOL_TYPE_SPI_3W, ++ PROTOCOL_TYPE_SPI_4W, ++}; ++ ++struct protocol_interface { ++ unsigned char (*read_cmd_data)(const unsigned char *cmd, unsigned short cmd_length, unsigned char *data, unsigned short data_length); ++ unsigned char (*read_data)(unsigned char *data, unsigned short length); ++ unsigned char (*read_byte)(unsigned char *bdata); ++ unsigned char (*write_cmd_data)(const unsigned char *cmd, unsigned short cmd_length, const unsigned char *data, unsigned short data_length); ++ unsigned char (*write_data)(const unsigned char *data, unsigned short length); ++ unsigned char (*write_byte)(unsigned char bdata); ++ enum protocol_types protocol_type; ++}; ++ ++#endif +diff -ruN main/drivers/auxdisplay/openvfd/protocols/spi_sw.c mod/drivers/auxdisplay/openvfd/protocols/spi_sw.c +--- main/drivers/auxdisplay/openvfd/protocols/spi_sw.c 1970-01-01 01:00:00.000000000 +0100 ++++ mod/drivers/auxdisplay/openvfd/protocols/spi_sw.c 2023-03-07 09:42:01.745535025 +0100 +@@ -0,0 +1,194 @@ ++#include ++#include "spi_sw.h" ++ ++#define pr_dbg2(args...) printk(KERN_DEBUG "OpenVFD: " args) ++#define LOW 0 ++#define HIGH 1 ++ ++static unsigned char spi_sw_read_cmd_data(const unsigned char *cmd, unsigned short cmd_length, unsigned char *data, unsigned short data_length); ++static unsigned char spi_sw_read_data(unsigned char *data, unsigned short length); ++static unsigned char spi_sw_read_byte(unsigned char *bdata); ++static unsigned char spi_sw_write_cmd_data(const unsigned char *cmd, unsigned short cmd_length, const unsigned char *data, unsigned short data_length); ++static unsigned char spi_sw_write_data(const unsigned char *data, unsigned short length); ++static unsigned char spi_sw_write_byte(unsigned char bdata); ++ ++static struct protocol_interface spi_sw_interface = { ++ .read_cmd_data = spi_sw_read_cmd_data, ++ .read_data = spi_sw_read_data, ++ .read_byte = spi_sw_read_byte, ++ .write_cmd_data = spi_sw_write_cmd_data, ++ .write_data = spi_sw_write_data, ++ .write_byte = spi_sw_write_byte, ++ .protocol_type = PROTOCOL_TYPE_SPI_3W ++}; ++ ++static void spi_sw_stop_condition(void); ++ ++static unsigned long spi_sw_delay = SPI_DELAY_100KHz; ++static unsigned char lsb_first = 0; ++static int pin_clk = 0; ++static int pin_do = 0; ++static int pin_stb = 0; ++static int pin_di = 0; ++ ++static struct protocol_interface *init_sw_spi(unsigned char _lsb_first, struct vfd_pin clk, struct vfd_pin dout, struct vfd_pin stb, const struct vfd_pin *din, unsigned long _spi_sw_delay) ++{ ++ struct protocol_interface *spi_sw_ptr = NULL; ++ if (clk.pin >= 0 && dout.pin >= 0 && stb.pin >= 0) { ++ pin_clk = clk.pin; ++ pin_do = dout.pin; ++ pin_stb = stb.pin; ++ lsb_first = _lsb_first; ++ spi_sw_delay = _spi_sw_delay; ++ if (!din) { ++ pin_di = pin_do; ++ spi_sw_interface.protocol_type = PROTOCOL_TYPE_SPI_3W; ++ spi_sw_ptr = &spi_sw_interface; ++ } else if (din->pin >= 0) { ++ pin_di = din->pin; ++ spi_sw_interface.protocol_type = PROTOCOL_TYPE_SPI_4W; ++ spi_sw_ptr = &spi_sw_interface; ++ } ++ if (spi_sw_ptr) ++ spi_sw_stop_condition(); ++ } ++ return spi_sw_ptr; ++} ++ ++struct protocol_interface *init_sw_spi_3w(unsigned char _lsb_first, struct vfd_pin clk, struct vfd_pin dat, struct vfd_pin stb, unsigned long _spi_sw_delay) ++{ ++ struct protocol_interface *spi_sw_3w_ptr = init_sw_spi(_lsb_first, clk, dat, stb, NULL, _spi_sw_delay); ++ if (spi_sw_3w_ptr) ++ pr_dbg2("SW SPI 3-wire interface intialized (%s mode)\n", lsb_first ? "LSB" : "MSB"); ++ else ++ pr_dbg2("SW SPI 3-wire interface failed to intialize. Invalid CLK (%d), DAT (%d) or STB (%d) pins\n", clk.pin, dat.pin, stb.pin); ++ return spi_sw_3w_ptr; ++} ++ ++struct protocol_interface *init_sw_spi_4w(unsigned char _lsb_first, struct vfd_pin clk, struct vfd_pin dout, struct vfd_pin din, struct vfd_pin stb, unsigned long _spi_sw_delay) ++{ ++ struct protocol_interface *spi_sw_4w_ptr = init_sw_spi(_lsb_first, clk, dout, stb, &din, _spi_sw_delay); ++ if (spi_sw_4w_ptr) ++ pr_dbg2("SW SPI 4-wire interface intialized (%s mode)\n", lsb_first ? "LSB" : "MSB"); ++ else ++ pr_dbg2("SW SPI 4-wire interface failed to intialize. Invalid CLK (%d), DOUT (%d), DIN (%d) or STB (%d) pins\n", clk.pin, dout.pin, din.pin, stb.pin); ++ return spi_sw_4w_ptr; ++} ++ ++static void spi_sw_start_condition(void) ++{ ++ gpio_direction_output(pin_stb, LOW); ++ udelay(spi_sw_delay); ++} ++ ++static void spi_sw_stop_condition(void) ++{ ++ gpio_direction_output(pin_clk, HIGH); ++ udelay(spi_sw_delay); ++ gpio_direction_output(pin_stb, HIGH); ++ gpio_direction_output(pin_do, HIGH); ++ gpio_direction_input(pin_do); ++ udelay(spi_sw_delay); ++} ++ ++static unsigned char spi_sw_write_raw_byte(unsigned char data) ++{ ++ unsigned char i = 8; ++ unsigned char mask = lsb_first ? 0x01 : 0x80; ++ while (i--) { ++ gpio_direction_output(pin_clk, LOW); ++ udelay(spi_sw_delay); ++ if (data & mask) ++ gpio_direction_output(pin_do, HIGH); ++ else ++ gpio_direction_output(pin_do, LOW); ++ gpio_direction_output(pin_clk, HIGH); ++ udelay(spi_sw_delay); ++ if (lsb_first) ++ data >>= 1; ++ else ++ data <<= 1; ++ } ++ return 0; ++} ++ ++static unsigned char spi_sw_read_raw_byte(unsigned char *data) ++{ ++ unsigned char i = 8; ++ unsigned char mask = lsb_first ? 0x80 : 0x01; ++ *data = 0; ++ gpio_direction_input(pin_di); ++ while (i--) { ++ if (lsb_first) ++ *data >>= 1; ++ else ++ *data <<= 1; ++ gpio_direction_output(pin_clk, LOW); ++ udelay(spi_sw_delay); ++ gpio_direction_output(pin_clk, HIGH); ++ udelay(spi_sw_delay); ++ if (gpio_get_value(pin_di)) ++ *data |= mask; ++ } ++ return 0; ++} ++ ++static unsigned char spi_sw_read_cmd_data(const unsigned char *cmd, unsigned short cmd_length, unsigned char *data, unsigned short data_length) ++{ ++ unsigned char status = 0; ++ spi_sw_start_condition(); ++ if (!status && cmd) { ++ while (cmd_length--) { ++ status |= spi_sw_write_raw_byte(*cmd); ++ cmd++; ++ } ++ } ++ if (!status) { ++ while (data_length--) { ++ status |= spi_sw_read_raw_byte(data); ++ data++; ++ } ++ } ++ spi_sw_stop_condition(); ++ return status; ++} ++ ++static unsigned char spi_sw_read_data(unsigned char *data, unsigned short length) ++{ ++ return spi_sw_read_cmd_data(NULL, 0, data, length); ++} ++ ++static unsigned char spi_sw_read_byte(unsigned char *bdata) ++{ ++ return spi_sw_read_cmd_data(NULL, 0, bdata, 1); ++} ++ ++static unsigned char spi_sw_write_cmd_data(const unsigned char *cmd, unsigned short cmd_length, const unsigned char *data, unsigned short data_length) ++{ ++ unsigned char status = 0; ++ spi_sw_start_condition(); ++ if (!status && cmd) { ++ while (cmd_length--) { ++ status |= spi_sw_write_raw_byte(*cmd); ++ cmd++; ++ } ++ } ++ if (!status) { ++ while (data_length--) { ++ status |= spi_sw_write_raw_byte(*data); ++ data++; ++ } ++ } ++ spi_sw_stop_condition(); ++ return status; ++} ++ ++static unsigned char spi_sw_write_data(const unsigned char *data, unsigned short length) ++{ ++ return spi_sw_write_cmd_data(NULL, 0, data, length); ++} ++ ++static unsigned char spi_sw_write_byte(unsigned char bdata) ++{ ++ return spi_sw_write_cmd_data(NULL, 0, &bdata, 1); ++} +diff -ruN main/drivers/auxdisplay/openvfd/protocols/spi_sw.h mod/drivers/auxdisplay/openvfd/protocols/spi_sw.h +--- main/drivers/auxdisplay/openvfd/protocols/spi_sw.h 1970-01-01 01:00:00.000000000 +0100 ++++ mod/drivers/auxdisplay/openvfd/protocols/spi_sw.h 2023-03-07 09:42:01.753535087 +0100 +@@ -0,0 +1,14 @@ ++#ifndef __SPI_SW_H__ ++#define __SPI_SW_H__ ++ ++#include "protocol.h" ++ ++#define SPI_DELAY_500KHz 1 ++#define SPI_DELAY_250KHz 2 ++#define SPI_DELAY_100KHz 5 ++#define SPI_DELAY_20KHz 25 ++ ++struct protocol_interface *init_sw_spi_3w(unsigned char lsb_first, struct vfd_pin clk, struct vfd_pin dat, struct vfd_pin stb, unsigned long _spi_delay); ++struct protocol_interface *init_sw_spi_4w(unsigned char lsb_first, struct vfd_pin clk, struct vfd_pin dout, struct vfd_pin din, struct vfd_pin stb, unsigned long _spi_delay); ++ ++#endif +diff -ruN main/drivers/auxdisplay/tm1628.c mod/drivers/auxdisplay/tm1628.c +--- main/drivers/auxdisplay/tm1628.c 1970-01-01 01:00:00.000000000 +0100 ++++ mod/drivers/auxdisplay/tm1628.c 2023-03-07 09:42:01.365532077 +0100 +@@ -0,0 +1,376 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++/* ++ * Titan Micro Electronics TM1628 LED controller ++ * ++ * Copyright (c) 2019 Andreas Färber ++ * Copyright (c) 2022 Heiner Kallweit ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define TM1628_CMD_DISPLAY_MODE (0 << 6) ++#define TM1628_DISPLAY_MODE_6_12 0x02 ++#define TM1628_DISPLAY_MODE_7_11 0x03 ++ ++#define TM1628_CMD_DATA (1 << 6) ++#define TM1628_DATA_TEST_MODE BIT(3) ++#define TM1628_DATA_FIXED_ADDR BIT(2) ++#define TM1628_DATA_WRITE_DATA 0x00 ++#define TM1628_DATA_READ_DATA 0x02 ++ ++#define TM1628_CMD_DISPLAY_CTRL (2 << 6) ++#define TM1628_DISPLAY_CTRL_DISPLAY_ON BIT(3) ++ ++#define TM1628_CMD_SET_ADDRESS (3 << 6) ++ ++#define TM1628_BRIGHTNESS_MAX 7 ++#define NUM_LED_SEGS 7 ++ ++/* Physical limits, depending on the mode the chip may support less */ ++#define MAX_GRID_SIZE 7 ++#define MAX_SEGMENT_NUM 16 ++ ++struct tm1628_led { ++ struct led_classdev leddev; ++ struct tm1628 *ctrl; ++ u32 grid; ++ u32 seg; ++}; ++ ++struct tm1628 { ++ struct spi_device *spi; ++ __le16 data[MAX_GRID_SIZE]; ++ struct mutex disp_lock; ++ char text[MAX_GRID_SIZE + 1]; ++ u8 segment_mapping[NUM_LED_SEGS]; ++ u8 grid[MAX_GRID_SIZE]; ++ int grid_size; ++ struct tm1628_led leds[]; ++}; ++ ++/* Command 1: Display Mode Setting */ ++static int tm1628_set_display_mode(struct spi_device *spi, u8 grid_mode) ++{ ++ const u8 cmd = TM1628_CMD_DISPLAY_MODE | grid_mode; ++ ++ return spi_write(spi, &cmd, 1); ++} ++ ++/* Command 3: Address Setting */ ++static int tm1628_set_address(struct spi_device *spi, u8 offset) ++{ ++ const u8 cmd = TM1628_CMD_SET_ADDRESS | (offset * sizeof(__le16)); ++ ++ return spi_write(spi, &cmd, 1); ++} ++ ++/* Command 2: Data Setting */ ++static int tm1628_write_data(struct spi_device *spi, unsigned int offset, ++ unsigned int len) ++{ ++ struct tm1628 *s = spi_get_drvdata(spi); ++ const u8 cmd = TM1628_CMD_DATA | TM1628_DATA_WRITE_DATA; ++ struct spi_transfer xfers[] = { ++ { ++ .tx_buf = &cmd, ++ .len = 1, ++ }, ++ { ++ .tx_buf = (__force void *)(s->data + offset), ++ .len = len * sizeof(__le16), ++ }, ++ }; ++ ++ if (offset + len > MAX_GRID_SIZE) { ++ dev_err(&spi->dev, "Invalid data address offset %u len %u\n", ++ offset, len); ++ return -EINVAL; ++ } ++ ++ tm1628_set_address(spi, offset); ++ ++ return spi_sync_transfer(spi, xfers, ARRAY_SIZE(xfers)); ++} ++ ++/* Command 4: Display Control */ ++static int tm1628_set_display_ctrl(struct spi_device *spi, bool on) ++{ ++ u8 cmd = TM1628_CMD_DISPLAY_CTRL | TM1628_BRIGHTNESS_MAX; ++ ++ if (on) ++ cmd |= TM1628_DISPLAY_CTRL_DISPLAY_ON; ++ ++ return spi_write(spi, &cmd, 1); ++} ++ ++static int tm1628_show_text(struct tm1628 *s) ++{ ++ static SEG7_CONVERSION_MAP(map_seg7, MAP_ASCII7SEG_ALPHANUM); ++ int msg_len, i, ret; ++ ++ msg_len = strlen(s->text); ++ ++ mutex_lock(&s->disp_lock); ++ ++ for (i = 0; i < s->grid_size; i++) { ++ int pos = s->grid[i] - 1; ++ int j, char7_raw, char7; ++ ++ if (i >= msg_len) { ++ s->data[pos] = 0; ++ continue; ++ } ++ ++ char7_raw = map_to_seg7(&map_seg7, s->text[i]); ++ ++ for (j = 0, char7 = 0; j < NUM_LED_SEGS; j++) { ++ if (char7_raw & BIT(j)) ++ char7 |= BIT(s->segment_mapping[j] - 1); ++ } ++ ++ s->data[pos] = cpu_to_le16(char7); ++ } ++ ++ ret = tm1628_write_data(s->spi, 0, s->grid_size); ++ ++ mutex_unlock(&s->disp_lock); ++ ++ return ret; ++} ++ ++static int tm1628_led_set_brightness(struct led_classdev *led_cdev, ++ enum led_brightness brightness) ++{ ++ struct tm1628_led *led = container_of(led_cdev, struct tm1628_led, leddev); ++ struct tm1628 *s = led->ctrl; ++ int ret, offset = led->grid - 1; ++ __le16 bit = cpu_to_le16(BIT(led->seg - 1)); ++ ++ mutex_lock(&s->disp_lock); ++ ++ if (brightness == LED_OFF) ++ s->data[offset] &= ~bit; ++ else ++ s->data[offset] |= bit; ++ ++ ret = tm1628_write_data(s->spi, offset, 1); ++ ++ mutex_unlock(&s->disp_lock); ++ ++ return ret; ++} ++ ++static enum led_brightness tm1628_led_get_brightness(struct led_classdev *led_cdev) ++{ ++ struct tm1628_led *led = container_of(led_cdev, struct tm1628_led, leddev); ++ struct tm1628 *s = led->ctrl; ++ int offset = led->grid - 1; ++ __le16 bit = cpu_to_le16(BIT(led->seg - 1)); ++ bool on; ++ ++ mutex_lock(&s->disp_lock); ++ on = s->data[offset] & bit; ++ mutex_unlock(&s->disp_lock); ++ ++ return on ? LED_ON : LED_OFF; ++} ++ ++static int tm1628_register_led(struct tm1628 *s, struct fwnode_handle *node, ++ u32 grid, u32 seg, struct tm1628_led *led) ++{ ++ struct device *dev = &s->spi->dev; ++ struct led_init_data init_data = { .fwnode = node }; ++ ++ led->ctrl = s; ++ led->grid = grid; ++ led->seg = seg; ++ led->leddev.max_brightness = LED_ON; ++ led->leddev.brightness_set_blocking = tm1628_led_set_brightness; ++ led->leddev.brightness_get = tm1628_led_get_brightness; ++ ++ return devm_led_classdev_register_ext(dev, &led->leddev, &init_data); ++} ++ ++static ssize_t display_text_show(struct device *dev, struct device_attribute *attr, ++ char *buf) ++{ ++ struct tm1628 *s = dev_get_drvdata(dev); ++ ++ return sysfs_emit(buf, "%s\n", s->text); ++} ++ ++static ssize_t display_text_store(struct device *dev, struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct tm1628 *s = dev_get_drvdata(dev); ++ int ret, i; ++ ++ for (i = 0; i < count && i < s->grid_size && isprint(buf[i]); i++) ++ s->text[i] = buf[i]; ++ ++ s->text[i] = '\0'; ++ ++ ret = tm1628_show_text(s); ++ if (ret < 0) ++ return ret; ++ ++ return count; ++} ++ ++static const DEVICE_ATTR_RW(display_text); ++ ++static int tm1628_spi_probe(struct spi_device *spi) ++{ ++ struct fwnode_handle *child; ++ unsigned int num_leds; ++ struct tm1628 *s; ++ int ret, i; ++ ++ num_leds = device_get_child_node_count(&spi->dev); ++ ++ s = devm_kzalloc(&spi->dev, struct_size(s, leds, num_leds), GFP_KERNEL); ++ if (!s) ++ return -ENOMEM; ++ ++ s->spi = spi; ++ spi_set_drvdata(spi, s); ++ ++ mutex_init(&s->disp_lock); ++ ++ /* According to TM1628 datasheet */ ++ msleep(200); ++ ++ /* Clear screen */ ++ ret = tm1628_write_data(spi, 0, MAX_GRID_SIZE); ++ if (ret) ++ return ret; ++ ++ /* For now we support 6x12 mode only. This should be sufficient for most use cases */ ++ ret = tm1628_set_display_mode(spi, TM1628_DISPLAY_MODE_6_12); ++ if (ret) ++ return ret; ++ ++ ret = tm1628_set_display_ctrl(spi, true); ++ if (ret) ++ return ret; ++ ++ num_leds = 0; ++ ++ if (!IS_REACHABLE(CONFIG_LEDS_CLASS)) ++ goto no_leds; ++ ++ device_for_each_child_node(&spi->dev, child) { ++ u32 reg[2]; ++ ++ ret = fwnode_property_read_u32_array(child, "reg", reg, 2); ++ if (ret) { ++ dev_err(&spi->dev, "Reading %s reg property failed (%d)\n", ++ fwnode_get_name(child), ret); ++ continue; ++ } ++ ++ if (reg[0] == 0 || reg[0] > MAX_GRID_SIZE) { ++ dev_err(&spi->dev, "Invalid grid %u at %s\n", ++ reg[0], fwnode_get_name(child)); ++ continue; ++ } ++ ++ if (reg[1] == 0 || reg[1] > MAX_SEGMENT_NUM) { ++ dev_err(&spi->dev, "Invalid segment %u at %s\n", ++ reg[1], fwnode_get_name(child)); ++ continue; ++ } ++ ++ ret = tm1628_register_led(s, child, reg[0], reg[1], s->leds + num_leds); ++ if (ret) { ++ dev_err(&spi->dev, "Failed to register LED %s (%d)\n", ++ fwnode_get_name(child), ret); ++ continue; ++ } ++ num_leds++; ++ } ++ ++no_leds: ++ ret = device_property_count_u8(&spi->dev, "titanmec,grid"); ++ if (ret < 1 || ret > MAX_GRID_SIZE) { ++ dev_err(&spi->dev, "Invalid display length (%d)\n", ret); ++ return -EINVAL; ++ } ++ ++ s->grid_size = ret; ++ ++ ret = device_property_read_u8_array(&spi->dev, "titanmec,grid", s->grid, s->grid_size); ++ if (ret < 0) ++ return ret; ++ ++ for (i = 0; i < s->grid_size; i++) { ++ if (s->grid[i] < 1 || s->grid[i] > s->grid_size) ++ return -EINVAL; ++ } ++ ++ ret = device_property_read_u8_array(&spi->dev, "titanmec,segment-mapping", ++ s->segment_mapping, NUM_LED_SEGS); ++ if (ret < 0) ++ return ret; ++ ++ for (i = 0; i < NUM_LED_SEGS; i++) { ++ if (s->segment_mapping[i] < 1 || s->segment_mapping[i] > MAX_SEGMENT_NUM) ++ return -EINVAL; ++ } ++ ++ ret = device_create_file(&spi->dev, &dev_attr_display_text); ++ if (ret) ++ return ret; ++ ++ dev_info(&spi->dev, "Configured display with %u digits and %u symbols\n", ++ s->grid_size, num_leds); ++ ++ return 0; ++} ++ ++static void tm1628_spi_remove(struct spi_device *spi) ++{ ++ device_remove_file(&spi->dev, &dev_attr_display_text); ++ tm1628_set_display_ctrl(spi, false); ++} ++ ++static void tm1628_spi_shutdown(struct spi_device *spi) ++{ ++ tm1628_set_display_ctrl(spi, false); ++} ++ ++static const struct of_device_id tm1628_spi_of_matches[] = { ++ { .compatible = "titanmec,tm1628" }, ++ {} ++}; ++MODULE_DEVICE_TABLE(of, tm1628_spi_of_matches); ++ ++static const struct spi_device_id tm1628_spi_id_table[] = { ++ { "tm1628" }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(spi, tm1628_spi_id_table); ++ ++static struct spi_driver tm1628_spi_driver = { ++ .probe = tm1628_spi_probe, ++ .remove = tm1628_spi_remove, ++ .shutdown = tm1628_spi_shutdown, ++ .id_table = tm1628_spi_id_table, ++ ++ .driver = { ++ .name = "tm1628", ++ .of_match_table = tm1628_spi_of_matches, ++ }, ++}; ++module_spi_driver(tm1628_spi_driver); ++ ++MODULE_DESCRIPTION("TM1628 LED controller driver"); ++MODULE_AUTHOR("Andreas Färber "); ++MODULE_AUTHOR("Heiner Kallweit "); ++MODULE_LICENSE("GPL");